@open-mercato/core 0.6.7-develop.6553.1.2ec7246e04 → 0.6.7-develop.6566.1.15385fa179

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.
Files changed (143) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/attachments/api/partitions/route.js.map +1 -1
  3. package/dist/modules/attachments/lib/reconcileOrganization.js +9 -7
  4. package/dist/modules/attachments/lib/reconcileOrganization.js.map +2 -2
  5. package/dist/modules/catalog/api/products/route.js.map +1 -1
  6. package/dist/modules/customers/api/companies/[id]/people/route.js +2 -2
  7. package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
  8. package/dist/modules/customers/api/deals/[id]/companies/route.js +2 -2
  9. package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
  10. package/dist/modules/customers/api/deals/[id]/people/route.js +2 -2
  11. package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
  12. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js +4 -4
  13. package/dist/modules/customers/api/dictionaries/[kind]/[id]/route.js.map +2 -2
  14. package/dist/modules/customers/api/entity-roles-factory.js +3 -3
  15. package/dist/modules/customers/api/entity-roles-factory.js.map +2 -2
  16. package/dist/modules/customers/api/labels/assign/route.js +2 -2
  17. package/dist/modules/customers/api/labels/assign/route.js.map +2 -2
  18. package/dist/modules/customers/api/labels/unassign/route.js +2 -2
  19. package/dist/modules/customers/api/labels/unassign/route.js.map +2 -2
  20. package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +3 -7
  21. package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +2 -2
  22. package/dist/modules/customers/api/people/[id]/companies/context.js +3 -3
  23. package/dist/modules/customers/api/people/[id]/companies/context.js.map +2 -2
  24. package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +2 -2
  25. package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
  26. package/dist/modules/customers/api/todos/route.js +2 -2
  27. package/dist/modules/customers/api/todos/route.js.map +2 -2
  28. package/dist/modules/customers/commands/addresses.js +3 -3
  29. package/dist/modules/customers/commands/addresses.js.map +2 -2
  30. package/dist/modules/customers/commands/comments.js +3 -3
  31. package/dist/modules/customers/commands/comments.js.map +2 -2
  32. package/dist/modules/customers/commands/companies.js +2 -2
  33. package/dist/modules/customers/commands/companies.js.map +2 -2
  34. package/dist/modules/customers/commands/deals.js +3 -3
  35. package/dist/modules/customers/commands/deals.js.map +2 -2
  36. package/dist/modules/customers/commands/dictionaries.js +3 -3
  37. package/dist/modules/customers/commands/dictionaries.js.map +2 -2
  38. package/dist/modules/customers/commands/entity-roles.js +3 -3
  39. package/dist/modules/customers/commands/entity-roles.js.map +2 -2
  40. package/dist/modules/customers/commands/interactions.js +6 -6
  41. package/dist/modules/customers/commands/interactions.js.map +2 -2
  42. package/dist/modules/customers/commands/labels.js +7 -7
  43. package/dist/modules/customers/commands/labels.js.map +2 -2
  44. package/dist/modules/customers/commands/people.js +3 -3
  45. package/dist/modules/customers/commands/people.js.map +2 -2
  46. package/dist/modules/customers/commands/personCompanyLinks.js +6 -6
  47. package/dist/modules/customers/commands/personCompanyLinks.js.map +2 -2
  48. package/dist/modules/customers/commands/pipeline-stages.js +3 -3
  49. package/dist/modules/customers/commands/pipeline-stages.js.map +2 -2
  50. package/dist/modules/customers/commands/pipelines.js +3 -3
  51. package/dist/modules/customers/commands/pipelines.js.map +2 -2
  52. package/dist/modules/customers/commands/shared.js +3 -3
  53. package/dist/modules/customers/commands/shared.js.map +2 -2
  54. package/dist/modules/customers/commands/tags.js +7 -7
  55. package/dist/modules/customers/commands/tags.js.map +2 -2
  56. package/dist/modules/customers/commands/todos.js +3 -3
  57. package/dist/modules/customers/commands/todos.js.map +2 -2
  58. package/dist/modules/customers/lib/personCompanies.js +4 -4
  59. package/dist/modules/customers/lib/personCompanies.js.map +2 -2
  60. package/dist/modules/perspectives/data/validators.js +4 -0
  61. package/dist/modules/perspectives/data/validators.js.map +2 -2
  62. package/dist/modules/sales/api/notes/route.js +2 -4
  63. package/dist/modules/sales/api/notes/route.js.map +2 -2
  64. package/dist/modules/sales/api/quotes/accept/route.js +2 -2
  65. package/dist/modules/sales/api/quotes/accept/route.js.map +2 -2
  66. package/dist/modules/sales/api/quotes/public/[token]/route.js +3 -7
  67. package/dist/modules/sales/api/quotes/public/[token]/route.js.map +2 -2
  68. package/dist/modules/sales/api/quotes/send/route.js +2 -2
  69. package/dist/modules/sales/api/quotes/send/route.js.map +2 -2
  70. package/dist/modules/sales/api/returns/[id]/route.js +2 -2
  71. package/dist/modules/sales/api/returns/[id]/route.js.map +2 -2
  72. package/dist/modules/sales/commands/configuration.js +11 -11
  73. package/dist/modules/sales/commands/configuration.js.map +2 -2
  74. package/dist/modules/sales/commands/documentAddresses.js +3 -3
  75. package/dist/modules/sales/commands/documentAddresses.js.map +2 -2
  76. package/dist/modules/sales/commands/documents.js +31 -39
  77. package/dist/modules/sales/commands/documents.js.map +2 -2
  78. package/dist/modules/sales/commands/notes.js +7 -7
  79. package/dist/modules/sales/commands/notes.js.map +2 -2
  80. package/dist/modules/sales/commands/payments.js +2 -2
  81. package/dist/modules/sales/commands/payments.js.map +2 -2
  82. package/dist/modules/sales/commands/returns.js +8 -8
  83. package/dist/modules/sales/commands/returns.js.map +2 -2
  84. package/dist/modules/sales/commands/shared.js +2 -2
  85. package/dist/modules/sales/commands/shared.js.map +2 -2
  86. package/dist/modules/sales/commands/shipments.js +5 -5
  87. package/dist/modules/sales/commands/shipments.js.map +2 -2
  88. package/dist/modules/sales/commands/statuses.js +2 -2
  89. package/dist/modules/sales/commands/statuses.js.map +2 -2
  90. package/dist/modules/sales/commands/tags.js +3 -3
  91. package/dist/modules/sales/commands/tags.js.map +2 -2
  92. package/package.json +8 -8
  93. package/src/modules/attachments/api/partitions/route.ts +1 -1
  94. package/src/modules/attachments/lib/reconcileOrganization.ts +16 -7
  95. package/src/modules/catalog/api/products/route.ts +1 -1
  96. package/src/modules/customer_accounts/i18n/de.json +12 -0
  97. package/src/modules/customer_accounts/i18n/en.json +12 -0
  98. package/src/modules/customer_accounts/i18n/es.json +34 -22
  99. package/src/modules/customer_accounts/i18n/pl.json +32 -20
  100. package/src/modules/customers/api/companies/[id]/people/route.ts +2 -2
  101. package/src/modules/customers/api/deals/[id]/companies/route.ts +2 -2
  102. package/src/modules/customers/api/deals/[id]/people/route.ts +2 -2
  103. package/src/modules/customers/api/dictionaries/[kind]/[id]/route.ts +4 -4
  104. package/src/modules/customers/api/entity-roles-factory.ts +3 -3
  105. package/src/modules/customers/api/labels/assign/route.ts +2 -2
  106. package/src/modules/customers/api/labels/unassign/route.ts +2 -2
  107. package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +3 -7
  108. package/src/modules/customers/api/people/[id]/companies/context.ts +3 -3
  109. package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +2 -2
  110. package/src/modules/customers/api/todos/route.ts +2 -2
  111. package/src/modules/customers/commands/addresses.ts +3 -3
  112. package/src/modules/customers/commands/comments.ts +3 -3
  113. package/src/modules/customers/commands/companies.ts +2 -2
  114. package/src/modules/customers/commands/deals.ts +3 -3
  115. package/src/modules/customers/commands/dictionaries.ts +3 -3
  116. package/src/modules/customers/commands/entity-roles.ts +3 -3
  117. package/src/modules/customers/commands/interactions.ts +6 -6
  118. package/src/modules/customers/commands/labels.ts +7 -7
  119. package/src/modules/customers/commands/people.ts +3 -3
  120. package/src/modules/customers/commands/personCompanyLinks.ts +6 -6
  121. package/src/modules/customers/commands/pipeline-stages.ts +3 -3
  122. package/src/modules/customers/commands/pipelines.ts +3 -3
  123. package/src/modules/customers/commands/shared.ts +3 -3
  124. package/src/modules/customers/commands/tags.ts +7 -7
  125. package/src/modules/customers/commands/todos.ts +3 -3
  126. package/src/modules/customers/lib/personCompanies.ts +4 -4
  127. package/src/modules/perspectives/data/validators.ts +4 -0
  128. package/src/modules/sales/api/notes/route.ts +2 -4
  129. package/src/modules/sales/api/quotes/accept/route.ts +2 -2
  130. package/src/modules/sales/api/quotes/public/[token]/route.ts +3 -7
  131. package/src/modules/sales/api/quotes/send/route.ts +2 -2
  132. package/src/modules/sales/api/returns/[id]/route.ts +2 -2
  133. package/src/modules/sales/commands/configuration.ts +11 -11
  134. package/src/modules/sales/commands/documentAddresses.ts +3 -3
  135. package/src/modules/sales/commands/documents.ts +23 -31
  136. package/src/modules/sales/commands/notes.ts +7 -7
  137. package/src/modules/sales/commands/payments.ts +2 -2
  138. package/src/modules/sales/commands/returns.ts +8 -8
  139. package/src/modules/sales/commands/shared.ts +2 -2
  140. package/src/modules/sales/commands/shipments.ts +5 -5
  141. package/src/modules/sales/commands/statuses.ts +2 -2
  142. package/src/modules/sales/commands/tags.ts +3 -3
  143. package/tsconfig.json +0 -2
