@open-mercato/core 0.6.7-develop.6553.1.2ec7246e04 → 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/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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { registerCommand } from "@open-mercato/shared/lib/commands";
|
|
2
2
|
import { emitCrudSideEffects } from "@open-mercato/shared/lib/commands/helpers";
|
|
3
|
-
import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
|
|
3
|
+
import { CrudHttpError, notFound } from "@open-mercato/shared/lib/crud/errors";
|
|
4
4
|
import {
|
|
5
5
|
documentAddressCreateSchema,
|
|
6
6
|
documentAddressDeleteSchema,
|
|
@@ -64,7 +64,7 @@ function applyDocumentAddressSnapshot(em, entity, snapshot) {
|
|
|
64
64
|
}
|
|
65
65
|
function assertDocumentAddressParent(entity, input) {
|
|
66
66
|
if (entity.documentId !== input.documentId || entity.documentKind !== input.documentKind) {
|
|
67
|
-
throw
|
|
67
|
+
throw notFound("sales.document.address.not_found");
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
async function emitDocumentAddressIndexSideEffects(ctx, action, snapshot) {
|
|
@@ -91,7 +91,7 @@ async function requireDocument(em, kind, id, organizationId, tenantId) {
|
|
|
91
91
|
const repo = kind === "order" ? SalesOrder : SalesQuote;
|
|
92
92
|
const doc = await findOneWithDecryption(em, repo, { id, organizationId, tenantId }, {}, { tenantId, organizationId });
|
|
93
93
|
if (!doc) {
|
|
94
|
-
throw
|
|
94
|
+
throw notFound("sales.document.not_found");
|
|
95
95
|
}
|
|
96
96
|
return doc;
|
|
97
97
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/sales/commands/documentAddresses.ts"],
|
|
4
|
-
"sourcesContent": ["// @ts-nocheck\n\nimport { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport {\n documentAddressCreateSchema,\n documentAddressDeleteSchema,\n documentAddressUpdateSchema,\n type DocumentAddressCreateInput,\n type DocumentAddressDeleteInput,\n type DocumentAddressUpdateInput,\n} from '../data/validators'\nimport { SalesDocumentAddress, SalesOrder, SalesQuote } from '../data/entities'\nimport { ensureOrganizationScope, ensureSameScope, ensureTenantScope, assertFound, extractUndoPayload } from './shared'\nimport { loadSalesSettings } from './settings'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { E } from '#generated/entities.ids.generated'\n\nconst DOCUMENT_ADDRESS_ENTITY_TYPE = E.sales.sales_document_address\n\ntype DocumentAddressSnapshot = {\n id: string\n organizationId: string\n tenantId: string\n documentId: string\n documentKind: 'order' | 'quote'\n customerAddressId: string | null\n name: string | null\n purpose: string | null\n companyName: string | null\n addressLine1: string\n addressLine2: string | null\n buildingNumber: string | null\n flatNumber: string | null\n city: string | null\n region: string | null\n postalCode: string | null\n country: string | null\n latitude: number | null\n longitude: number | null\n}\n\ntype DocumentAddressUndoPayload = {\n before?: DocumentAddressSnapshot | null\n after?: DocumentAddressSnapshot | null\n}\n\nfunction snapshotDocumentAddress(entity: SalesDocumentAddress): DocumentAddressSnapshot {\n return {\n id: entity.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n documentId: entity.documentId,\n documentKind: entity.documentKind as 'order' | 'quote',\n customerAddressId: entity.customerAddressId ?? null,\n name: entity.name ?? null,\n purpose: entity.purpose ?? null,\n companyName: entity.companyName ?? null,\n addressLine1: entity.addressLine1,\n addressLine2: entity.addressLine2 ?? null,\n buildingNumber: entity.buildingNumber ?? null,\n flatNumber: entity.flatNumber ?? null,\n city: entity.city ?? null,\n region: entity.region ?? null,\n postalCode: entity.postalCode ?? null,\n country: entity.country ?? null,\n latitude: entity.latitude ?? null,\n longitude: entity.longitude ?? null,\n }\n}\n\nasync function loadDocumentAddressSnapshot(\n em: EntityManager,\n id: string\n): Promise<DocumentAddressSnapshot | null> {\n const entity = await findOneWithDecryption(em, SalesDocumentAddress, { id }, {})\n return entity ? snapshotDocumentAddress(entity) : null\n}\n\nfunction applyDocumentAddressSnapshot(em: EntityManager, entity: SalesDocumentAddress, snapshot: DocumentAddressSnapshot): void {\n entity.organizationId = snapshot.organizationId\n entity.tenantId = snapshot.tenantId\n entity.documentId = snapshot.documentId\n entity.documentKind = snapshot.documentKind\n entity.customerAddressId = snapshot.customerAddressId\n entity.name = snapshot.name\n entity.purpose = snapshot.purpose\n entity.companyName = snapshot.companyName\n entity.addressLine1 = snapshot.addressLine1\n entity.addressLine2 = snapshot.addressLine2\n entity.buildingNumber = snapshot.buildingNumber\n entity.flatNumber = snapshot.flatNumber\n entity.city = snapshot.city\n entity.region = snapshot.region\n entity.postalCode = snapshot.postalCode\n entity.country = snapshot.country\n entity.latitude = snapshot.latitude\n entity.longitude = snapshot.longitude\n entity.order = snapshot.documentKind === 'order' ? em.getReference(SalesOrder, snapshot.documentId) : null\n entity.quote = snapshot.documentKind === 'quote' ? em.getReference(SalesQuote, snapshot.documentId) : null\n}\n\nfunction assertDocumentAddressParent(entity: SalesDocumentAddress, input: { documentId: string; documentKind: 'order' | 'quote' }): void {\n if (entity.documentId !== input.documentId || entity.documentKind !== input.documentKind) {\n throw new CrudHttpError(404, { error: 'sales.document.address.not_found' })\n }\n}\n\nasync function emitDocumentAddressIndexSideEffects(\n ctx: { container: { resolve: (name: string) => unknown } },\n action: 'created' | 'updated' | 'deleted',\n snapshot: DocumentAddressSnapshot\n): Promise<void> {\n let dataEngine: DataEngine | null = null\n try {\n dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n } catch {\n dataEngine = null\n }\n if (!dataEngine) return\n await emitCrudSideEffects({\n dataEngine,\n action,\n entity: snapshot,\n identifiers: {\n id: snapshot.id,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n },\n indexer: { entityType: DOCUMENT_ADDRESS_ENTITY_TYPE },\n })\n}\n\nasync function requireDocument(\n em: EntityManager,\n kind: 'order' | 'quote',\n id: string,\n organizationId: string,\n tenantId: string\n): Promise<SalesOrder | SalesQuote> {\n const repo = kind === 'order' ? SalesOrder : SalesQuote\n const doc = await findOneWithDecryption(em, repo, { id, organizationId, tenantId }, {}, { tenantId, organizationId })\n if (!doc) {\n throw new CrudHttpError(404, { error: 'sales.document.not_found' })\n }\n return doc\n}\n\nasync function assertAddressEditable(\n em: EntityManager,\n params: { organizationId: string; tenantId: string; status: string | null }\n): Promise<void> {\n const settings = await loadSalesSettings(em, {\n tenantId: params.tenantId,\n organizationId: params.organizationId,\n })\n const allowed = settings?.orderAddressEditableStatuses ?? null\n if (!Array.isArray(allowed)) return\n const { translate } = await resolveTranslations()\n if (allowed.length === 0) {\n throw new CrudHttpError(400, { error: translate('sales.orders.edit_addresses_blocked', 'Addresses cannot be changed for the current status.') })\n }\n if (!params.status || !allowed.includes(params.status)) {\n throw new CrudHttpError(400, { error: translate('sales.orders.edit_addresses_blocked', 'Addresses cannot be changed for the current status.') })\n }\n}\n\nconst createDocumentAddress: CommandHandler<DocumentAddressCreateInput, { id: string }> = {\n id: 'sales.document-addresses.create',\n async execute(rawInput, ctx) {\n const input = documentAddressCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const document = await requireDocument(em, input.documentKind, input.documentId, input.organizationId, input.tenantId)\n if (input.documentKind === 'order') {\n await assertAddressEditable(em, {\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n status: (document as SalesOrder).status ?? null,\n })\n }\n\n const entity = em.create(SalesDocumentAddress, {\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n documentId: input.documentId,\n documentKind: input.documentKind,\n customerAddressId: input.customerAddressId ?? null,\n name: input.name ?? null,\n purpose: input.purpose ?? null,\n companyName: input.companyName ?? null,\n addressLine1: input.addressLine1,\n addressLine2: input.addressLine2 ?? null,\n buildingNumber: input.buildingNumber ?? null,\n flatNumber: input.flatNumber ?? null,\n city: input.city ?? null,\n region: input.region ?? null,\n postalCode: input.postalCode ?? null,\n country: input.country ?? null,\n latitude: input.latitude ?? null,\n longitude: input.longitude ?? null,\n order: input.documentKind === 'order' ? (document as SalesOrder) : null,\n quote: input.documentKind === 'quote' ? (document as SalesQuote) : null,\n })\n await em.persist(entity).flush()\n return { id: entity.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return result?.id ? loadDocumentAddressSnapshot(em, result.id) : null\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as DocumentAddressSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.document_addresses.create', 'Add document address'),\n resourceKind: 'sales.document_address',\n resourceId: result.id,\n parentResourceKind: after.documentKind === 'order' ? 'sales.order' : 'sales.quote',\n parentResourceId: after.documentId,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: { undo: { after } satisfies DocumentAddressUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DocumentAddressUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n ensureTenantScope(ctx, after.tenantId)\n ensureOrganizationScope(ctx, after.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = await findOneWithDecryption(em, SalesDocumentAddress, { id: after.id }, {}, { tenantId: after.tenantId, organizationId: after.organizationId })\n if (!entity) return\n await em.remove(entity).flush()\n await emitDocumentAddressIndexSideEffects(ctx, 'deleted', after)\n },\n}\n\nconst updateDocumentAddress: CommandHandler<DocumentAddressUpdateInput, { id: string }> = {\n id: 'sales.document-addresses.update',\n async prepare(rawInput, ctx) {\n const parsed = documentAddressUpdateSchema.parse(rawInput)\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadDocumentAddressSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const input = documentAddressUpdateSchema.parse(rawInput)\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = assertFound(\n await findOneWithDecryption(em, SalesDocumentAddress, { id: input.id }, {}, { tenantId: input.tenantId, organizationId: input.organizationId }),\n 'sales.document.address.not_found'\n )\n ensureSameScope(entity, input.organizationId, input.tenantId)\n assertDocumentAddressParent(entity, input)\n const document = await requireDocument(em, input.documentKind, input.documentId, input.organizationId, input.tenantId)\n if (input.documentKind === 'order') {\n await assertAddressEditable(em, {\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n status: (document as SalesOrder).status ?? null,\n })\n }\n\n entity.documentId = input.documentId\n entity.documentKind = input.documentKind\n entity.customerAddressId = input.customerAddressId ?? null\n entity.name = input.name ?? null\n entity.purpose = input.purpose ?? null\n entity.companyName = input.companyName ?? null\n entity.addressLine1 = input.addressLine1\n entity.addressLine2 = input.addressLine2 ?? null\n entity.buildingNumber = input.buildingNumber ?? null\n entity.flatNumber = input.flatNumber ?? null\n entity.city = input.city ?? null\n entity.region = input.region ?? null\n entity.postalCode = input.postalCode ?? null\n entity.country = input.country ?? null\n entity.latitude = input.latitude ?? null\n entity.longitude = input.longitude ?? null\n\n await em.flush()\n return { id: entity.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return result?.id ? loadDocumentAddressSnapshot(em, result.id) : null\n },\n buildLog: async ({ result, snapshots }) => {\n const before = snapshots.before as DocumentAddressSnapshot | undefined\n const after = snapshots.after as DocumentAddressSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.document_addresses.update', 'Update document address'),\n resourceKind: 'sales.document_address',\n resourceId: result.id,\n parentResourceKind: after.documentKind === 'order' ? 'sales.order' : 'sales.quote',\n parentResourceId: after.documentId,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotBefore: before ?? null,\n snapshotAfter: after,\n payload: { undo: { before: before ?? null, after } satisfies DocumentAddressUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DocumentAddressUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity =\n (await findOneWithDecryption(em, SalesDocumentAddress, { id: before.id }, {}, { tenantId: before.tenantId, organizationId: before.organizationId })) ??\n em.create(SalesDocumentAddress, { id: before.id } as Partial<SalesDocumentAddress>)\n applyDocumentAddressSnapshot(em, entity, before)\n await em.persist(entity).flush()\n await emitDocumentAddressIndexSideEffects(ctx, 'updated', before)\n },\n}\n\nconst deleteDocumentAddress: CommandHandler<\n DocumentAddressDeleteInput,\n { ok: true; id: string }\n> = {\n id: 'sales.document-addresses.delete',\n async prepare(rawInput, ctx) {\n const parsed = documentAddressDeleteSchema.parse(rawInput)\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadDocumentAddressSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const input = documentAddressDeleteSchema.parse(rawInput)\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = assertFound(\n await findOneWithDecryption(em, SalesDocumentAddress, { id: input.id }, {}, { tenantId: input.tenantId, organizationId: input.organizationId }),\n 'sales.document.address.not_found'\n )\n ensureSameScope(entity, input.organizationId, input.tenantId)\n assertDocumentAddressParent(entity, input)\n const document = await requireDocument(em, input.documentKind, input.documentId, input.organizationId, input.tenantId)\n if (input.documentKind === 'order') {\n await assertAddressEditable(em, {\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n status: (document as SalesOrder).status ?? null,\n })\n }\n await em.remove(entity).flush()\n return { ok: true, id: input.id }\n },\n buildLog: async ({ result, snapshots }) => {\n const before = snapshots.before as DocumentAddressSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.document_addresses.delete', 'Remove document address'),\n resourceKind: 'sales.document_address',\n resourceId: result.id,\n parentResourceKind: before.documentKind === 'order' ? 'sales.order' : 'sales.quote',\n parentResourceId: before.documentId,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: { undo: { before } satisfies DocumentAddressUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DocumentAddressUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await findOneWithDecryption(em, SalesDocumentAddress, { id: before.id }, {}, { tenantId: before.tenantId, organizationId: before.organizationId })\n const entity = existing ?? em.create(SalesDocumentAddress, { id: before.id } as Partial<SalesDocumentAddress>)\n applyDocumentAddressSnapshot(em, entity, before)\n await em.persist(entity).flush()\n await emitDocumentAddressIndexSideEffects(ctx, 'created', before)\n },\n}\n\nexport const documentAddressCommands = [createDocumentAddress, updateDocumentAddress, deleteDocumentAddress]\n\nregisterCommand(createDocumentAddress)\nregisterCommand(updateDocumentAddress)\nregisterCommand(deleteDocumentAddress)\n"],
|
|
5
|
-
"mappings": "AAEA,SAAS,uBAA4C;AACrD,SAAS,2BAA2B;AAGpC,SAAS,
|
|
4
|
+
"sourcesContent": ["// @ts-nocheck\n\nimport { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'\nimport { emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'\nimport type { DataEngine } from '@open-mercato/shared/lib/data/engine'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'\nimport {\n documentAddressCreateSchema,\n documentAddressDeleteSchema,\n documentAddressUpdateSchema,\n type DocumentAddressCreateInput,\n type DocumentAddressDeleteInput,\n type DocumentAddressUpdateInput,\n} from '../data/validators'\nimport { SalesDocumentAddress, SalesOrder, SalesQuote } from '../data/entities'\nimport { ensureOrganizationScope, ensureSameScope, ensureTenantScope, assertFound, extractUndoPayload } from './shared'\nimport { loadSalesSettings } from './settings'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { E } from '#generated/entities.ids.generated'\n\nconst DOCUMENT_ADDRESS_ENTITY_TYPE = E.sales.sales_document_address\n\ntype DocumentAddressSnapshot = {\n id: string\n organizationId: string\n tenantId: string\n documentId: string\n documentKind: 'order' | 'quote'\n customerAddressId: string | null\n name: string | null\n purpose: string | null\n companyName: string | null\n addressLine1: string\n addressLine2: string | null\n buildingNumber: string | null\n flatNumber: string | null\n city: string | null\n region: string | null\n postalCode: string | null\n country: string | null\n latitude: number | null\n longitude: number | null\n}\n\ntype DocumentAddressUndoPayload = {\n before?: DocumentAddressSnapshot | null\n after?: DocumentAddressSnapshot | null\n}\n\nfunction snapshotDocumentAddress(entity: SalesDocumentAddress): DocumentAddressSnapshot {\n return {\n id: entity.id,\n organizationId: entity.organizationId,\n tenantId: entity.tenantId,\n documentId: entity.documentId,\n documentKind: entity.documentKind as 'order' | 'quote',\n customerAddressId: entity.customerAddressId ?? null,\n name: entity.name ?? null,\n purpose: entity.purpose ?? null,\n companyName: entity.companyName ?? null,\n addressLine1: entity.addressLine1,\n addressLine2: entity.addressLine2 ?? null,\n buildingNumber: entity.buildingNumber ?? null,\n flatNumber: entity.flatNumber ?? null,\n city: entity.city ?? null,\n region: entity.region ?? null,\n postalCode: entity.postalCode ?? null,\n country: entity.country ?? null,\n latitude: entity.latitude ?? null,\n longitude: entity.longitude ?? null,\n }\n}\n\nasync function loadDocumentAddressSnapshot(\n em: EntityManager,\n id: string\n): Promise<DocumentAddressSnapshot | null> {\n const entity = await findOneWithDecryption(em, SalesDocumentAddress, { id }, {})\n return entity ? snapshotDocumentAddress(entity) : null\n}\n\nfunction applyDocumentAddressSnapshot(em: EntityManager, entity: SalesDocumentAddress, snapshot: DocumentAddressSnapshot): void {\n entity.organizationId = snapshot.organizationId\n entity.tenantId = snapshot.tenantId\n entity.documentId = snapshot.documentId\n entity.documentKind = snapshot.documentKind\n entity.customerAddressId = snapshot.customerAddressId\n entity.name = snapshot.name\n entity.purpose = snapshot.purpose\n entity.companyName = snapshot.companyName\n entity.addressLine1 = snapshot.addressLine1\n entity.addressLine2 = snapshot.addressLine2\n entity.buildingNumber = snapshot.buildingNumber\n entity.flatNumber = snapshot.flatNumber\n entity.city = snapshot.city\n entity.region = snapshot.region\n entity.postalCode = snapshot.postalCode\n entity.country = snapshot.country\n entity.latitude = snapshot.latitude\n entity.longitude = snapshot.longitude\n entity.order = snapshot.documentKind === 'order' ? em.getReference(SalesOrder, snapshot.documentId) : null\n entity.quote = snapshot.documentKind === 'quote' ? em.getReference(SalesQuote, snapshot.documentId) : null\n}\n\nfunction assertDocumentAddressParent(entity: SalesDocumentAddress, input: { documentId: string; documentKind: 'order' | 'quote' }): void {\n if (entity.documentId !== input.documentId || entity.documentKind !== input.documentKind) {\n throw notFound('sales.document.address.not_found')\n }\n}\n\nasync function emitDocumentAddressIndexSideEffects(\n ctx: { container: { resolve: (name: string) => unknown } },\n action: 'created' | 'updated' | 'deleted',\n snapshot: DocumentAddressSnapshot\n): Promise<void> {\n let dataEngine: DataEngine | null = null\n try {\n dataEngine = ctx.container.resolve('dataEngine') as DataEngine\n } catch {\n dataEngine = null\n }\n if (!dataEngine) return\n await emitCrudSideEffects({\n dataEngine,\n action,\n entity: snapshot,\n identifiers: {\n id: snapshot.id,\n organizationId: snapshot.organizationId,\n tenantId: snapshot.tenantId,\n },\n indexer: { entityType: DOCUMENT_ADDRESS_ENTITY_TYPE },\n })\n}\n\nasync function requireDocument(\n em: EntityManager,\n kind: 'order' | 'quote',\n id: string,\n organizationId: string,\n tenantId: string\n): Promise<SalesOrder | SalesQuote> {\n const repo = kind === 'order' ? SalesOrder : SalesQuote\n const doc = await findOneWithDecryption(em, repo, { id, organizationId, tenantId }, {}, { tenantId, organizationId })\n if (!doc) {\n throw notFound('sales.document.not_found')\n }\n return doc\n}\n\nasync function assertAddressEditable(\n em: EntityManager,\n params: { organizationId: string; tenantId: string; status: string | null }\n): Promise<void> {\n const settings = await loadSalesSettings(em, {\n tenantId: params.tenantId,\n organizationId: params.organizationId,\n })\n const allowed = settings?.orderAddressEditableStatuses ?? null\n if (!Array.isArray(allowed)) return\n const { translate } = await resolveTranslations()\n if (allowed.length === 0) {\n throw new CrudHttpError(400, { error: translate('sales.orders.edit_addresses_blocked', 'Addresses cannot be changed for the current status.') })\n }\n if (!params.status || !allowed.includes(params.status)) {\n throw new CrudHttpError(400, { error: translate('sales.orders.edit_addresses_blocked', 'Addresses cannot be changed for the current status.') })\n }\n}\n\nconst createDocumentAddress: CommandHandler<DocumentAddressCreateInput, { id: string }> = {\n id: 'sales.document-addresses.create',\n async execute(rawInput, ctx) {\n const input = documentAddressCreateSchema.parse(rawInput)\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const document = await requireDocument(em, input.documentKind, input.documentId, input.organizationId, input.tenantId)\n if (input.documentKind === 'order') {\n await assertAddressEditable(em, {\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n status: (document as SalesOrder).status ?? null,\n })\n }\n\n const entity = em.create(SalesDocumentAddress, {\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n documentId: input.documentId,\n documentKind: input.documentKind,\n customerAddressId: input.customerAddressId ?? null,\n name: input.name ?? null,\n purpose: input.purpose ?? null,\n companyName: input.companyName ?? null,\n addressLine1: input.addressLine1,\n addressLine2: input.addressLine2 ?? null,\n buildingNumber: input.buildingNumber ?? null,\n flatNumber: input.flatNumber ?? null,\n city: input.city ?? null,\n region: input.region ?? null,\n postalCode: input.postalCode ?? null,\n country: input.country ?? null,\n latitude: input.latitude ?? null,\n longitude: input.longitude ?? null,\n order: input.documentKind === 'order' ? (document as SalesOrder) : null,\n quote: input.documentKind === 'quote' ? (document as SalesQuote) : null,\n })\n await em.persist(entity).flush()\n return { id: entity.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return result?.id ? loadDocumentAddressSnapshot(em, result.id) : null\n },\n buildLog: async ({ result, snapshots }) => {\n const after = snapshots.after as DocumentAddressSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.document_addresses.create', 'Add document address'),\n resourceKind: 'sales.document_address',\n resourceId: result.id,\n parentResourceKind: after.documentKind === 'order' ? 'sales.order' : 'sales.quote',\n parentResourceId: after.documentId,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotAfter: after,\n payload: { undo: { after } satisfies DocumentAddressUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DocumentAddressUndoPayload>(logEntry)\n const after = payload?.after\n if (!after) return\n ensureTenantScope(ctx, after.tenantId)\n ensureOrganizationScope(ctx, after.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = await findOneWithDecryption(em, SalesDocumentAddress, { id: after.id }, {}, { tenantId: after.tenantId, organizationId: after.organizationId })\n if (!entity) return\n await em.remove(entity).flush()\n await emitDocumentAddressIndexSideEffects(ctx, 'deleted', after)\n },\n}\n\nconst updateDocumentAddress: CommandHandler<DocumentAddressUpdateInput, { id: string }> = {\n id: 'sales.document-addresses.update',\n async prepare(rawInput, ctx) {\n const parsed = documentAddressUpdateSchema.parse(rawInput)\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadDocumentAddressSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const input = documentAddressUpdateSchema.parse(rawInput)\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = assertFound(\n await findOneWithDecryption(em, SalesDocumentAddress, { id: input.id }, {}, { tenantId: input.tenantId, organizationId: input.organizationId }),\n 'sales.document.address.not_found'\n )\n ensureSameScope(entity, input.organizationId, input.tenantId)\n assertDocumentAddressParent(entity, input)\n const document = await requireDocument(em, input.documentKind, input.documentId, input.organizationId, input.tenantId)\n if (input.documentKind === 'order') {\n await assertAddressEditable(em, {\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n status: (document as SalesOrder).status ?? null,\n })\n }\n\n entity.documentId = input.documentId\n entity.documentKind = input.documentKind\n entity.customerAddressId = input.customerAddressId ?? null\n entity.name = input.name ?? null\n entity.purpose = input.purpose ?? null\n entity.companyName = input.companyName ?? null\n entity.addressLine1 = input.addressLine1\n entity.addressLine2 = input.addressLine2 ?? null\n entity.buildingNumber = input.buildingNumber ?? null\n entity.flatNumber = input.flatNumber ?? null\n entity.city = input.city ?? null\n entity.region = input.region ?? null\n entity.postalCode = input.postalCode ?? null\n entity.country = input.country ?? null\n entity.latitude = input.latitude ?? null\n entity.longitude = input.longitude ?? null\n\n await em.flush()\n return { id: entity.id }\n },\n captureAfter: async (_input, result, ctx) => {\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n return result?.id ? loadDocumentAddressSnapshot(em, result.id) : null\n },\n buildLog: async ({ result, snapshots }) => {\n const before = snapshots.before as DocumentAddressSnapshot | undefined\n const after = snapshots.after as DocumentAddressSnapshot | undefined\n if (!after) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.document_addresses.update', 'Update document address'),\n resourceKind: 'sales.document_address',\n resourceId: result.id,\n parentResourceKind: after.documentKind === 'order' ? 'sales.order' : 'sales.quote',\n parentResourceId: after.documentId,\n tenantId: after.tenantId,\n organizationId: after.organizationId,\n snapshotBefore: before ?? null,\n snapshotAfter: after,\n payload: { undo: { before: before ?? null, after } satisfies DocumentAddressUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DocumentAddressUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity =\n (await findOneWithDecryption(em, SalesDocumentAddress, { id: before.id }, {}, { tenantId: before.tenantId, organizationId: before.organizationId })) ??\n em.create(SalesDocumentAddress, { id: before.id } as Partial<SalesDocumentAddress>)\n applyDocumentAddressSnapshot(em, entity, before)\n await em.persist(entity).flush()\n await emitDocumentAddressIndexSideEffects(ctx, 'updated', before)\n },\n}\n\nconst deleteDocumentAddress: CommandHandler<\n DocumentAddressDeleteInput,\n { ok: true; id: string }\n> = {\n id: 'sales.document-addresses.delete',\n async prepare(rawInput, ctx) {\n const parsed = documentAddressDeleteSchema.parse(rawInput)\n const em = ctx.container.resolve('em') as EntityManager\n const snapshot = await loadDocumentAddressSnapshot(em, parsed.id)\n return snapshot ? { before: snapshot } : {}\n },\n async execute(rawInput, ctx) {\n const input = documentAddressDeleteSchema.parse(rawInput)\n ensureTenantScope(ctx, input.tenantId)\n ensureOrganizationScope(ctx, input.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const entity = assertFound(\n await findOneWithDecryption(em, SalesDocumentAddress, { id: input.id }, {}, { tenantId: input.tenantId, organizationId: input.organizationId }),\n 'sales.document.address.not_found'\n )\n ensureSameScope(entity, input.organizationId, input.tenantId)\n assertDocumentAddressParent(entity, input)\n const document = await requireDocument(em, input.documentKind, input.documentId, input.organizationId, input.tenantId)\n if (input.documentKind === 'order') {\n await assertAddressEditable(em, {\n organizationId: input.organizationId,\n tenantId: input.tenantId,\n status: (document as SalesOrder).status ?? null,\n })\n }\n await em.remove(entity).flush()\n return { ok: true, id: input.id }\n },\n buildLog: async ({ result, snapshots }) => {\n const before = snapshots.before as DocumentAddressSnapshot | undefined\n if (!before) return null\n const { translate } = await resolveTranslations()\n return {\n actionLabel: translate('sales.audit.document_addresses.delete', 'Remove document address'),\n resourceKind: 'sales.document_address',\n resourceId: result.id,\n parentResourceKind: before.documentKind === 'order' ? 'sales.order' : 'sales.quote',\n parentResourceId: before.documentId,\n tenantId: before.tenantId,\n organizationId: before.organizationId,\n snapshotBefore: before,\n payload: { undo: { before } satisfies DocumentAddressUndoPayload },\n }\n },\n undo: async ({ logEntry, ctx }) => {\n const payload = extractUndoPayload<DocumentAddressUndoPayload>(logEntry)\n const before = payload?.before\n if (!before) return\n ensureTenantScope(ctx, before.tenantId)\n ensureOrganizationScope(ctx, before.organizationId)\n const em = (ctx.container.resolve('em') as EntityManager).fork()\n const existing = await findOneWithDecryption(em, SalesDocumentAddress, { id: before.id }, {}, { tenantId: before.tenantId, organizationId: before.organizationId })\n const entity = existing ?? em.create(SalesDocumentAddress, { id: before.id } as Partial<SalesDocumentAddress>)\n applyDocumentAddressSnapshot(em, entity, before)\n await em.persist(entity).flush()\n await emitDocumentAddressIndexSideEffects(ctx, 'created', before)\n },\n}\n\nexport const documentAddressCommands = [createDocumentAddress, updateDocumentAddress, deleteDocumentAddress]\n\nregisterCommand(createDocumentAddress)\nregisterCommand(updateDocumentAddress)\nregisterCommand(deleteDocumentAddress)\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,uBAA4C;AACrD,SAAS,2BAA2B;AAGpC,SAAS,eAAe,gBAAgB;AACxC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AACP,SAAS,sBAAsB,YAAY,kBAAkB;AAC7D,SAAS,yBAAyB,iBAAiB,mBAAmB,aAAa,0BAA0B;AAC7G,SAAS,yBAAyB;AAClC,SAAS,2BAA2B;AACpC,SAAS,6BAA6B;AACtC,SAAS,SAAS;AAElB,MAAM,+BAA+B,EAAE,MAAM;AA6B7C,SAAS,wBAAwB,QAAuD;AACtF,SAAO;AAAA,IACL,IAAI,OAAO;AAAA,IACX,gBAAgB,OAAO;AAAA,IACvB,UAAU,OAAO;AAAA,IACjB,YAAY,OAAO;AAAA,IACnB,cAAc,OAAO;AAAA,IACrB,mBAAmB,OAAO,qBAAqB;AAAA,IAC/C,MAAM,OAAO,QAAQ;AAAA,IACrB,SAAS,OAAO,WAAW;AAAA,IAC3B,aAAa,OAAO,eAAe;AAAA,IACnC,cAAc,OAAO;AAAA,IACrB,cAAc,OAAO,gBAAgB;AAAA,IACrC,gBAAgB,OAAO,kBAAkB;AAAA,IACzC,YAAY,OAAO,cAAc;AAAA,IACjC,MAAM,OAAO,QAAQ;AAAA,IACrB,QAAQ,OAAO,UAAU;AAAA,IACzB,YAAY,OAAO,cAAc;AAAA,IACjC,SAAS,OAAO,WAAW;AAAA,IAC3B,UAAU,OAAO,YAAY;AAAA,IAC7B,WAAW,OAAO,aAAa;AAAA,EACjC;AACF;AAEA,eAAe,4BACb,IACA,IACyC;AACzC,QAAM,SAAS,MAAM,sBAAsB,IAAI,sBAAsB,EAAE,GAAG,GAAG,CAAC,CAAC;AAC/E,SAAO,SAAS,wBAAwB,MAAM,IAAI;AACpD;AAEA,SAAS,6BAA6B,IAAmB,QAA8B,UAAyC;AAC9H,SAAO,iBAAiB,SAAS;AACjC,SAAO,WAAW,SAAS;AAC3B,SAAO,aAAa,SAAS;AAC7B,SAAO,eAAe,SAAS;AAC/B,SAAO,oBAAoB,SAAS;AACpC,SAAO,OAAO,SAAS;AACvB,SAAO,UAAU,SAAS;AAC1B,SAAO,cAAc,SAAS;AAC9B,SAAO,eAAe,SAAS;AAC/B,SAAO,eAAe,SAAS;AAC/B,SAAO,iBAAiB,SAAS;AACjC,SAAO,aAAa,SAAS;AAC7B,SAAO,OAAO,SAAS;AACvB,SAAO,SAAS,SAAS;AACzB,SAAO,aAAa,SAAS;AAC7B,SAAO,UAAU,SAAS;AAC1B,SAAO,WAAW,SAAS;AAC3B,SAAO,YAAY,SAAS;AAC5B,SAAO,QAAQ,SAAS,iBAAiB,UAAU,GAAG,aAAa,YAAY,SAAS,UAAU,IAAI;AACtG,SAAO,QAAQ,SAAS,iBAAiB,UAAU,GAAG,aAAa,YAAY,SAAS,UAAU,IAAI;AACxG;AAEA,SAAS,4BAA4B,QAA8B,OAAsE;AACvI,MAAI,OAAO,eAAe,MAAM,cAAc,OAAO,iBAAiB,MAAM,cAAc;AACxF,UAAM,SAAS,kCAAkC;AAAA,EACnD;AACF;AAEA,eAAe,oCACb,KACA,QACA,UACe;AACf,MAAI,aAAgC;AACpC,MAAI;AACF,iBAAa,IAAI,UAAU,QAAQ,YAAY;AAAA,EACjD,QAAQ;AACN,iBAAa;AAAA,EACf;AACA,MAAI,CAAC,WAAY;AACjB,QAAM,oBAAoB;AAAA,IACxB;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,aAAa;AAAA,MACX,IAAI,SAAS;AAAA,MACb,gBAAgB,SAAS;AAAA,MACzB,UAAU,SAAS;AAAA,IACrB;AAAA,IACA,SAAS,EAAE,YAAY,6BAA6B;AAAA,EACtD,CAAC;AACH;AAEA,eAAe,gBACb,IACA,MACA,IACA,gBACA,UACkC;AAClC,QAAM,OAAO,SAAS,UAAU,aAAa;AAC7C,QAAM,MAAM,MAAM,sBAAsB,IAAI,MAAM,EAAE,IAAI,gBAAgB,SAAS,GAAG,CAAC,GAAG,EAAE,UAAU,eAAe,CAAC;AACpH,MAAI,CAAC,KAAK;AACR,UAAM,SAAS,0BAA0B;AAAA,EAC3C;AACA,SAAO;AACT;AAEA,eAAe,sBACb,IACA,QACe;AACf,QAAM,WAAW,MAAM,kBAAkB,IAAI;AAAA,IAC3C,UAAU,OAAO;AAAA,IACjB,gBAAgB,OAAO;AAAA,EACzB,CAAC;AACD,QAAM,UAAU,UAAU,gCAAgC;AAC1D,MAAI,CAAC,MAAM,QAAQ,OAAO,EAAG;AAC7B,QAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,MAAI,QAAQ,WAAW,GAAG;AACxB,UAAM,IAAI,cAAc,KAAK,EAAE,OAAO,UAAU,uCAAuC,qDAAqD,EAAE,CAAC;AAAA,EACjJ;AACA,MAAI,CAAC,OAAO,UAAU,CAAC,QAAQ,SAAS,OAAO,MAAM,GAAG;AACtD,UAAM,IAAI,cAAc,KAAK,EAAE,OAAO,UAAU,uCAAuC,qDAAqD,EAAE,CAAC;AAAA,EACjJ;AACF;AAEA,MAAM,wBAAoF;AAAA,EACxF,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,QAAQ,4BAA4B,MAAM,QAAQ;AACxD,sBAAkB,KAAK,MAAM,QAAQ;AACrC,4BAAwB,KAAK,MAAM,cAAc;AACjD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,WAAW,MAAM,gBAAgB,IAAI,MAAM,cAAc,MAAM,YAAY,MAAM,gBAAgB,MAAM,QAAQ;AACrH,QAAI,MAAM,iBAAiB,SAAS;AAClC,YAAM,sBAAsB,IAAI;AAAA,QAC9B,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,QAChB,QAAS,SAAwB,UAAU;AAAA,MAC7C,CAAC;AAAA,IACH;AAEA,UAAM,SAAS,GAAG,OAAO,sBAAsB;AAAA,MAC7C,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,MAChB,YAAY,MAAM;AAAA,MAClB,cAAc,MAAM;AAAA,MACpB,mBAAmB,MAAM,qBAAqB;AAAA,MAC9C,MAAM,MAAM,QAAQ;AAAA,MACpB,SAAS,MAAM,WAAW;AAAA,MAC1B,aAAa,MAAM,eAAe;AAAA,MAClC,cAAc,MAAM;AAAA,MACpB,cAAc,MAAM,gBAAgB;AAAA,MACpC,gBAAgB,MAAM,kBAAkB;AAAA,MACxC,YAAY,MAAM,cAAc;AAAA,MAChC,MAAM,MAAM,QAAQ;AAAA,MACpB,QAAQ,MAAM,UAAU;AAAA,MACxB,YAAY,MAAM,cAAc;AAAA,MAChC,SAAS,MAAM,WAAW;AAAA,MAC1B,UAAU,MAAM,YAAY;AAAA,MAC5B,WAAW,MAAM,aAAa;AAAA,MAC9B,OAAO,MAAM,iBAAiB,UAAW,WAA0B;AAAA,MACnE,OAAO,MAAM,iBAAiB,UAAW,WAA0B;AAAA,IACrE,CAAC;AACD,UAAM,GAAG,QAAQ,MAAM,EAAE,MAAM;AAC/B,WAAO,EAAE,IAAI,OAAO,GAAG;AAAA,EACzB;AAAA,EACA,cAAc,OAAO,QAAQ,QAAQ,QAAQ;AAC3C,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,WAAO,QAAQ,KAAK,4BAA4B,IAAI,OAAO,EAAE,IAAI;AAAA,EACnE;AAAA,EACA,UAAU,OAAO,EAAE,QAAQ,UAAU,MAAM;AACzC,UAAM,QAAQ,UAAU;AACxB,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,WAAO;AAAA,MACL,aAAa,UAAU,yCAAyC,sBAAsB;AAAA,MACtF,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,oBAAoB,MAAM,iBAAiB,UAAU,gBAAgB;AAAA,MACrE,kBAAkB,MAAM;AAAA,MACxB,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,MACtB,eAAe;AAAA,MACf,SAAS,EAAE,MAAM,EAAE,MAAM,EAAuC;AAAA,IAClE;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,UAAU,mBAA+C,QAAQ;AACvE,UAAM,QAAQ,SAAS;AACvB,QAAI,CAAC,MAAO;AACZ,sBAAkB,KAAK,MAAM,QAAQ;AACrC,4BAAwB,KAAK,MAAM,cAAc;AACjD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,SAAS,MAAM,sBAAsB,IAAI,sBAAsB,EAAE,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe,CAAC;AAC7J,QAAI,CAAC,OAAQ;AACb,UAAM,GAAG,OAAO,MAAM,EAAE,MAAM;AAC9B,UAAM,oCAAoC,KAAK,WAAW,KAAK;AAAA,EACjE;AACF;AAEA,MAAM,wBAAoF;AAAA,EACxF,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,4BAA4B,MAAM,QAAQ;AACzD,UAAM,KAAK,IAAI,UAAU,QAAQ,IAAI;AACrC,UAAM,WAAW,MAAM,4BAA4B,IAAI,OAAO,EAAE;AAChE,WAAO,WAAW,EAAE,QAAQ,SAAS,IAAI,CAAC;AAAA,EAC5C;AAAA,EACA,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,QAAQ,4BAA4B,MAAM,QAAQ;AACxD,sBAAkB,KAAK,MAAM,QAAQ;AACrC,4BAAwB,KAAK,MAAM,cAAc;AACjD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,SAAS;AAAA,MACb,MAAM,sBAAsB,IAAI,sBAAsB,EAAE,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe,CAAC;AAAA,MAC9I;AAAA,IACF;AACA,oBAAgB,QAAQ,MAAM,gBAAgB,MAAM,QAAQ;AAC5D,gCAA4B,QAAQ,KAAK;AACzC,UAAM,WAAW,MAAM,gBAAgB,IAAI,MAAM,cAAc,MAAM,YAAY,MAAM,gBAAgB,MAAM,QAAQ;AACrH,QAAI,MAAM,iBAAiB,SAAS;AAClC,YAAM,sBAAsB,IAAI;AAAA,QAC9B,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,QAChB,QAAS,SAAwB,UAAU;AAAA,MAC7C,CAAC;AAAA,IACH;AAEA,WAAO,aAAa,MAAM;AAC1B,WAAO,eAAe,MAAM;AAC5B,WAAO,oBAAoB,MAAM,qBAAqB;AACtD,WAAO,OAAO,MAAM,QAAQ;AAC5B,WAAO,UAAU,MAAM,WAAW;AAClC,WAAO,cAAc,MAAM,eAAe;AAC1C,WAAO,eAAe,MAAM;AAC5B,WAAO,eAAe,MAAM,gBAAgB;AAC5C,WAAO,iBAAiB,MAAM,kBAAkB;AAChD,WAAO,aAAa,MAAM,cAAc;AACxC,WAAO,OAAO,MAAM,QAAQ;AAC5B,WAAO,SAAS,MAAM,UAAU;AAChC,WAAO,aAAa,MAAM,cAAc;AACxC,WAAO,UAAU,MAAM,WAAW;AAClC,WAAO,WAAW,MAAM,YAAY;AACpC,WAAO,YAAY,MAAM,aAAa;AAEtC,UAAM,GAAG,MAAM;AACf,WAAO,EAAE,IAAI,OAAO,GAAG;AAAA,EACzB;AAAA,EACA,cAAc,OAAO,QAAQ,QAAQ,QAAQ;AAC3C,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,WAAO,QAAQ,KAAK,4BAA4B,IAAI,OAAO,EAAE,IAAI;AAAA,EACnE;AAAA,EACA,UAAU,OAAO,EAAE,QAAQ,UAAU,MAAM;AACzC,UAAM,SAAS,UAAU;AACzB,UAAM,QAAQ,UAAU;AACxB,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,WAAO;AAAA,MACL,aAAa,UAAU,yCAAyC,yBAAyB;AAAA,MACzF,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,oBAAoB,MAAM,iBAAiB,UAAU,gBAAgB;AAAA,MACrE,kBAAkB,MAAM;AAAA,MACxB,UAAU,MAAM;AAAA,MAChB,gBAAgB,MAAM;AAAA,MACtB,gBAAgB,UAAU;AAAA,MAC1B,eAAe;AAAA,MACf,SAAS,EAAE,MAAM,EAAE,QAAQ,UAAU,MAAM,MAAM,EAAuC;AAAA,IAC1F;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,UAAU,mBAA+C,QAAQ;AACvE,UAAM,SAAS,SAAS;AACxB,QAAI,CAAC,OAAQ;AACb,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAClD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,SACH,MAAM,sBAAsB,IAAI,sBAAsB,EAAE,IAAI,OAAO,GAAG,GAAG,CAAC,GAAG,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe,CAAC,KAClJ,GAAG,OAAO,sBAAsB,EAAE,IAAI,OAAO,GAAG,CAAkC;AACpF,iCAA6B,IAAI,QAAQ,MAAM;AAC/C,UAAM,GAAG,QAAQ,MAAM,EAAE,MAAM;AAC/B,UAAM,oCAAoC,KAAK,WAAW,MAAM;AAAA,EAClE;AACF;AAEA,MAAM,wBAGF;AAAA,EACF,IAAI;AAAA,EACJ,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,SAAS,4BAA4B,MAAM,QAAQ;AACzD,UAAM,KAAK,IAAI,UAAU,QAAQ,IAAI;AACrC,UAAM,WAAW,MAAM,4BAA4B,IAAI,OAAO,EAAE;AAChE,WAAO,WAAW,EAAE,QAAQ,SAAS,IAAI,CAAC;AAAA,EAC5C;AAAA,EACA,MAAM,QAAQ,UAAU,KAAK;AAC3B,UAAM,QAAQ,4BAA4B,MAAM,QAAQ;AACxD,sBAAkB,KAAK,MAAM,QAAQ;AACrC,4BAAwB,KAAK,MAAM,cAAc;AACjD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,SAAS;AAAA,MACb,MAAM,sBAAsB,IAAI,sBAAsB,EAAE,IAAI,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,UAAU,MAAM,UAAU,gBAAgB,MAAM,eAAe,CAAC;AAAA,MAC9I;AAAA,IACF;AACA,oBAAgB,QAAQ,MAAM,gBAAgB,MAAM,QAAQ;AAC5D,gCAA4B,QAAQ,KAAK;AACzC,UAAM,WAAW,MAAM,gBAAgB,IAAI,MAAM,cAAc,MAAM,YAAY,MAAM,gBAAgB,MAAM,QAAQ;AACrH,QAAI,MAAM,iBAAiB,SAAS;AAClC,YAAM,sBAAsB,IAAI;AAAA,QAC9B,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,QAChB,QAAS,SAAwB,UAAU;AAAA,MAC7C,CAAC;AAAA,IACH;AACA,UAAM,GAAG,OAAO,MAAM,EAAE,MAAM;AAC9B,WAAO,EAAE,IAAI,MAAM,IAAI,MAAM,GAAG;AAAA,EAClC;AAAA,EACA,UAAU,OAAO,EAAE,QAAQ,UAAU,MAAM;AACzC,UAAM,SAAS,UAAU;AACzB,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,WAAO;AAAA,MACL,aAAa,UAAU,yCAAyC,yBAAyB;AAAA,MACzF,cAAc;AAAA,MACd,YAAY,OAAO;AAAA,MACnB,oBAAoB,OAAO,iBAAiB,UAAU,gBAAgB;AAAA,MACtE,kBAAkB,OAAO;AAAA,MACzB,UAAU,OAAO;AAAA,MACjB,gBAAgB,OAAO;AAAA,MACvB,gBAAgB;AAAA,MAChB,SAAS,EAAE,MAAM,EAAE,OAAO,EAAuC;AAAA,IACnE;AAAA,EACF;AAAA,EACA,MAAM,OAAO,EAAE,UAAU,IAAI,MAAM;AACjC,UAAM,UAAU,mBAA+C,QAAQ;AACvE,UAAM,SAAS,SAAS;AACxB,QAAI,CAAC,OAAQ;AACb,sBAAkB,KAAK,OAAO,QAAQ;AACtC,4BAAwB,KAAK,OAAO,cAAc;AAClD,UAAM,KAAM,IAAI,UAAU,QAAQ,IAAI,EAAoB,KAAK;AAC/D,UAAM,WAAW,MAAM,sBAAsB,IAAI,sBAAsB,EAAE,IAAI,OAAO,GAAG,GAAG,CAAC,GAAG,EAAE,UAAU,OAAO,UAAU,gBAAgB,OAAO,eAAe,CAAC;AAClK,UAAM,SAAS,YAAY,GAAG,OAAO,sBAAsB,EAAE,IAAI,OAAO,GAAG,CAAkC;AAC7G,iCAA6B,IAAI,QAAQ,MAAM;AAC/C,UAAM,GAAG,QAAQ,MAAM,EAAE,MAAM;AAC/B,UAAM,oCAAoC,KAAK,WAAW,MAAM;AAAA,EAClE;AACF;AAEO,MAAM,0BAA0B,CAAC,uBAAuB,uBAAuB,qBAAqB;AAE3G,gBAAgB,qBAAqB;AACrC,gBAAgB,qBAAqB;AACrC,gBAAgB,qBAAqB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
requireId
|
|
9
9
|
} from "@open-mercato/shared/lib/commands/helpers";
|
|
10
10
|
import { LockMode } from "@mikro-orm/core";
|
|
11
|
-
import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
|
|
11
|
+
import { CrudHttpError, notFound } from "@open-mercato/shared/lib/crud/errors";
|
|
12
12
|
import {
|
|
13
13
|
deriveResourceFromCommandId,
|
|
14
14
|
invalidateCrudCache
|
|
@@ -3421,7 +3421,7 @@ const deleteQuoteCommand = {
|
|
|
3421
3421
|
const em = ctx.container.resolve("em").fork();
|
|
3422
3422
|
const quote = await findOneWithDecryption(em, SalesQuote, { id });
|
|
3423
3423
|
if (!quote)
|
|
3424
|
-
throw
|
|
3424
|
+
throw notFound("Sales quote not found");
|
|
3425
3425
|
ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
|
|
3426
3426
|
const [addresses, notes, tags, adjustments, lines] = await Promise.all([
|
|
3427
3427
|
findWithDecryption(
|
|
@@ -3545,7 +3545,7 @@ const updateQuoteCommand = {
|
|
|
3545
3545
|
deletedAt: null
|
|
3546
3546
|
});
|
|
3547
3547
|
if (!quote)
|
|
3548
|
-
throw
|
|
3548
|
+
throw notFound("Sales quote not found");
|
|
3549
3549
|
ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
|
|
3550
3550
|
await enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
|
|
3551
3551
|
const shouldInvalidateSentToken = (quote.status ?? null) === "sent";
|
|
@@ -3757,7 +3757,7 @@ const updateOrderCommand = {
|
|
|
3757
3757
|
deletedAt: null
|
|
3758
3758
|
});
|
|
3759
3759
|
if (!order)
|
|
3760
|
-
throw
|
|
3760
|
+
throw notFound("Sales order not found");
|
|
3761
3761
|
ensureOrderScope(ctx, order.organizationId, order.tenantId);
|
|
3762
3762
|
await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
|
|
3763
3763
|
const previousStatus = normalizeStatusValue(order.status);
|
|
@@ -4306,7 +4306,7 @@ const deleteOrderCommand = {
|
|
|
4306
4306
|
const em = ctx.container.resolve("em").fork();
|
|
4307
4307
|
const order = await findOneWithDecryption(em, SalesOrder, { id });
|
|
4308
4308
|
if (!order)
|
|
4309
|
-
throw
|
|
4309
|
+
throw notFound("Sales order not found");
|
|
4310
4310
|
ensureOrderScope(ctx, order.organizationId, order.tenantId);
|
|
4311
4311
|
const shipments = await em.find(SalesShipment, { order: order.id });
|
|
4312
4312
|
const shipmentIds = shipments.map((entry) => entry.id);
|
|
@@ -4479,22 +4479,18 @@ const convertQuoteToOrderCommand = {
|
|
|
4479
4479
|
);
|
|
4480
4480
|
const { translate } = await resolveTranslations();
|
|
4481
4481
|
if (!quote)
|
|
4482
|
-
throw
|
|
4483
|
-
error
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
)
|
|
4487
|
-
});
|
|
4482
|
+
throw notFound(translate(
|
|
4483
|
+
"sales.documents.detail.error",
|
|
4484
|
+
"Document not found or inaccessible."
|
|
4485
|
+
));
|
|
4488
4486
|
ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
|
|
4489
4487
|
await enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
|
|
4490
4488
|
const snapshot = await loadQuoteSnapshot(em, payload.quoteId);
|
|
4491
4489
|
if (!snapshot)
|
|
4492
|
-
throw
|
|
4493
|
-
error
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
)
|
|
4497
|
-
});
|
|
4490
|
+
throw notFound(translate(
|
|
4491
|
+
"sales.documents.detail.error",
|
|
4492
|
+
"Document not found or inaccessible."
|
|
4493
|
+
));
|
|
4498
4494
|
const orderId = payload.orderId ?? quote.id;
|
|
4499
4495
|
const existingOrder = await findOneWithDecryption(em, SalesOrder, {
|
|
4500
4496
|
id: orderId,
|
|
@@ -4942,7 +4938,7 @@ const orderLineUpsertCommand = {
|
|
|
4942
4938
|
deletedAt: null
|
|
4943
4939
|
});
|
|
4944
4940
|
if (!order)
|
|
4945
|
-
throw
|
|
4941
|
+
throw notFound("Sales order not found");
|
|
4946
4942
|
ensureOrderScope(ctx, order.organizationId, order.tenantId);
|
|
4947
4943
|
await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
|
|
4948
4944
|
const [existingLines, adjustments] = await Promise.all([
|
|
@@ -5195,12 +5191,10 @@ const orderLineDeleteCommand = {
|
|
|
5195
5191
|
deletedAt: null
|
|
5196
5192
|
});
|
|
5197
5193
|
if (!order)
|
|
5198
|
-
throw
|
|
5199
|
-
error
|
|
5200
|
-
|
|
5201
|
-
|
|
5202
|
-
)
|
|
5203
|
-
});
|
|
5194
|
+
throw notFound(translate(
|
|
5195
|
+
"sales.documents.detail.error",
|
|
5196
|
+
"Document not found or inaccessible."
|
|
5197
|
+
));
|
|
5204
5198
|
ensureOrderScope(ctx, order.organizationId, order.tenantId);
|
|
5205
5199
|
await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
|
|
5206
5200
|
const shipmentCount = await em.count(SalesShipmentItem, {
|
|
@@ -5227,12 +5221,10 @@ const orderLineDeleteCommand = {
|
|
|
5227
5221
|
);
|
|
5228
5222
|
const filtered = existingLines.filter((line) => line.id !== parsed.id);
|
|
5229
5223
|
if (filtered.length === existingLines.length) {
|
|
5230
|
-
throw
|
|
5231
|
-
error
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
)
|
|
5235
|
-
});
|
|
5224
|
+
throw notFound(translate(
|
|
5225
|
+
"sales.documents.detail.error",
|
|
5226
|
+
"Document not found or inaccessible."
|
|
5227
|
+
));
|
|
5236
5228
|
}
|
|
5237
5229
|
const sourceInputs = filtered.map((line, index) => ({
|
|
5238
5230
|
...mapOrderLineEntityToSnapshot(line),
|
|
@@ -5360,7 +5352,7 @@ const quoteLineUpsertCommand = {
|
|
|
5360
5352
|
deletedAt: null
|
|
5361
5353
|
});
|
|
5362
5354
|
if (!quote)
|
|
5363
|
-
throw
|
|
5355
|
+
throw notFound("Sales quote not found");
|
|
5364
5356
|
ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
|
|
5365
5357
|
await enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
|
|
5366
5358
|
const [existingLines, adjustments] = await Promise.all([
|
|
@@ -5610,7 +5602,7 @@ const quoteLineDeleteCommand = {
|
|
|
5610
5602
|
deletedAt: null
|
|
5611
5603
|
});
|
|
5612
5604
|
if (!quote)
|
|
5613
|
-
throw
|
|
5605
|
+
throw notFound("Sales quote not found");
|
|
5614
5606
|
ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
|
|
5615
5607
|
await enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
|
|
5616
5608
|
const existingLines = await em.find(
|
|
@@ -5625,7 +5617,7 @@ const quoteLineDeleteCommand = {
|
|
|
5625
5617
|
);
|
|
5626
5618
|
const filtered = existingLines.filter((line) => line.id !== parsed.id);
|
|
5627
5619
|
if (filtered.length === existingLines.length) {
|
|
5628
|
-
throw
|
|
5620
|
+
throw notFound("Quote line not found");
|
|
5629
5621
|
}
|
|
5630
5622
|
const sourceInputs = filtered.map((line, index) => ({
|
|
5631
5623
|
...mapQuoteLineEntityToSnapshot(line),
|
|
@@ -5753,7 +5745,7 @@ const orderAdjustmentUpsertCommand = {
|
|
|
5753
5745
|
deletedAt: null
|
|
5754
5746
|
});
|
|
5755
5747
|
if (!order)
|
|
5756
|
-
throw
|
|
5748
|
+
throw notFound("Sales order not found");
|
|
5757
5749
|
ensureOrderScope(ctx, order.organizationId, order.tenantId);
|
|
5758
5750
|
await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
|
|
5759
5751
|
if (parsed.scope === "line") {
|
|
@@ -6006,7 +5998,7 @@ const orderAdjustmentDeleteCommand = {
|
|
|
6006
5998
|
deletedAt: null
|
|
6007
5999
|
});
|
|
6008
6000
|
if (!order)
|
|
6009
|
-
throw
|
|
6001
|
+
throw notFound("Sales order not found");
|
|
6010
6002
|
ensureOrderScope(ctx, order.organizationId, order.tenantId);
|
|
6011
6003
|
await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
|
|
6012
6004
|
const [existingLines, adjustments] = await Promise.all([
|
|
@@ -6019,7 +6011,7 @@ const orderAdjustmentDeleteCommand = {
|
|
|
6019
6011
|
]);
|
|
6020
6012
|
const filtered = adjustments.filter((adj) => adj.id !== parsed.id);
|
|
6021
6013
|
if (filtered.length === adjustments.length) {
|
|
6022
|
-
throw
|
|
6014
|
+
throw notFound("Adjustment not found");
|
|
6023
6015
|
}
|
|
6024
6016
|
const lineSnapshots = existingLines.map(mapOrderLineEntityToSnapshot);
|
|
6025
6017
|
const calcLines = lineSnapshots.map(
|
|
@@ -6163,7 +6155,7 @@ const quoteAdjustmentUpsertCommand = {
|
|
|
6163
6155
|
deletedAt: null
|
|
6164
6156
|
});
|
|
6165
6157
|
if (!quote)
|
|
6166
|
-
throw
|
|
6158
|
+
throw notFound("Sales quote not found");
|
|
6167
6159
|
ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
|
|
6168
6160
|
await enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
|
|
6169
6161
|
if (parsed.scope === "line") {
|
|
@@ -6414,7 +6406,7 @@ const quoteAdjustmentDeleteCommand = {
|
|
|
6414
6406
|
deletedAt: null
|
|
6415
6407
|
});
|
|
6416
6408
|
if (!quote)
|
|
6417
|
-
throw
|
|
6409
|
+
throw notFound("Sales quote not found");
|
|
6418
6410
|
ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
|
|
6419
6411
|
await enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
|
|
6420
6412
|
const [existingLines, adjustments] = await Promise.all([
|
|
@@ -6427,7 +6419,7 @@ const quoteAdjustmentDeleteCommand = {
|
|
|
6427
6419
|
]);
|
|
6428
6420
|
const filtered = adjustments.filter((adj) => adj.id !== parsed.id);
|
|
6429
6421
|
if (filtered.length === adjustments.length) {
|
|
6430
|
-
throw
|
|
6422
|
+
throw notFound("Adjustment not found");
|
|
6431
6423
|
}
|
|
6432
6424
|
const lineSnapshots = existingLines.map(mapQuoteLineEntityToSnapshot);
|
|
6433
6425
|
const calcLines = lineSnapshots.map(
|