@open-mercato/core 0.6.7-develop.6552.1.5208a19369 → 0.6.7-develop.6565.1.1026d85fff
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/attachments/lib/reconcileOrganization.js +9 -7
- package/dist/modules/attachments/lib/reconcileOrganization.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/people/route.js +2 -2
- package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/companies/route.js +2 -2
- package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +4 -4
- package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
- package/dist/modules/customers/api/entity-roles-factory.js +3 -3
- package/dist/modules/customers/api/entity-roles-factory.js.map +2 -2
- package/dist/modules/customers/api/labels/assign/route.js +2 -2
- package/dist/modules/customers/api/labels/assign/route.js.map +2 -2
- package/dist/modules/customers/api/labels/unassign/route.js +2 -2
- package/dist/modules/customers/api/labels/unassign/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +3 -7
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/context.js +3 -3
- package/dist/modules/customers/api/people/[id]/companies/context.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
- package/dist/modules/customers/api/todos/route.js +2 -2
- package/dist/modules/customers/api/todos/route.js.map +2 -2
- package/dist/modules/customers/commands/addresses.js +3 -3
- package/dist/modules/customers/commands/addresses.js.map +2 -2
- package/dist/modules/customers/commands/comments.js +3 -3
- package/dist/modules/customers/commands/comments.js.map +2 -2
- package/dist/modules/customers/commands/companies.js +2 -2
- package/dist/modules/customers/commands/companies.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +3 -3
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/dictionaries.js +3 -3
- package/dist/modules/customers/commands/dictionaries.js.map +2 -2
- package/dist/modules/customers/commands/entity-roles.js +3 -3
- package/dist/modules/customers/commands/entity-roles.js.map +2 -2
- package/dist/modules/customers/commands/interactions.js +6 -6
- package/dist/modules/customers/commands/interactions.js.map +2 -2
- package/dist/modules/customers/commands/labels.js +7 -7
- package/dist/modules/customers/commands/labels.js.map +2 -2
- package/dist/modules/customers/commands/people.js +3 -3
- package/dist/modules/customers/commands/people.js.map +2 -2
- package/dist/modules/customers/commands/personCompanyLinks.js +6 -6
- package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
- package/dist/modules/customers/commands/pipeline-stages.js +3 -3
- package/dist/modules/customers/commands/pipeline-stages.js.map +2 -2
- package/dist/modules/customers/commands/pipelines.js +3 -3
- package/dist/modules/customers/commands/pipelines.js.map +2 -2
- package/dist/modules/customers/commands/shared.js +3 -3
- package/dist/modules/customers/commands/shared.js.map +2 -2
- package/dist/modules/customers/commands/tags.js +7 -7
- package/dist/modules/customers/commands/tags.js.map +2 -2
- package/dist/modules/customers/commands/todos.js +3 -3
- package/dist/modules/customers/commands/todos.js.map +2 -2
- package/dist/modules/customers/lib/personCompanies.js +4 -4
- package/dist/modules/customers/lib/personCompanies.js.map +2 -2
- package/dist/modules/perspectives/data/validators.js +4 -0
- package/dist/modules/perspectives/data/validators.js.map +2 -2
- package/dist/modules/sales/api/notes/route.js +2 -4
- package/dist/modules/sales/api/notes/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/accept/route.js +2 -2
- package/dist/modules/sales/api/quotes/accept/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/public/[token]/route.js +3 -7
- package/dist/modules/sales/api/quotes/public/[token]/route.js.map +2 -2
- package/dist/modules/sales/api/quotes/send/route.js +2 -2
- package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
- package/dist/modules/sales/api/returns/[id]/route.js +2 -2
- package/dist/modules/sales/api/returns/[id]/route.js.map +2 -2
- package/dist/modules/sales/commands/configuration.js +11 -11
- package/dist/modules/sales/commands/configuration.js.map +2 -2
- package/dist/modules/sales/commands/documentAddresses.js +3 -3
- package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
- package/dist/modules/sales/commands/documents.js +31 -39
- package/dist/modules/sales/commands/documents.js.map +2 -2
- package/dist/modules/sales/commands/notes.js +7 -7
- package/dist/modules/sales/commands/notes.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +2 -2
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/dist/modules/sales/commands/returns.js +8 -8
- package/dist/modules/sales/commands/returns.js.map +2 -2
- package/dist/modules/sales/commands/shared.js +2 -2
- package/dist/modules/sales/commands/shared.js.map +2 -2
- package/dist/modules/sales/commands/shipments.js +5 -5
- package/dist/modules/sales/commands/shipments.js.map +2 -2
- package/dist/modules/sales/commands/statuses.js +2 -2
- package/dist/modules/sales/commands/statuses.js.map +2 -2
- package/dist/modules/sales/commands/tags.js +3 -3
- package/dist/modules/sales/commands/tags.js.map +2 -2
- package/dist/modules/sales/lib/calculations.js +6 -0
- package/dist/modules/sales/lib/calculations.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/attachments/lib/reconcileOrganization.ts +16 -7
- package/src/modules/customer_accounts/i18n/de.json +12 -0
- package/src/modules/customer_accounts/i18n/en.json +12 -0
- package/src/modules/customer_accounts/i18n/es.json +34 -22
- package/src/modules/customer_accounts/i18n/pl.json +32 -20
- package/src/modules/customers/api/companies/[id]/people/route.ts +2 -2
- package/src/modules/customers/api/deals/[id]/companies/route.ts +2 -2
- package/src/modules/customers/api/deals/[id]/people/route.ts +2 -2
- package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +4 -4
- package/src/modules/customers/api/entity-roles-factory.ts +3 -3
- package/src/modules/customers/api/labels/assign/route.ts +2 -2
- package/src/modules/customers/api/labels/unassign/route.ts +2 -2
- package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +3 -7
- package/src/modules/customers/api/people/[id]/companies/context.ts +3 -3
- package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +2 -2
- package/src/modules/customers/api/todos/route.ts +2 -2
- package/src/modules/customers/commands/addresses.ts +3 -3
- package/src/modules/customers/commands/comments.ts +3 -3
- package/src/modules/customers/commands/companies.ts +2 -2
- package/src/modules/customers/commands/deals.ts +3 -3
- package/src/modules/customers/commands/dictionaries.ts +3 -3
- package/src/modules/customers/commands/entity-roles.ts +3 -3
- package/src/modules/customers/commands/interactions.ts +6 -6
- package/src/modules/customers/commands/labels.ts +7 -7
- package/src/modules/customers/commands/people.ts +3 -3
- package/src/modules/customers/commands/personCompanyLinks.ts +6 -6
- package/src/modules/customers/commands/pipeline-stages.ts +3 -3
- package/src/modules/customers/commands/pipelines.ts +3 -3
- package/src/modules/customers/commands/shared.ts +3 -3
- package/src/modules/customers/commands/tags.ts +7 -7
- package/src/modules/customers/commands/todos.ts +3 -3
- package/src/modules/customers/lib/personCompanies.ts +4 -4
- package/src/modules/perspectives/data/validators.ts +4 -0
- package/src/modules/sales/api/notes/route.ts +2 -4
- package/src/modules/sales/api/quotes/accept/route.ts +2 -2
- package/src/modules/sales/api/quotes/public/[token]/route.ts +3 -7
- package/src/modules/sales/api/quotes/send/route.ts +2 -2
- package/src/modules/sales/api/returns/[id]/route.ts +2 -2
- package/src/modules/sales/commands/configuration.ts +11 -11
- package/src/modules/sales/commands/documentAddresses.ts +3 -3
- package/src/modules/sales/commands/documents.ts +23 -31
- package/src/modules/sales/commands/notes.ts +7 -7
- package/src/modules/sales/commands/payments.ts +2 -2
- package/src/modules/sales/commands/returns.ts +8 -8
- package/src/modules/sales/commands/shared.ts +2 -2
- package/src/modules/sales/commands/shipments.ts +5 -5
- package/src/modules/sales/commands/statuses.ts +2 -2
- package/src/modules/sales/commands/tags.ts +3 -3
- package/src/modules/sales/lib/calculations.ts +15 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
2
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
2
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
3
3
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
4
4
|
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
5
5
|
import {
|
|
@@ -35,7 +35,7 @@ export async function loadPersonContext(req: Request, personId: string) {
|
|
|
35
35
|
)
|
|
36
36
|
|
|
37
37
|
if (!person) {
|
|
38
|
-
throw
|
|
38
|
+
throw notFound(translate('customers.errors.person_not_found', 'Person not found'))
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
if (!isOrganizationReadAccessAllowed({ scope, auth: authenticatedAuth, organizationId: person.organizationId })) {
|
|
@@ -53,7 +53,7 @@ export async function loadPersonContext(req: Request, personId: string) {
|
|
|
53
53
|
},
|
|
54
54
|
)
|
|
55
55
|
if (!profile) {
|
|
56
|
-
throw
|
|
56
|
+
throw notFound(translate('customers.errors.person_profile_not_found', 'Person profile not found'))
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
return {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server'
|
|
2
2
|
import { z } from 'zod'
|
|
3
3
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
4
|
-
import { CrudHttpError, isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
4
|
+
import { CrudHttpError, isCrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
5
5
|
import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
|
|
6
6
|
import { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'
|
|
7
7
|
import { resolveOrganizationScopeForRequest } from '@open-mercato/core/modules/directory/utils/organizationScope'
|
|
@@ -174,7 +174,7 @@ export async function GET(req: Request, ctx: { params?: { id?: string } }) {
|
|
|
174
174
|
const decryptionScope = { tenantId: auth.tenantId, organizationId: auth.orgId ?? null }
|
|
175
175
|
const person = await findOneWithDecryption(em, CustomerEntity, { id, kind: 'person', tenantId: auth.tenantId, deletedAt: null }, {}, decryptionScope)
|
|
176
176
|
if (!person) {
|
|
177
|
-
throw
|
|
177
|
+
throw notFound(translate('customers.errors.person_not_found', 'Person not found'))
|
|
178
178
|
}
|
|
179
179
|
|
|
180
180
|
if (!isOrganizationReadAccessAllowed({ scope, auth, organizationId: person.organizationId })) {
|
|
@@ -7,7 +7,7 @@ import { z } from 'zod'
|
|
|
7
7
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
8
8
|
import type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'
|
|
9
9
|
import type { CommandBus } from '@open-mercato/shared/lib/commands'
|
|
10
|
-
import {
|
|
10
|
+
import { isCrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
11
11
|
import { parseBooleanToken } from '@open-mercato/shared/lib/boolean'
|
|
12
12
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
13
13
|
import {
|
|
@@ -218,7 +218,7 @@ async function resolveCanonicalTodoTargetId(
|
|
|
218
218
|
|
|
219
219
|
const legacyLink = await findLegacyTodoLink(em, target, tenantId)
|
|
220
220
|
if (!legacyLink) {
|
|
221
|
-
if (!target.todoId) throw
|
|
221
|
+
if (!target.todoId) throw notFound('Todo not found')
|
|
222
222
|
return target.todoId
|
|
223
223
|
}
|
|
224
224
|
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
resolveParentResourceKind,
|
|
15
15
|
} from './shared'
|
|
16
16
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
17
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
17
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
18
18
|
import type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'
|
|
19
19
|
import { E } from '#generated/entities.ids.generated'
|
|
20
20
|
import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
|
|
@@ -288,7 +288,7 @@ const updateAddressCommand: CommandHandler<AddressUpdateInput, { addressId: stri
|
|
|
288
288
|
const parsed = addressUpdateSchema.parse(rawInput)
|
|
289
289
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
290
290
|
const address = await em.findOne(CustomerAddress, { id: parsed.id })
|
|
291
|
-
if (!address) throw
|
|
291
|
+
if (!address) throw notFound('Address not found')
|
|
292
292
|
ensureTenantScope(ctx, address.tenantId)
|
|
293
293
|
ensureOrganizationScope(ctx, address.organizationId)
|
|
294
294
|
|
|
@@ -477,7 +477,7 @@ const deleteAddressCommand: CommandHandler<{ body?: Record<string, unknown>; que
|
|
|
477
477
|
const id = requireId(input, 'Address id required')
|
|
478
478
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
479
479
|
const address = await em.findOne(CustomerAddress, { id })
|
|
480
|
-
if (!address) throw
|
|
480
|
+
if (!address) throw notFound('Address not found')
|
|
481
481
|
ensureTenantScope(ctx, address.tenantId)
|
|
482
482
|
ensureOrganizationScope(ctx, address.organizationId)
|
|
483
483
|
em.remove(address)
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
resolveParentResourceKind,
|
|
16
16
|
} from './shared'
|
|
17
17
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
18
|
-
import {
|
|
18
|
+
import { notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
19
19
|
import type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'
|
|
20
20
|
import { E } from '#generated/entities.ids.generated'
|
|
21
21
|
import { makeCreateRedo } from '@open-mercato/shared/lib/commands/redo'
|
|
@@ -196,7 +196,7 @@ const updateCommentCommand: CommandHandler<CommentUpdateInput, { commentId: stri
|
|
|
196
196
|
const parsed = commentUpdateSchema.parse(rawInput)
|
|
197
197
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
198
198
|
const comment = await em.findOne(CustomerComment, { id: parsed.id })
|
|
199
|
-
if (!comment) throw
|
|
199
|
+
if (!comment) throw notFound('Comment not found')
|
|
200
200
|
ensureTenantScope(ctx, comment.tenantId)
|
|
201
201
|
ensureOrganizationScope(ctx, comment.organizationId)
|
|
202
202
|
|
|
@@ -332,7 +332,7 @@ const deleteCommentCommand: CommandHandler<{ body?: Record<string, unknown>; que
|
|
|
332
332
|
const id = requireId(input, 'Comment id required')
|
|
333
333
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
334
334
|
const comment = await em.findOne(CustomerComment, { id })
|
|
335
|
-
if (!comment) throw
|
|
335
|
+
if (!comment) throw notFound('Comment not found')
|
|
336
336
|
ensureTenantScope(ctx, comment.tenantId)
|
|
337
337
|
ensureOrganizationScope(ctx, comment.organizationId)
|
|
338
338
|
em.remove(comment)
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import type { DataEngine } from '@open-mercato/shared/lib/data/engine'
|
|
12
12
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
13
13
|
import type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
|
|
14
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
14
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
15
15
|
import {
|
|
16
16
|
CustomerAddress,
|
|
17
17
|
CustomerComment,
|
|
@@ -738,7 +738,7 @@ const updateCompanyCommand: CommandHandler<CompanyUpdateInput, { entityId: strin
|
|
|
738
738
|
ensureTenantScope(ctx, record.tenantId)
|
|
739
739
|
ensureOrganizationScope(ctx, record.organizationId)
|
|
740
740
|
const profile = await em.findOne(CustomerCompanyProfile, { entity: record })
|
|
741
|
-
if (!profile) throw
|
|
741
|
+
if (!profile) throw notFound('Company profile not found')
|
|
742
742
|
|
|
743
743
|
await withAtomicFlush(em, [
|
|
744
744
|
() => {
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
buildCustomFieldResetMap,
|
|
41
41
|
type CustomFieldChangeSet,
|
|
42
42
|
} from '@open-mercato/shared/lib/commands/customFieldSnapshots'
|
|
43
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
43
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
44
44
|
import type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'
|
|
45
45
|
import { E } from '#generated/entities.ids.generated'
|
|
46
46
|
import { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
@@ -625,7 +625,7 @@ const updateDealCommand: CommandHandler<DealUpdateInput, { dealId: string }> = {
|
|
|
625
625
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
626
626
|
const deal = await findOneWithDecryption(em, CustomerDeal, { id: parsed.id, deletedAt: null })
|
|
627
627
|
const record = deal ?? null
|
|
628
|
-
if (!record) throw
|
|
628
|
+
if (!record) throw notFound('Deal not found')
|
|
629
629
|
ensureTenantScope(ctx, record.tenantId)
|
|
630
630
|
ensureOrganizationScope(ctx, record.organizationId)
|
|
631
631
|
|
|
@@ -936,7 +936,7 @@ const deleteDealCommand: CommandHandler<{ body?: Record<string, unknown>; query?
|
|
|
936
936
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
937
937
|
const deal = await findOneWithDecryption(em, CustomerDeal, { id, deletedAt: null })
|
|
938
938
|
const record = deal ?? null
|
|
939
|
-
if (!record) throw
|
|
939
|
+
if (!record) throw notFound('Deal not found')
|
|
940
940
|
ensureTenantScope(ctx, record.tenantId)
|
|
941
941
|
ensureOrganizationScope(ctx, record.organizationId)
|
|
942
942
|
await deleteDealStageTransitions(em, record)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'
|
|
2
2
|
import type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
|
|
3
3
|
import { buildChanges } from '@open-mercato/shared/lib/commands/helpers'
|
|
4
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
4
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
5
5
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
6
6
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
7
7
|
import { invalidateDictionaryCache } from '../api/dictionaries/cache'
|
|
@@ -425,7 +425,7 @@ const updateDictionaryEntryCommand: CommandHandler<CustomerDictionaryEntryUpdate
|
|
|
425
425
|
},
|
|
426
426
|
)
|
|
427
427
|
if (!entry || entry.organizationId !== parsed.organizationId || entry.tenantId !== parsed.tenantId || entry.kind !== parsed.kind) {
|
|
428
|
-
throw
|
|
428
|
+
throw notFound('Dictionary entry not found')
|
|
429
429
|
}
|
|
430
430
|
|
|
431
431
|
let changed = false
|
|
@@ -611,7 +611,7 @@ const deleteDictionaryEntryCommand: CommandHandler<CustomerDictionaryEntryDelete
|
|
|
611
611
|
},
|
|
612
612
|
)
|
|
613
613
|
if (!entry || entry.organizationId !== parsed.organizationId || entry.tenantId !== parsed.tenantId || entry.kind !== parsed.kind) {
|
|
614
|
-
throw
|
|
614
|
+
throw notFound('Dictionary entry not found')
|
|
615
615
|
}
|
|
616
616
|
if (entry.kind === 'person_company_role') {
|
|
617
617
|
const usage = await loadRoleTypeUsage(em, {
|
|
@@ -2,7 +2,7 @@ import { registerCommand } from '@open-mercato/shared/lib/commands'
|
|
|
2
2
|
import type { CommandHandler } from '@open-mercato/shared/lib/commands'
|
|
3
3
|
import type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'
|
|
4
4
|
import { emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'
|
|
5
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
5
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
6
6
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
7
7
|
import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
8
8
|
import type { DataEngine } from '@open-mercato/shared/lib/data/engine'
|
|
@@ -345,7 +345,7 @@ const updateEntityRoleCommand: CommandHandler<EntityRoleUpdateInput, { roleId: s
|
|
|
345
345
|
{ tenantId: parsed.tenantId, organizationId: parsed.organizationId },
|
|
346
346
|
)
|
|
347
347
|
if (!role) {
|
|
348
|
-
throw
|
|
348
|
+
throw notFound('Role not found')
|
|
349
349
|
}
|
|
350
350
|
|
|
351
351
|
role.userId = parsed.userId
|
|
@@ -448,7 +448,7 @@ const deleteEntityRoleCommand: CommandHandler<EntityRoleDeleteInput, { roleId: s
|
|
|
448
448
|
{ tenantId: parsed.tenantId, organizationId: parsed.organizationId },
|
|
449
449
|
)
|
|
450
450
|
if (!role) {
|
|
451
|
-
throw
|
|
451
|
+
throw notFound('Role not found')
|
|
452
452
|
}
|
|
453
453
|
|
|
454
454
|
role.deletedAt = new Date()
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
loadCustomFieldSnapshot,
|
|
39
39
|
buildCustomFieldResetMap,
|
|
40
40
|
} from '@open-mercato/shared/lib/commands/customFieldSnapshots'
|
|
41
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
41
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
42
42
|
import { enforceRecordGoneIsConflict, enforceCommandOptimisticLockWithGuards } from '@open-mercato/shared/lib/crud/optimistic-lock-command'
|
|
43
43
|
import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
44
44
|
import type { CrudIndexerConfig, CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'
|
|
@@ -642,7 +642,7 @@ const updateInteractionCommand: CommandHandler<InteractionUpdateInput, { interac
|
|
|
642
642
|
const interaction = await findOneWithDecryption(trx, CustomerInteraction, { id: parsed.id, deletedAt: null })
|
|
643
643
|
if (!interaction) {
|
|
644
644
|
enforceRecordGoneIsConflict({ resourceKind: 'customers.interaction', resourceId: parsed.id, request: ctx.request ?? null })
|
|
645
|
-
throw
|
|
645
|
+
throw notFound('Interaction not found')
|
|
646
646
|
}
|
|
647
647
|
ensureTenantScope(ctx, interaction.tenantId)
|
|
648
648
|
ensureOrganizationScope(ctx, interaction.organizationId)
|
|
@@ -684,7 +684,7 @@ const updateInteractionCommand: CommandHandler<InteractionUpdateInput, { interac
|
|
|
684
684
|
userFeatures: undefined,
|
|
685
685
|
})
|
|
686
686
|
) {
|
|
687
|
-
throw
|
|
687
|
+
throw notFound('Email not found')
|
|
688
688
|
}
|
|
689
689
|
}
|
|
690
690
|
|
|
@@ -915,7 +915,7 @@ const completeInteractionCommand: CommandHandler<InteractionCompleteInput, { int
|
|
|
915
915
|
const interaction = await findOneWithDecryption(trx, CustomerInteraction, { id: parsed.id, deletedAt: null })
|
|
916
916
|
if (!interaction) {
|
|
917
917
|
enforceRecordGoneIsConflict({ resourceKind: 'customers.interaction', resourceId: parsed.id, request: ctx.request ?? null })
|
|
918
|
-
throw
|
|
918
|
+
throw notFound('Interaction not found')
|
|
919
919
|
}
|
|
920
920
|
ensureTenantScope(ctx, interaction.tenantId)
|
|
921
921
|
ensureOrganizationScope(ctx, interaction.organizationId)
|
|
@@ -1055,7 +1055,7 @@ const cancelInteractionCommand: CommandHandler<InteractionCancelInput, { interac
|
|
|
1055
1055
|
const interaction = await findOneWithDecryption(trx, CustomerInteraction, { id: parsed.id, deletedAt: null })
|
|
1056
1056
|
if (!interaction) {
|
|
1057
1057
|
enforceRecordGoneIsConflict({ resourceKind: 'customers.interaction', resourceId: parsed.id, request: ctx.request ?? null })
|
|
1058
|
-
throw
|
|
1058
|
+
throw notFound('Interaction not found')
|
|
1059
1059
|
}
|
|
1060
1060
|
ensureTenantScope(ctx, interaction.tenantId)
|
|
1061
1061
|
ensureOrganizationScope(ctx, interaction.organizationId)
|
|
@@ -1193,7 +1193,7 @@ const deleteInteractionCommand: CommandHandler<{ body?: Record<string, unknown>;
|
|
|
1193
1193
|
const interaction = await findOneWithDecryption(trx, CustomerInteraction, { id, deletedAt: null })
|
|
1194
1194
|
if (!interaction) {
|
|
1195
1195
|
enforceRecordGoneIsConflict({ resourceKind: 'customers.interaction', resourceId: id, request: ctx.request ?? null })
|
|
1196
|
-
throw
|
|
1196
|
+
throw notFound('Interaction not found')
|
|
1197
1197
|
}
|
|
1198
1198
|
ensureTenantScope(ctx, interaction.tenantId)
|
|
1199
1199
|
ensureOrganizationScope(ctx, interaction.organizationId)
|
|
@@ -2,7 +2,7 @@ import { registerCommand } from '@open-mercato/shared/lib/commands'
|
|
|
2
2
|
import type { CommandHandler } from '@open-mercato/shared/lib/commands'
|
|
3
3
|
import type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'
|
|
4
4
|
import { emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'
|
|
5
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
5
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
6
6
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
7
7
|
import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
8
8
|
import type { DataEngine } from '@open-mercato/shared/lib/data/engine'
|
|
@@ -287,7 +287,7 @@ const assignLabelCommand: CommandHandler<LabelAssignCommandInput, { assignmentId
|
|
|
287
287
|
{ tenantId: parsed.tenantId, organizationId: parsed.organizationId },
|
|
288
288
|
)
|
|
289
289
|
if (!label) {
|
|
290
|
-
throw
|
|
290
|
+
throw notFound('Label not found')
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
const entity = await findOneWithDecryption(
|
|
@@ -298,7 +298,7 @@ const assignLabelCommand: CommandHandler<LabelAssignCommandInput, { assignmentId
|
|
|
298
298
|
{ tenantId: parsed.tenantId, organizationId: parsed.organizationId },
|
|
299
299
|
)
|
|
300
300
|
if (!entity) {
|
|
301
|
-
throw
|
|
301
|
+
throw notFound('Entity not found')
|
|
302
302
|
}
|
|
303
303
|
|
|
304
304
|
const existing = await findOneWithDecryption(
|
|
@@ -441,7 +441,7 @@ const assignLabelCommand: CommandHandler<LabelAssignCommandInput, { assignmentId
|
|
|
441
441
|
{ tenantId: after.tenantId, organizationId: after.organizationId },
|
|
442
442
|
)
|
|
443
443
|
if (!label) {
|
|
444
|
-
throw
|
|
444
|
+
throw notFound('Label not found')
|
|
445
445
|
}
|
|
446
446
|
const entity = await findOneWithDecryption(
|
|
447
447
|
em,
|
|
@@ -451,7 +451,7 @@ const assignLabelCommand: CommandHandler<LabelAssignCommandInput, { assignmentId
|
|
|
451
451
|
{ tenantId: after.tenantId, organizationId: after.organizationId },
|
|
452
452
|
)
|
|
453
453
|
if (!entity) {
|
|
454
|
-
throw
|
|
454
|
+
throw notFound('Entity not found')
|
|
455
455
|
}
|
|
456
456
|
|
|
457
457
|
let assignment = await findOneWithDecryption(
|
|
@@ -570,7 +570,7 @@ const unassignLabelCommand: CommandHandler<LabelUnassignCommandInput, { assignme
|
|
|
570
570
|
{ tenantId: parsed.tenantId, organizationId: parsed.organizationId },
|
|
571
571
|
)
|
|
572
572
|
if (!label) {
|
|
573
|
-
throw
|
|
573
|
+
throw notFound('Label not found')
|
|
574
574
|
}
|
|
575
575
|
|
|
576
576
|
const entity = await findOneWithDecryption(
|
|
@@ -581,7 +581,7 @@ const unassignLabelCommand: CommandHandler<LabelUnassignCommandInput, { assignme
|
|
|
581
581
|
{ tenantId: parsed.tenantId, organizationId: parsed.organizationId },
|
|
582
582
|
)
|
|
583
583
|
if (!entity) {
|
|
584
|
-
throw
|
|
584
|
+
throw notFound('Entity not found')
|
|
585
585
|
}
|
|
586
586
|
|
|
587
587
|
const existing = await findOneWithDecryption(
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
} from './shared'
|
|
47
47
|
import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
|
|
48
48
|
import { resolveRedoSnapshot } from '@open-mercato/shared/lib/commands/redo'
|
|
49
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
49
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
50
50
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
51
51
|
import {
|
|
52
52
|
loadCustomFieldSnapshot,
|
|
@@ -851,7 +851,7 @@ const createPersonCommand: CommandHandler<PersonCreateInput, { entityId: string;
|
|
|
851
851
|
undefined,
|
|
852
852
|
{ tenantId: after.entity.tenantId, organizationId: after.entity.organizationId },
|
|
853
853
|
)
|
|
854
|
-
if (!existingProfile) throw
|
|
854
|
+
if (!existingProfile) throw notFound('Person profile not found')
|
|
855
855
|
profile = existingProfile
|
|
856
856
|
const survivingEntity = entity
|
|
857
857
|
await withAtomicFlush(em, [
|
|
@@ -927,7 +927,7 @@ const updatePersonCommand: CommandHandler<PersonUpdateInput, { entityId: string
|
|
|
927
927
|
ensureTenantScope(ctx, record.tenantId)
|
|
928
928
|
ensureOrganizationScope(ctx, record.organizationId)
|
|
929
929
|
const profile = await em.findOne(CustomerPersonProfile, { entity: record })
|
|
930
|
-
if (!profile) throw
|
|
930
|
+
if (!profile) throw notFound('Person profile not found')
|
|
931
931
|
|
|
932
932
|
if (parsed.displayName !== undefined) {
|
|
933
933
|
const nextDisplayName = parsed.displayName.trim()
|
|
@@ -2,7 +2,7 @@ import { registerCommand } from '@open-mercato/shared/lib/commands'
|
|
|
2
2
|
import type { CommandHandler } from '@open-mercato/shared/lib/commands'
|
|
3
3
|
import type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'
|
|
4
4
|
import { emitCrudSideEffects, emitCrudUndoSideEffects } from '@open-mercato/shared/lib/commands/helpers'
|
|
5
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
5
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
6
6
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
7
7
|
import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
8
8
|
import type { DataEngine } from '@open-mercato/shared/lib/data/engine'
|
|
@@ -126,7 +126,7 @@ async function requirePersonEntity(
|
|
|
126
126
|
{ tenantId, organizationId },
|
|
127
127
|
)
|
|
128
128
|
if (!person) {
|
|
129
|
-
throw
|
|
129
|
+
throw notFound('Person not found')
|
|
130
130
|
}
|
|
131
131
|
return person
|
|
132
132
|
}
|
|
@@ -145,7 +145,7 @@ async function requireCompanyEntity(
|
|
|
145
145
|
{ tenantId, organizationId },
|
|
146
146
|
)
|
|
147
147
|
if (!company) {
|
|
148
|
-
throw
|
|
148
|
+
throw notFound('Company not found')
|
|
149
149
|
}
|
|
150
150
|
return company
|
|
151
151
|
}
|
|
@@ -162,7 +162,7 @@ async function requirePersonProfile(
|
|
|
162
162
|
{ tenantId: person.tenantId, organizationId: person.organizationId },
|
|
163
163
|
)
|
|
164
164
|
if (!profile) {
|
|
165
|
-
throw
|
|
165
|
+
throw notFound('Person profile not found')
|
|
166
166
|
}
|
|
167
167
|
return profile
|
|
168
168
|
}
|
|
@@ -433,7 +433,7 @@ const updatePersonCompanyLinkCommand: CommandHandler<PersonCompanyLinkUpdateInpu
|
|
|
433
433
|
{ tenantId: parsed.tenantId, organizationId: parsed.organizationId },
|
|
434
434
|
)
|
|
435
435
|
if (!link) {
|
|
436
|
-
throw
|
|
436
|
+
throw notFound('Company link not found')
|
|
437
437
|
}
|
|
438
438
|
|
|
439
439
|
const personId = typeof link.person === 'string' ? link.person : link.person.id
|
|
@@ -606,7 +606,7 @@ const deletePersonCompanyLinkCommand: CommandHandler<PersonCompanyLinkDeleteInpu
|
|
|
606
606
|
{ tenantId: parsed.tenantId, organizationId: parsed.organizationId },
|
|
607
607
|
)
|
|
608
608
|
if (!link) {
|
|
609
|
-
throw
|
|
609
|
+
throw notFound('Company link not found')
|
|
610
610
|
}
|
|
611
611
|
|
|
612
612
|
const personId = typeof link.person === 'string' ? link.person : link.person.id
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
type PipelineStageReorderInput,
|
|
15
15
|
} from '../data/validators'
|
|
16
16
|
import { ensureOrganizationScope, ensureTenantScope, ensureDictionaryEntry } from './shared'
|
|
17
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
17
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
18
18
|
import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
|
|
19
19
|
import {
|
|
20
20
|
enforceCommandOptimisticLockWithGuards,
|
|
@@ -112,7 +112,7 @@ const updatePipelineStageCommand: CommandHandler<PipelineStageUpdateInput, void>
|
|
|
112
112
|
})
|
|
113
113
|
if (!stage) {
|
|
114
114
|
enforceRecordGoneIsConflict({ resourceKind: 'customers.pipelineStage', resourceId: parsed.id, request: ctx.request ?? null })
|
|
115
|
-
throw
|
|
115
|
+
throw notFound('Pipeline stage not found')
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
ensureTenantScope(ctx, stage.tenantId)
|
|
@@ -164,7 +164,7 @@ const deletePipelineStageCommand: CommandHandler<PipelineStageDeleteInput, void>
|
|
|
164
164
|
})
|
|
165
165
|
if (!stage) {
|
|
166
166
|
enforceRecordGoneIsConflict({ resourceKind: 'customers.pipelineStage', resourceId: parsed.id, request: ctx.request ?? null })
|
|
167
|
-
throw
|
|
167
|
+
throw notFound('Pipeline stage not found')
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
ensureTenantScope(ctx, stage.tenantId)
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
type PipelineDeleteInput,
|
|
12
12
|
} from '../data/validators'
|
|
13
13
|
import { ensureOrganizationScope, ensureTenantScope } from './shared'
|
|
14
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
14
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
15
15
|
import {
|
|
16
16
|
enforceCommandOptimisticLockWithGuards,
|
|
17
17
|
enforceRecordGoneIsConflict,
|
|
@@ -62,7 +62,7 @@ const updatePipelineCommand: CommandHandler<PipelineUpdateInput, void> = {
|
|
|
62
62
|
const pipeline = await em.findOne(CustomerPipeline, { id: parsed.id })
|
|
63
63
|
if (!pipeline) {
|
|
64
64
|
enforceRecordGoneIsConflict({ resourceKind: 'customers.pipeline', resourceId: parsed.id, request: ctx.request ?? null })
|
|
65
|
-
throw
|
|
65
|
+
throw notFound('Pipeline not found')
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
ensureTenantScope(ctx, pipeline.tenantId)
|
|
@@ -102,7 +102,7 @@ const deletePipelineCommand: CommandHandler<PipelineDeleteInput, void> = {
|
|
|
102
102
|
const pipeline = await em.findOne(CustomerPipeline, { id: parsed.id })
|
|
103
103
|
if (!pipeline) {
|
|
104
104
|
enforceRecordGoneIsConflict({ resourceKind: 'customers.pipeline', resourceId: parsed.id, request: ctx.request ?? null })
|
|
105
|
-
throw
|
|
105
|
+
throw notFound('Pipeline not found')
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
ensureTenantScope(ctx, pipeline.tenantId)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
2
2
|
import { CustomerDeal, CustomerEntity, CustomerTag, CustomerTagAssignment, CustomerDictionaryEntry, type CustomerEntityKind } from '../data/entities'
|
|
3
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
3
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
4
4
|
import type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
|
|
5
5
|
import { ensureOrganizationScope, ensureSameScope } from '@open-mercato/shared/lib/commands/scope'
|
|
6
6
|
import { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
@@ -47,7 +47,7 @@ export async function requireCustomerEntity(
|
|
|
47
47
|
tenantId: scope.tenantId,
|
|
48
48
|
organizationId: scope.organizationId,
|
|
49
49
|
})
|
|
50
|
-
if (!entity) throw
|
|
50
|
+
if (!entity) throw notFound(message)
|
|
51
51
|
if (kind && entity.kind !== kind) {
|
|
52
52
|
throw new CrudHttpError(400, { error: 'Invalid entity type' })
|
|
53
53
|
}
|
|
@@ -80,7 +80,7 @@ export async function requireTimelineParentEntity(
|
|
|
80
80
|
if (deal) {
|
|
81
81
|
throw new CrudHttpError(422, { error: 'entityId must reference a person or company, not a deal' })
|
|
82
82
|
}
|
|
83
|
-
throw
|
|
83
|
+
throw notFound('Customer not found')
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
export async function syncEntityTags(
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
loadEntityTagIds,
|
|
22
22
|
} from './shared'
|
|
23
23
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
24
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
24
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
25
25
|
import type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'
|
|
26
26
|
import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
27
27
|
import { emitCustomersEvent } from '../events'
|
|
@@ -172,7 +172,7 @@ const updateTagCommand: CommandHandler<TagUpdateInput, { tagId: string }> = {
|
|
|
172
172
|
const parsed = tagUpdateSchema.parse(rawInput)
|
|
173
173
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
174
174
|
const tag = await em.findOne(CustomerTag, { id: parsed.id })
|
|
175
|
-
if (!tag) throw
|
|
175
|
+
if (!tag) throw notFound('Tag not found')
|
|
176
176
|
ensureTenantScope(ctx, tag.tenantId)
|
|
177
177
|
ensureOrganizationScope(ctx, tag.organizationId)
|
|
178
178
|
|
|
@@ -290,7 +290,7 @@ const deleteTagCommand: CommandHandler<{ body?: Record<string, unknown>; query?:
|
|
|
290
290
|
const id = requireId(input, 'Tag id required')
|
|
291
291
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
292
292
|
const tag = await em.findOne(CustomerTag, { id })
|
|
293
|
-
if (!tag) throw
|
|
293
|
+
if (!tag) throw notFound('Tag not found')
|
|
294
294
|
ensureTenantScope(ctx, tag.tenantId)
|
|
295
295
|
ensureOrganizationScope(ctx, tag.organizationId)
|
|
296
296
|
await withAtomicFlush(em, [
|
|
@@ -386,7 +386,7 @@ const assignTagCommand: CommandHandler<TagAssignmentInput, { assignmentId: strin
|
|
|
386
386
|
|
|
387
387
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
388
388
|
const tag = await em.findOne(CustomerTag, { id: parsed.tagId, tenantId: parsed.tenantId, organizationId: parsed.organizationId })
|
|
389
|
-
if (!tag) throw
|
|
389
|
+
if (!tag) throw notFound('Tag not found')
|
|
390
390
|
const entity = await requireCustomerEntity(em, parsed.entityId, { tenantId: parsed.tenantId, organizationId: parsed.organizationId }, undefined, 'Customer not found')
|
|
391
391
|
ensureSameScope(entity, parsed.organizationId, parsed.tenantId)
|
|
392
392
|
const tagIds = await loadEntityTagIds(em, entity)
|
|
@@ -477,7 +477,7 @@ const assignTagCommand: CommandHandler<TagAssignmentInput, { assignmentId: strin
|
|
|
477
477
|
const assignmentId = logEntry?.resourceId ?? null
|
|
478
478
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
479
479
|
const tag = await em.findOne(CustomerTag, { id: before.tagId })
|
|
480
|
-
if (!tag) throw
|
|
480
|
+
if (!tag) throw notFound('Tag not found')
|
|
481
481
|
const entity = await requireCustomerEntity(em, before.entityId, { tenantId: before.tenantId, organizationId: before.organizationId }, undefined, 'Customer not found')
|
|
482
482
|
ensureSameScope(entity, before.organizationId, before.tenantId)
|
|
483
483
|
|
|
@@ -537,7 +537,7 @@ const unassignTagCommand: CommandHandler<TagAssignmentInput, { assignmentId: str
|
|
|
537
537
|
tenantId: parsed.tenantId,
|
|
538
538
|
organizationId: parsed.organizationId,
|
|
539
539
|
})
|
|
540
|
-
if (!existing) throw
|
|
540
|
+
if (!existing) throw notFound('Tag assignment not found')
|
|
541
541
|
await em.remove(existing).flush()
|
|
542
542
|
|
|
543
543
|
const de = (ctx.container.resolve('dataEngine') as DataEngine)
|
|
@@ -591,7 +591,7 @@ const unassignTagCommand: CommandHandler<TagAssignmentInput, { assignmentId: str
|
|
|
591
591
|
const tag = await em.findOne(CustomerTag, { id: before.tagId })
|
|
592
592
|
const entity = await requireCustomerEntity(em, before.entityId, { tenantId: before.tenantId, organizationId: before.organizationId }, undefined, 'Customer not found')
|
|
593
593
|
ensureSameScope(entity, before.organizationId, before.tenantId)
|
|
594
|
-
if (!tag) throw
|
|
594
|
+
if (!tag) throw notFound('Tag not found')
|
|
595
595
|
const existing = await em.findOne(CustomerTagAssignment, {
|
|
596
596
|
tag,
|
|
597
597
|
entity,
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
resolveParentResourceKind,
|
|
17
17
|
} from './shared'
|
|
18
18
|
import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
|
|
19
|
-
import {
|
|
19
|
+
import { notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
20
20
|
import {
|
|
21
21
|
CUSTOMER_INTERACTION_TASK_SOURCE,
|
|
22
22
|
CUSTOMER_INTERACTION_TODO_ADAPTER_SOURCE,
|
|
@@ -290,7 +290,7 @@ async function resolveTodoTarget(
|
|
|
290
290
|
const em = (ctx.container.resolve('em') as EntityManager).fork()
|
|
291
291
|
const legacyLink = await em.findOne(CustomerTodoLink, { id: linkId }, { populate: ['entity'] })
|
|
292
292
|
if (!legacyLink) {
|
|
293
|
-
throw
|
|
293
|
+
throw notFound('Todo link not found')
|
|
294
294
|
}
|
|
295
295
|
|
|
296
296
|
const bridgedSnapshot = await loadInteractionSnapshot(legacyLink.todoId, ctx)
|
|
@@ -333,7 +333,7 @@ const unlinkTodoCommand: CommandHandler<
|
|
|
333
333
|
const target = await resolveTodoTarget(parsed.linkId, ctx)
|
|
334
334
|
if (!target.canonicalExists) {
|
|
335
335
|
if (!target.legacyLink) {
|
|
336
|
-
throw
|
|
336
|
+
throw notFound('Todo link not found')
|
|
337
337
|
}
|
|
338
338
|
const canonicalCreate = getRequiredHandler<
|
|
339
339
|
InteractionCreateInput & { customValues?: Record<string, unknown> },
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { EntityManager } from '@mikro-orm/postgresql'
|
|
2
|
-
import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
|
|
2
|
+
import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
|
|
3
3
|
import { findWithDecryption, findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
|
|
4
4
|
import {
|
|
5
5
|
CustomerEntity,
|
|
@@ -48,7 +48,7 @@ async function requireCompany(
|
|
|
48
48
|
): Promise<CustomerEntity> {
|
|
49
49
|
const company = await findOneWithDecryption(em, CustomerEntity, { id: companyId, kind: 'company', deletedAt: null }, {}, { tenantId, organizationId })
|
|
50
50
|
if (!company) {
|
|
51
|
-
throw
|
|
51
|
+
throw notFound('Company not found')
|
|
52
52
|
}
|
|
53
53
|
if (company.organizationId !== organizationId || company.tenantId !== tenantId) {
|
|
54
54
|
throw new CrudHttpError(403, { error: 'Cannot link company outside current scope' })
|
|
@@ -260,7 +260,7 @@ export async function updatePersonCompanyLink(
|
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
if (!link) {
|
|
263
|
-
throw
|
|
263
|
+
throw notFound('Company link not found')
|
|
264
264
|
}
|
|
265
265
|
|
|
266
266
|
if (patch.isPrimary === true) {
|
|
@@ -301,7 +301,7 @@ export async function removePersonCompanyLink(
|
|
|
301
301
|
profile.company = null
|
|
302
302
|
return
|
|
303
303
|
}
|
|
304
|
-
throw
|
|
304
|
+
throw notFound('Company link not found')
|
|
305
305
|
}
|
|
306
306
|
|
|
307
307
|
const removedCompanyId = typeof link.company === 'string' ? link.company : link.company.id
|
|
@@ -4,6 +4,10 @@ import type { PerspectiveSettings } from '@open-mercato/shared/modules/perspecti
|
|
|
4
4
|
export const perspectiveSettingsSchema: z.ZodType<PerspectiveSettings> = z.object({
|
|
5
5
|
columnOrder: z.array(z.string().min(1)).max(120).optional(),
|
|
6
6
|
columnVisibility: z.record(z.string(), z.boolean()).optional(),
|
|
7
|
+
// User-resized column widths in pixels, keyed by column id (#1835). Clamped to
|
|
8
|
+
// the same [60, 900] bound the client enforces so a saved perspective cannot
|
|
9
|
+
// carry a column width that collapses or blows out the table.
|
|
10
|
+
columnSizing: z.record(z.string().min(1), z.number().int().min(60).max(900)).optional(),
|
|
7
11
|
filters: z.record(z.string(), z.unknown()).optional(),
|
|
8
12
|
sorting: z
|
|
9
13
|
.array(z.object({ id: z.string().min(1), desc: z.boolean().optional() }))
|