@@ -4,7 +4,7 @@ import { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/c
4
4
  import { emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'
5
5
  import type { DataEngine } from '@open-mercato/shared/lib/data/engine'
6
6
  import type { EntityManager } from '@mikro-orm/postgresql'
7
- import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
7
+ import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
8
8
  import {
9
9
  documentAddressCreateSchema,
10
10
  documentAddressDeleteSchema,
@@ -106,7 +106,7 @@ function applyDocumentAddressSnapshot(em: EntityManager, entity: SalesDocumentAd
106
106
 
107
107
  function assertDocumentAddressParent(entity: SalesDocumentAddress, input: { documentId: string; documentKind: 'order' | 'quote' }): void {
108
108
  if (entity.documentId !== input.documentId || entity.documentKind !== input.documentKind) {
109
- throw new CrudHttpError(404, { error: 'sales.document.address.not_found' })
109
+ throw notFound('sales.document.address.not_found')
110
110
  }
111
111
  }
112
112
 
@@ -145,7 +145,7 @@ async function requireDocument(
145
145
  const repo = kind === 'order' ? SalesOrder : SalesQuote
146
146
  const doc = await findOneWithDecryption(em, repo, { id, organizationId, tenantId }, {}, { tenantId, organizationId })
147
147
  if (!doc) {
148
- throw new CrudHttpError(404, { error: 'sales.document.not_found' })
148
+ throw notFound('sales.document.not_found')
149
149
  }
150
150
  return doc
151
151
  }
@@ -15,7 +15,7 @@ import { LockMode } from "@mikro-orm/core";
15
15
  import type { EntityManager } from "@mikro-orm/postgresql";
16
16
  import type { EventBus } from "@open-mercato/events";
17
17
  import type { DataEngine } from "@open-mercato/shared/lib/data/engine";
18
- import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
18
+ import { CrudHttpError, notFound } from "@open-mercato/shared/lib/crud/errors";
19
19
  import {
20
20
  deriveResourceFromCommandId,
21
21
  invalidateCrudCache,
@@ -4854,7 +4854,7 @@ const deleteQuoteCommand: CommandHandler<
4854
4854
  const em = (ctx.container.resolve("em") as EntityManager).fork();
4855
4855
  const quote = await findOneWithDecryption(em, SalesQuote, { id });
4856
4856
  if (!quote)
4857
- throw new CrudHttpError(404, { error: "Sales quote not found" });
4857
+ throw notFound("Sales quote not found");
4858
4858
  ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
4859
4859
  const [addresses, notes, tags, adjustments, lines] = await Promise.all([
4860
4860
  findWithDecryption(
@@ -4984,7 +4984,7 @@ const updateQuoteCommand: CommandHandler<
4984
4984
  deletedAt: null,
4985
4985
  });
4986
4986
  if (!quote)
4987
- throw new CrudHttpError(404, { error: "Sales quote not found" });
4987
+ throw notFound("Sales quote not found");
4988
4988
  ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
4989
4989
  await enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
4990
4990
  const shouldInvalidateSentToken = (quote.status ?? null) === "sent";
@@ -5216,7 +5216,7 @@ const updateOrderCommand: CommandHandler<
5216
5216
  deletedAt: null,
5217
5217
  });
5218
5218
  if (!order)
5219
- throw new CrudHttpError(404, { error: "Sales order not found" });
5219
+ throw notFound("Sales order not found");
5220
5220
  ensureOrderScope(ctx, order.organizationId, order.tenantId);
5221
5221
  await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
5222
5222
  const previousStatus = normalizeStatusValue(order.status);
@@ -5861,7 +5861,7 @@ const deleteOrderCommand: CommandHandler<
5861
5861
  const em = (ctx.container.resolve("em") as EntityManager).fork();
5862
5862
  const order = await findOneWithDecryption(em, SalesOrder, { id });
5863
5863
  if (!order)
5864
- throw new CrudHttpError(404, { error: "Sales order not found" });
5864
+ throw notFound("Sales order not found");
5865
5865
  ensureOrderScope(ctx, order.organizationId, order.tenantId);
5866
5866
  const shipments = await em.find(SalesShipment, { order: order.id });
5867
5867
  const shipmentIds = shipments.map((entry) => entry.id);
@@ -6055,22 +6055,18 @@ const convertQuoteToOrderCommand: CommandHandler<
6055
6055
  );
6056
6056
  const { translate } = await resolveTranslations();
6057
6057
  if (!quote)
6058
- throw new CrudHttpError(404, {
6059
- error: translate(
6058
+ throw notFound(translate(
6060
6059
  "sales.documents.detail.error",
6061
6060
  "Document not found or inaccessible.",
6062
- ),
6063
- });
6061
+ ));
6064
6062
  ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
6065
6063
  await enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
6066
6064
  const snapshot = await loadQuoteSnapshot(em, payload.quoteId);
6067
6065
  if (!snapshot)
6068
- throw new CrudHttpError(404, {
6069
- error: translate(
6066
+ throw notFound(translate(
6070
6067
  "sales.documents.detail.error",
6071
6068
  "Document not found or inaccessible.",
6072
- ),
6073
- });
6069
+ ));
6074
6070
  const orderId = payload.orderId ?? quote.id;
6075
6071
  const existingOrder = await findOneWithDecryption(em, SalesOrder, {
6076
6072
  id: orderId,
@@ -6613,7 +6609,7 @@ const orderLineUpsertCommand: CommandHandler<
6613
6609
  deletedAt: null,
6614
6610
  });
6615
6611
  if (!order)
6616
- throw new CrudHttpError(404, { error: "Sales order not found" });
6612
+ throw notFound("Sales order not found");
6617
6613
  ensureOrderScope(ctx, order.organizationId, order.tenantId);
6618
6614
  await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
6619
6615
 
@@ -6930,12 +6926,10 @@ const orderLineDeleteCommand: CommandHandler<
6930
6926
  deletedAt: null,
6931
6927
  });
6932
6928
  if (!order)
6933
- throw new CrudHttpError(404, {
6934
- error: translate(
6929
+ throw notFound(translate(
6935
6930
  "sales.documents.detail.error",
6936
6931
  "Document not found or inaccessible.",
6937
- ),
6938
- });
6932
+ ));
6939
6933
  ensureOrderScope(ctx, order.organizationId, order.tenantId);
6940
6934
  await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
6941
6935
  const shipmentCount = await em.count(SalesShipmentItem, {
@@ -6962,12 +6956,10 @@ const orderLineDeleteCommand: CommandHandler<
6962
6956
  );
6963
6957
  const filtered = existingLines.filter((line) => line.id !== parsed.id);
6964
6958
  if (filtered.length === existingLines.length) {
6965
- throw new CrudHttpError(404, {
6966
- error: translate(
6959
+ throw notFound(translate(
6967
6960
  "sales.documents.detail.error",
6968
6961
  "Document not found or inaccessible.",
6969
- ),
6970
- });
6962
+ ));
6971
6963
  }
6972
6964
  const sourceInputs = filtered.map((line, index) => ({
6973
6965
  ...mapOrderLineEntityToSnapshot(line),
@@ -7106,7 +7098,7 @@ const quoteLineUpsertCommand: CommandHandler<
7106
7098
  deletedAt: null,
7107
7099
  });
7108
7100
  if (!quote)
7109
- throw new CrudHttpError(404, { error: "Sales quote not found" });
7101
+ throw notFound("Sales quote not found");
7110
7102
  ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
7111
7103
  await enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
7112
7104
  const [existingLines, adjustments] = await Promise.all([
@@ -7418,7 +7410,7 @@ const quoteLineDeleteCommand: CommandHandler<
7418
7410
  deletedAt: null,
7419
7411
  });
7420
7412
  if (!quote)
7421
- throw new CrudHttpError(404, { error: "Sales quote not found" });
7413
+ throw notFound("Sales quote not found");
7422
7414
  ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
7423
7415
  await enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
7424
7416
  const existingLines = await em.find(
@@ -7433,7 +7425,7 @@ const quoteLineDeleteCommand: CommandHandler<
7433
7425
  );
7434
7426
  const filtered = existingLines.filter((line) => line.id !== parsed.id);
7435
7427
  if (filtered.length === existingLines.length) {
7436
- throw new CrudHttpError(404, { error: "Quote line not found" });
7428
+ throw notFound("Quote line not found");
7437
7429
  }
7438
7430
  const sourceInputs = filtered.map((line, index) => ({
7439
7431
  ...mapQuoteLineEntityToSnapshot(line),
@@ -7572,7 +7564,7 @@ const orderAdjustmentUpsertCommand: CommandHandler<
7572
7564
  deletedAt: null,
7573
7565
  });
7574
7566
  if (!order)
7575
- throw new CrudHttpError(404, { error: "Sales order not found" });
7567
+ throw notFound("Sales order not found");
7576
7568
  ensureOrderScope(ctx, order.organizationId, order.tenantId);
7577
7569
  await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
7578
7570
  if (parsed.scope === "line") {
@@ -7866,7 +7858,7 @@ const orderAdjustmentDeleteCommand: CommandHandler<
7866
7858
  deletedAt: null,
7867
7859
  });
7868
7860
  if (!order)
7869
- throw new CrudHttpError(404, { error: "Sales order not found" });
7861
+ throw notFound("Sales order not found");
7870
7862
  ensureOrderScope(ctx, order.organizationId, order.tenantId);
7871
7863
  await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER);
7872
7864
 
@@ -7880,7 +7872,7 @@ const orderAdjustmentDeleteCommand: CommandHandler<
7880
7872
  ]);
7881
7873
  const filtered = adjustments.filter((adj) => adj.id !== parsed.id);
7882
7874
  if (filtered.length === adjustments.length) {
7883
- throw new CrudHttpError(404, { error: "Adjustment not found" });
7875
+ throw notFound("Adjustment not found");
7884
7876
  }
7885
7877
  const lineSnapshots = existingLines.map(mapOrderLineEntityToSnapshot);
7886
7878
  const calcLines = lineSnapshots.map((line, index) =>
@@ -8031,7 +8023,7 @@ const quoteAdjustmentUpsertCommand: CommandHandler<
8031
8023
  deletedAt: null,
8032
8024
  });
8033
8025
  if (!quote)
8034
- throw new CrudHttpError(404, { error: "Sales quote not found" });
8026
+ throw notFound("Sales quote not found");
8035
8027
  ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
8036
8028
  await enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
8037
8029
  if (parsed.scope === "line") {
@@ -8323,7 +8315,7 @@ const quoteAdjustmentDeleteCommand: CommandHandler<
8323
8315
  deletedAt: null,
8324
8316
  });
8325
8317
  if (!quote)
8326
- throw new CrudHttpError(404, { error: "Sales quote not found" });
8318
+ throw notFound("Sales quote not found");
8327
8319
  ensureQuoteScope(ctx, quote.organizationId, quote.tenantId);
8328
8320
  await enforceSalesDocumentOptimisticLock(ctx, quote, SALES_RESOURCE_KIND_QUOTE);
8329
8321
 
@@ -8337,7 +8329,7 @@ const quoteAdjustmentDeleteCommand: CommandHandler<
8337
8329
  ]);
8338
8330
  const filtered = adjustments.filter((adj) => adj.id !== parsed.id);
8339
8331
  if (filtered.length === adjustments.length) {
8340
- throw new CrudHttpError(404, { error: "Adjustment not found" });
8332
+ throw notFound("Adjustment not found");
8341
8333
  }
8342
8334
  const lineSnapshots = existingLines.map(mapQuoteLineEntityToSnapshot);
8343
8335
  const calcLines = lineSnapshots.map((line, index) =>
@@ -7,7 +7,7 @@ import {
7
7
  } from '@open-mercato/shared/lib/commands/helpers'
8
8
  import type { DataEngine } from '@open-mercato/shared/lib/data/engine'
9
9
  import type { EntityManager } from '@mikro-orm/postgresql'
10
- import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
10
+ import { notFound } from '@open-mercato/shared/lib/crud/errors'
11
11
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
12
12
  import type { CrudEventsConfig } from '@open-mercato/shared/lib/crud/types'
13
13
  import { E } from '#generated/entities.ids.generated'
@@ -96,7 +96,7 @@ async function requireContext(
96
96
  if (contextType === 'order') {
97
97
  const order = await findOneWithDecryption(em, SalesOrder, { id: contextId }, {}, { tenantId, organizationId })
98
98
  if (!order) {
99
- throw new CrudHttpError(404, { error: 'sales.notes.context_not_found' })
99
+ throw notFound('sales.notes.context_not_found')
100
100
  }
101
101
  if (organizationId && tenantId) {
102
102
  ensureSameScope(order, organizationId, tenantId)
@@ -111,7 +111,7 @@ async function requireContext(
111
111
  if (contextType === 'quote') {
112
112
  const quote = await findOneWithDecryption(em, SalesQuote, { id: contextId }, {}, { tenantId, organizationId })
113
113
  if (!quote) {
114
- throw new CrudHttpError(404, { error: 'sales.notes.context_not_found' })
114
+ throw notFound('sales.notes.context_not_found')
115
115
  }
116
116
  if (organizationId && tenantId) {
117
117
  ensureSameScope(quote, organizationId, tenantId)
@@ -132,7 +132,7 @@ async function requireContext(
132
132
  { tenantId, organizationId },
133
133
  ) as (SalesInvoice | SalesCreditMemo) | null
134
134
  if (!entity) {
135
- throw new CrudHttpError(404, { error: 'sales.notes.context_not_found' })
135
+ throw notFound('sales.notes.context_not_found')
136
136
  }
137
137
  if (organizationId && tenantId) {
138
138
  ensureSameScope(entity, organizationId, tenantId)
@@ -256,7 +256,7 @@ const createNoteCommand: CommandHandler<NoteCreateInput, { noteId: string; autho
256
256
  beforeRestore: async ({ em, snapshot }) => {
257
257
  const context = await requireContext(em, snapshot.contextType, snapshot.contextId).catch(() => null)
258
258
  if (!context) {
259
- throw new CrudHttpError(404, { error: 'sales.notes.context_not_found' })
259
+ throw notFound('sales.notes.context_not_found')
260
260
  }
261
261
  return {
262
262
  order: snapshot.orderId ? context.order ?? null : null,
@@ -279,7 +279,7 @@ const updateNoteCommand: CommandHandler<NoteUpdateInput, { noteId: string }> = {
279
279
  const parsed = noteUpdateSchema.parse(rawInput ?? {})
280
280
  const em = (ctx.container.resolve('em') as EntityManager).fork()
281
281
  const note = await findOneWithDecryption(em, SalesNote, { id: parsed.id }, {})
282
- if (!note) throw new CrudHttpError(404, { error: 'sales.notes.not_found' })
282
+ if (!note) throw notFound('sales.notes.not_found')
283
283
  ensureTenantScope(ctx, note.tenantId)
284
284
  ensureOrganizationScope(ctx, note.organizationId)
285
285
 
@@ -413,7 +413,7 @@ const deleteNoteCommand: CommandHandler<{ body?: Record<string, unknown>; query?
413
413
  const id = requireId(input, 'Note id required')
414
414
  const em = (ctx.container.resolve('em') as EntityManager).fork()
415
415
  const note = await findOneWithDecryption(em, SalesNote, { id }, {})
416
- if (!note) throw new CrudHttpError(404, { error: 'sales.notes.not_found' })
416
+ if (!note) throw notFound('sales.notes.not_found')
417
417
  ensureTenantScope(ctx, note.tenantId)
418
418
  ensureOrganizationScope(ctx, note.organizationId)
419
419
  em.remove(note)
@@ -3,7 +3,7 @@
3
3
  import { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'
4
4
  import { LockMode } from '@mikro-orm/core'
5
5
  import type { EntityManager } from '@mikro-orm/postgresql'
6
- import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
6
+ import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
7
7
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
8
8
  import { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'
9
9
  import { setRecordCustomFields } from '@open-mercato/core/modules/entities/lib/helpers'
@@ -346,7 +346,7 @@ const createPaymentCommand: CommandHandler<
346
346
  )
347
347
  ensureSameScope(order, input.organizationId, input.tenantId)
348
348
  if (order.deletedAt) {
349
- throw new CrudHttpError(404, { error: 'sales.payments.order_not_found' })
349
+ throw notFound('sales.payments.order_not_found')
350
350
  }
351
351
  // Guard the parent order's aggregate version (Gap A): a payment mutation
352
352
  // recalculates the order totals, so a stale parent must 409 before we touch it.
@@ -3,7 +3,7 @@ import { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/c
3
3
  import { withAtomicFlush } from '@open-mercato/shared/lib/commands/flush'
4
4
  import { LockMode } from '@mikro-orm/core'
5
5
  import type { EntityManager } from '@mikro-orm/postgresql'
6
- import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
6
+ import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
7
7
  import { invalidateCrudCache } from '@open-mercato/shared/lib/crud/cache'
8
8
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
9
9
  import { emitCrudSideEffects } from '@open-mercato/shared/lib/commands/helpers'
@@ -456,7 +456,7 @@ async function restoreReturnEffects(
456
456
  { tenantId: snapshot.tenantId, organizationId: snapshot.organizationId },
457
457
  )
458
458
  if (!order) {
459
- throw new CrudHttpError(404, { error: 'sales.returns.orderMissing' })
459
+ throw notFound('sales.returns.orderMissing')
460
460
  }
461
461
  ensureSameScope(order, snapshot.organizationId, snapshot.tenantId)
462
462
 
@@ -620,7 +620,7 @@ const createReturnCommand: CommandHandler<ReturnCreateInput, { returnId: string
620
620
  { tenantId: input.tenantId, organizationId: input.organizationId },
621
621
  )
622
622
  if (!order) {
623
- throw new CrudHttpError(404, { error: translate('sales.returns.orderMissing', 'Order not found.') })
623
+ throw notFound(translate('sales.returns.orderMissing', 'Order not found.'))
624
624
  }
625
625
  ensureSameScope(order, input.organizationId, input.tenantId)
626
626
  await enforceSalesDocumentOptimisticLock(ctx, order, SALES_RESOURCE_KIND_ORDER)
@@ -642,7 +642,7 @@ const createReturnCommand: CommandHandler<ReturnCreateInput, { returnId: string
642
642
  requested.forEach(({ orderLineId, quantity }) => {
643
643
  const line = lineMap.get(orderLineId)
644
644
  if (!line) {
645
- throw new CrudHttpError(404, { error: translate('sales.returns.lineMissing', 'Order line not found.') })
645
+ throw notFound(translate('sales.returns.lineMissing', 'Order line not found.'))
646
646
  }
647
647
  const available = computeAvailableReturnQuantity({
648
648
  quantity: toNumeric(line.quantity),
@@ -846,7 +846,7 @@ const createReturnCommand: CommandHandler<ReturnCreateInput, { returnId: string
846
846
  { tenantId: after.tenantId, organizationId: after.organizationId },
847
847
  )
848
848
  if (!header) {
849
- throw new CrudHttpError(404, { error: 'sales.returns.orderMissing' })
849
+ throw notFound('sales.returns.orderMissing')
850
850
  }
851
851
 
852
852
  await invalidateOrderCache(ctx.container, {
@@ -911,7 +911,7 @@ const updateReturnCommand: CommandHandler<ReturnUpdateInput, { returnId: string
911
911
  { tenantId: input.tenantId, organizationId: input.organizationId },
912
912
  )
913
913
  if (!entity || !entity.order) {
914
- throw new CrudHttpError(404, { error: translate('sales.returns.notFound', 'Return not found.') })
914
+ throw notFound(translate('sales.returns.notFound', 'Return not found.'))
915
915
  }
916
916
  ensureSameScope(entity, input.organizationId, input.tenantId)
917
917
  const orderId = typeof entity.order === 'string' ? entity.order : entity.order.id
@@ -1031,7 +1031,7 @@ const deleteReturnCommand: CommandHandler<ReturnDeleteInput, { returnId: string
1031
1031
 
1032
1032
  const snapshot = await loadReturnSnapshot(em, input.id)
1033
1033
  if (!snapshot) {
1034
- throw new CrudHttpError(404, { error: translate('sales.returns.notFound', 'Return not found.') })
1034
+ throw notFound(translate('sales.returns.notFound', 'Return not found.'))
1035
1035
  }
1036
1036
  ensureSameScope(snapshot, input.organizationId, input.tenantId)
1037
1037
  if (input.orderId !== snapshot.orderId) {
@@ -1046,7 +1046,7 @@ const deleteReturnCommand: CommandHandler<ReturnDeleteInput, { returnId: string
1046
1046
  { tenantId: input.tenantId, organizationId: input.organizationId },
1047
1047
  )
1048
1048
  if (!header) {
1049
- throw new CrudHttpError(404, { error: translate('sales.returns.notFound', 'Return not found.') })
1049
+ throw notFound(translate('sales.returns.notFound', 'Return not found.'))
1050
1050
  }
1051
1051
  ensureSameScope(header, input.organizationId, input.tenantId)
1052
1052
  // Lock on the return's own version, captured before any mutation.
@@ -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 { notFound } from '@open-mercato/shared/lib/crud/errors'
3
3
  import { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'
4
4
  import type { CommandRuntimeContext } from '@open-mercato/shared/lib/commands'
5
5
  import { enforceCommandOptimisticLockWithGuards } from '@open-mercato/shared/lib/crud/optimistic-lock-command'
@@ -138,6 +138,6 @@ export async function requireScopedEntity<T extends { id: string; deletedAt?: Da
138
138
  if (scope.organizationId) where.organizationId = scope.organizationId
139
139
  if (scope.tenantId) where.tenantId = scope.tenantId
140
140
  const entity = await findOneWithDecryption(em, entityClass, where, {}, scope)
141
- if (!entity) throw new CrudHttpError(404, { error: message })
141
+ if (!entity) throw notFound(message)
142
142
  return entity
143
143
  }
@@ -4,7 +4,7 @@ import { randomUUID } from 'crypto'
4
4
  import { registerCommand, type CommandHandler } from '@open-mercato/shared/lib/commands'
5
5
  import { LockMode } from '@mikro-orm/core'
6
6
  import type { EntityManager } from '@mikro-orm/postgresql'
7
- import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
7
+ import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
8
8
  import { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'
9
9
  import { loadCustomFieldValues } from '@open-mercato/shared/lib/crud/custom-fields'
10
10
  import { setRecordCustomFields } from '@open-mercato/core/modules/entities/lib/helpers'
@@ -340,7 +340,7 @@ async function loadOrder(
340
340
  scope?: { tenantId: string; organizationId: string }
341
341
  ): Promise<SalesOrder> {
342
342
  const order = await findOneWithDecryption(em, SalesOrder, { id, deletedAt: null }, {}, scope)
343
- if (!order) throw new CrudHttpError(404, { error: 'sales.shipments.not_found' })
343
+ if (!order) throw notFound('sales.shipments.not_found')
344
344
  return order
345
345
  }
346
346
 
@@ -403,7 +403,7 @@ async function validateShipmentItems(params: {
403
403
  }
404
404
  const line = lineMap.get(lineId)
405
405
  if (!line) {
406
- throw new CrudHttpError(404, { error: translate('sales.shipments.line_missing', 'Order line not found.') })
406
+ throw notFound(translate('sales.shipments.line_missing', 'Order line not found.'))
407
407
  }
408
408
  const lineTotal = toNumber(line.quantity)
409
409
  const alreadyShipped = shippedTotals.get(lineId) ?? 0
@@ -675,7 +675,7 @@ const updateShipmentCommand: CommandHandler<ShipmentUpdateInput, { shipmentId: s
675
675
  { tenantId: input.tenantId, organizationId: input.organizationId },
676
676
  )
677
677
  if (!shipmentEntity || !shipmentEntity.order) {
678
- throw new CrudHttpError(404, { error: 'sales.shipments.not_found' })
678
+ throw notFound('sales.shipments.not_found')
679
679
  }
680
680
  ensureSameScope(shipmentEntity, input.organizationId, input.tenantId)
681
681
  const order = shipmentEntity.order as SalesOrder
@@ -970,7 +970,7 @@ const deleteShipmentCommand: CommandHandler<
970
970
  { tenantId: payload.tenantId, organizationId: payload.organizationId },
971
971
  )
972
972
  if (!shipmentEntity || !shipmentEntity.order) {
973
- throw new CrudHttpError(404, { error: translate('sales.shipments.not_found', 'Shipment not found') })
973
+ throw notFound(translate('sales.shipments.not_found', 'Shipment not found'))
974
974
  }
975
975
  try {
976
976
  ensureSameScope(shipmentEntity, payload.organizationId, payload.tenantId)
@@ -1,6 +1,6 @@
1
1
  import { DictionaryEntry } from '@open-mercato/core/modules/dictionaries/data/entities'
2
2
  import { registerDictionaryEntryCommands } from '@open-mercato/core/modules/dictionaries/commands/factory'
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
  ensureSalesDictionary,
6
6
  getSalesDictionaryDefinition,
@@ -70,7 +70,7 @@ function registerStatusDictionaryCommands(kind: SalesDictionaryKind): void {
70
70
  resolveEntry: async ({ em, ctx, id }) => {
71
71
  const entry = await findOneWithDecryption(em, DictionaryEntry, id, { populate: ['dictionary'] })
72
72
  if (!entry) {
73
- throw new CrudHttpError(404, { error: 'Dictionary entry not found' })
73
+ throw notFound('Dictionary entry not found')
74
74
  }
75
75
  if (entry.dictionary.key !== definition.key) {
76
76
  throw new CrudHttpError(400, { error: 'Entry does not belong to this dictionary.' })
@@ -3,7 +3,7 @@
3
3
  import { registerCommand } from '@open-mercato/shared/lib/commands'
4
4
  import type { CommandHandler } from '@open-mercato/shared/lib/commands'
5
5
  import type { EntityManager } from '@mikro-orm/postgresql'
6
- import { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'
6
+ import { CrudHttpError, notFound } from '@open-mercato/shared/lib/crud/errors'
7
7
  import { SalesDocumentTag, SalesDocumentTagAssignment } from '../data/entities'
8
8
  import { ensureTenantScope } from './shared'
9
9
  import {
@@ -44,7 +44,7 @@ const updateTagCommand: CommandHandler<SalesTagUpdateInput, { tagId: string }> =
44
44
  const parsed = salesTagUpdateSchema.parse(rawInput ?? {})
45
45
  const em = (ctx.container.resolve('em') as EntityManager).fork()
46
46
  const tag = await em.findOne(SalesDocumentTag, { id: parsed.id })
47
- if (!tag) throw new CrudHttpError(404, { error: 'Tag not found' })
47
+ if (!tag) throw notFound('Tag not found')
48
48
  ensureTenantScope(ctx, parsed.tenantId ?? tag.tenantId)
49
49
  if (parsed.slug && parsed.slug !== tag.slug) {
50
50
  const conflict = await em.findOne(SalesDocumentTag, {
@@ -74,7 +74,7 @@ const deleteTagCommand: CommandHandler<{ id?: string }, { tagId: string }> = {
74
74
  if (!id) throw new CrudHttpError(400, { error: 'Tag id is required' })
75
75
  const em = (ctx.container.resolve('em') as EntityManager).fork()
76
76
  const tag = await em.findOne(SalesDocumentTag, { id })
77
- if (!tag) throw new CrudHttpError(404, { error: 'Tag not found' })
77
+ if (!tag) throw notFound('Tag not found')
78
78
  ensureTenantScope(ctx, tag.tenantId)
79
79
  await em.nativeDelete(SalesDocumentTagAssignment, { tag: tag.id })
80
80
  em.remove(tag)
package/tsconfig.json CHANGED
@@ -3,8 +3,6 @@
3
3
  "extends": "../../tsconfig.base.json",
4
4
  "compilerOptions": {
5
5
  "noEmit": true,
6
- "baseUrl": ".",
7
- "ignoreDeprecations": "6.0",
8
6
  "paths": {
9
7
  "@open-mercato/core/modules/core/__integration__/helpers/*": [
10
8
  "./src/modules/core/__integration__/helpers/*"