@open-mercato/core 0.6.2-develop.3467.1.2a1818709d → 0.6.2

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 (158) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/helpers/integration/queue-runner.js +15 -3
  3. package/dist/helpers/integration/queue-runner.js.map +2 -2
  4. package/dist/helpers/integration/queue.js +1 -1
  5. package/dist/helpers/integration/queue.js.map +2 -2
  6. package/dist/helpers/integration/salesUi.js +24 -1
  7. package/dist/helpers/integration/salesUi.js.map +2 -2
  8. package/dist/modules/auth/api/roles/acl/route.js +37 -1
  9. package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
  10. package/dist/modules/auth/api/roles/route.js +36 -2
  11. package/dist/modules/auth/api/roles/route.js.map +2 -2
  12. package/dist/modules/auth/api/users/acl/route.js +36 -1
  13. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  14. package/dist/modules/auth/api/users/route.js +101 -13
  15. package/dist/modules/auth/api/users/route.js.map +2 -2
  16. package/dist/modules/auth/backend/roles/[id]/edit/page.js +32 -14
  17. package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
  18. package/dist/modules/auth/backend/users/[id]/edit/page.js +1 -1
  19. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  20. package/dist/modules/auth/backend/users/create/page.js +1 -1
  21. package/dist/modules/auth/backend/users/create/page.js.map +2 -2
  22. package/dist/modules/auth/backend/users/roleOptions.js +1 -1
  23. package/dist/modules/auth/backend/users/roleOptions.js.map +2 -2
  24. package/dist/modules/auth/commands/roles.js +8 -0
  25. package/dist/modules/auth/commands/roles.js.map +2 -2
  26. package/dist/modules/auth/commands/users.js +3 -0
  27. package/dist/modules/auth/commands/users.js.map +2 -2
  28. package/dist/modules/auth/components/AclEditor.js +53 -26
  29. package/dist/modules/auth/components/AclEditor.js.map +2 -2
  30. package/dist/modules/auth/lib/grantChecks.js +97 -2
  31. package/dist/modules/auth/lib/grantChecks.js.map +2 -2
  32. package/dist/modules/business_rules/lib/expression-evaluator.js +9 -7
  33. package/dist/modules/business_rules/lib/expression-evaluator.js.map +2 -2
  34. package/dist/modules/customers/ai-agents.js +10 -1
  35. package/dist/modules/customers/ai-agents.js.map +2 -2
  36. package/dist/modules/customers/ai-tools/settings-pack.js +55 -1
  37. package/dist/modules/customers/ai-tools/settings-pack.js.map +2 -2
  38. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +13 -5
  39. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
  40. package/dist/modules/customers/lib/personCompanyLinkTable.js +4 -30
  41. package/dist/modules/customers/lib/personCompanyLinkTable.js.map +2 -2
  42. package/dist/modules/customers/migrations/Migration20260521175027.js +12 -0
  43. package/dist/modules/customers/migrations/Migration20260521175027.js.map +7 -0
  44. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +41 -12
  45. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  46. package/dist/modules/data_sync/api/options.js +2 -0
  47. package/dist/modules/data_sync/api/options.js.map +2 -2
  48. package/dist/modules/data_sync/api/run.js +77 -58
  49. package/dist/modules/data_sync/api/run.js.map +2 -2
  50. package/dist/modules/data_sync/backend/data-sync/page.js +3 -2
  51. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  52. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +8 -3
  53. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  54. package/dist/modules/integrations/backend/integrations/[id]/page.js +15 -13
  55. package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
  56. package/dist/modules/integrations/data/validators.js +9 -6
  57. package/dist/modules/integrations/data/validators.js.map +2 -2
  58. package/dist/modules/messages/api/route.js +2 -2
  59. package/dist/modules/messages/api/route.js.map +2 -2
  60. package/dist/modules/messages/commands/messages.js +42 -2
  61. package/dist/modules/messages/commands/messages.js.map +2 -2
  62. package/dist/modules/messages/components/MessagesInboxPageClient.js +66 -87
  63. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
  64. package/dist/modules/messages/components/inboxFilters.js +133 -0
  65. package/dist/modules/messages/components/inboxFilters.js.map +7 -0
  66. package/dist/modules/messages/data/validators.js +8 -6
  67. package/dist/modules/messages/data/validators.js.map +2 -2
  68. package/dist/modules/progress/api/jobs/route.js +26 -16
  69. package/dist/modules/progress/api/jobs/route.js.map +2 -2
  70. package/dist/modules/query_index/di.js +8 -6
  71. package/dist/modules/query_index/di.js.map +2 -2
  72. package/dist/modules/query_index/lib/indexer.js +12 -10
  73. package/dist/modules/query_index/lib/indexer.js.map +2 -2
  74. package/dist/modules/query_index/subscribers/upsert_one.js +7 -1
  75. package/dist/modules/query_index/subscribers/upsert_one.js.map +2 -2
  76. package/dist/modules/sales/api/order-adjustments/route.js.map +2 -2
  77. package/dist/modules/sales/api/quote-adjustments/route.js.map +2 -2
  78. package/dist/modules/sales/commands/documents.js +104 -0
  79. package/dist/modules/sales/commands/documents.js.map +2 -2
  80. package/dist/modules/sales/data/validators.js +20 -1
  81. package/dist/modules/sales/data/validators.js.map +2 -2
  82. package/dist/modules/sales/lib/makeSalesLineRoute.js.map +2 -2
  83. package/dist/modules/sync_excel/api/import/route.js +126 -116
  84. package/dist/modules/sync_excel/api/import/route.js.map +2 -2
  85. package/dist/modules/sync_excel/lib/adapters/customers.js +1 -0
  86. package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
  87. package/dist/modules/translations/components/TranslationManager.js +9 -4
  88. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  89. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  90. package/dist/modules/workflows/lib/event-trigger-service.js +23 -11
  91. package/dist/modules/workflows/lib/event-trigger-service.js.map +2 -2
  92. package/jest.config.cjs +4 -1
  93. package/package.json +15 -16
  94. package/src/helpers/integration/queue-runner.ts +21 -2
  95. package/src/helpers/integration/queue.ts +1 -1
  96. package/src/helpers/integration/salesUi.ts +26 -1
  97. package/src/modules/auth/api/roles/acl/route.ts +39 -1
  98. package/src/modules/auth/api/roles/route.ts +38 -2
  99. package/src/modules/auth/api/users/acl/route.ts +41 -1
  100. package/src/modules/auth/api/users/route.ts +105 -12
  101. package/src/modules/auth/backend/roles/[id]/edit/page.tsx +35 -13
  102. package/src/modules/auth/backend/users/[id]/edit/page.tsx +1 -1
  103. package/src/modules/auth/backend/users/create/page.tsx +1 -1
  104. package/src/modules/auth/backend/users/roleOptions.ts +2 -1
  105. package/src/modules/auth/commands/roles.ts +8 -0
  106. package/src/modules/auth/commands/users.ts +3 -0
  107. package/src/modules/auth/components/AclEditor.tsx +50 -24
  108. package/src/modules/auth/lib/grantChecks.ts +116 -2
  109. package/src/modules/business_rules/lib/expression-evaluator.ts +9 -13
  110. package/src/modules/customers/ai-agents.ts +10 -1
  111. package/src/modules/customers/ai-tools/settings-pack.ts +62 -1
  112. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +18 -7
  113. package/src/modules/customers/lib/personCompanyLinkTable.ts +33 -41
  114. package/src/modules/customers/migrations/Migration20260521175027.ts +39 -0
  115. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +38 -12
  116. package/src/modules/data_sync/api/options.ts +2 -0
  117. package/src/modules/data_sync/api/run.ts +80 -61
  118. package/src/modules/data_sync/backend/data-sync/page.tsx +10 -0
  119. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +17 -3
  120. package/src/modules/data_sync/i18n/de.json +3 -0
  121. package/src/modules/data_sync/i18n/en.json +3 -0
  122. package/src/modules/data_sync/i18n/es.json +3 -0
  123. package/src/modules/data_sync/i18n/pl.json +3 -0
  124. package/src/modules/data_sync/lib/adapter.ts +9 -0
  125. package/src/modules/integrations/backend/integrations/[id]/page.tsx +15 -13
  126. package/src/modules/integrations/data/validators.ts +5 -4
  127. package/src/modules/messages/api/route.ts +2 -2
  128. package/src/modules/messages/commands/messages.ts +54 -2
  129. package/src/modules/messages/components/MessagesInboxPageClient.tsx +75 -90
  130. package/src/modules/messages/components/inboxFilters.ts +162 -0
  131. package/src/modules/messages/data/validators.ts +7 -5
  132. package/src/modules/messages/i18n/de.json +5 -4
  133. package/src/modules/messages/i18n/en.json +5 -4
  134. package/src/modules/messages/i18n/es.json +5 -4
  135. package/src/modules/messages/i18n/pl.json +5 -4
  136. package/src/modules/progress/api/jobs/route.ts +30 -20
  137. package/src/modules/query_index/di.ts +9 -7
  138. package/src/modules/query_index/lib/indexer.ts +13 -11
  139. package/src/modules/query_index/subscribers/upsert_one.ts +9 -1
  140. package/src/modules/sales/api/order-adjustments/route.ts +2 -1
  141. package/src/modules/sales/api/quote-adjustments/route.ts +2 -1
  142. package/src/modules/sales/commands/documents.ts +116 -0
  143. package/src/modules/sales/data/validators.ts +38 -0
  144. package/src/modules/sales/i18n/de.json +2 -0
  145. package/src/modules/sales/i18n/en.json +2 -0
  146. package/src/modules/sales/i18n/es.json +2 -0
  147. package/src/modules/sales/i18n/pl.json +2 -0
  148. package/src/modules/sales/lib/makeSalesLineRoute.ts +2 -1
  149. package/src/modules/staff/i18n/de.json +1 -0
  150. package/src/modules/staff/i18n/en.json +1 -0
  151. package/src/modules/staff/i18n/es.json +1 -0
  152. package/src/modules/staff/i18n/pl.json +1 -0
  153. package/src/modules/sync_excel/api/import/route.ts +141 -131
  154. package/src/modules/sync_excel/lib/adapters/customers.ts +1 -0
  155. package/src/modules/translations/components/TranslationManager.tsx +9 -4
  156. package/src/modules/workflows/lib/activity-executor.ts +4 -3
  157. package/src/modules/workflows/lib/event-trigger-service.ts +24 -11
  158. package/tsconfig.json +1 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/sales/api/quote-adjustments/route.ts"],
4
- "sourcesContent": ["import { z } from 'zod'\nimport { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { SalesQuoteAdjustment } from '../../data/entities'\nimport {\n enforceAdjustmentSign,\n quoteAdjustmentCreateSchema,\n} from '../../data/validators'\nimport { createPagedListResponseSchema, createSalesCrudOpenApi, defaultOkResponseSchema } from '../openapi'\nimport { withScopedPayload } from '../utils'\nimport { E } from '#generated/entities.ids.generated'\nimport * as F from '#generated/entities/sales_quote_adjustment'\nimport { buildCustomFieldFiltersFromQuery, extractAllCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields'\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst listSchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n quoteId: z.string().uuid().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n })\n .passthrough()\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['sales.quotes.view'] },\n POST: { requireAuth: true, requireFeatures: ['sales.quotes.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['sales.quotes.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['sales.quotes.manage'] },\n}\n\nconst upsertSchema = quoteAdjustmentCreateSchema\n .extend({ id: z.string().uuid().optional() })\n .superRefine(enforceAdjustmentSign)\n\nconst deleteSchema = z.object({\n id: z.string().uuid(),\n quoteId: z.string().uuid(),\n})\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: SalesQuoteAdjustment,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n list: {\n schema: listSchema,\n entityId: E.sales.sales_quote_adjustment,\n decorateCustomFields: { entityIds: [E.sales.sales_quote_adjustment] },\n fields: [\n F.id,\n 'quote_id',\n 'quote_line_id',\n F.scope,\n F.kind,\n F.code,\n F.label,\n F.calculator_key,\n F.promotion_id,\n F.rate,\n F.amount_net,\n F.amount_gross,\n F.currency_code,\n F.metadata,\n F.position,\n F.created_at,\n F.updated_at,\n ],\n sortFieldMap: {\n createdAt: F.created_at,\n updatedAt: F.updated_at,\n position: F.position,\n },\n buildFilters: async (query, ctx) => {\n const filters: Record<string, unknown> = {}\n if (query.quoteId) filters.quote_id = { $eq: query.quoteId }\n try {\n const em = ctx.container.resolve('em')\n const cfFilters = await buildCustomFieldFiltersFromQuery({\n entityId: E.sales.sales_quote_adjustment,\n query,\n em,\n tenantId: ctx.auth?.tenantId ?? null,\n })\n Object.assign(filters, cfFilters)\n } catch {\n // ignore custom field filters when unavailable\n }\n return filters\n },\n transformItem: (item: any) => {\n if (!item) return item\n const normalized = { ...item }\n const cfEntries = extractAllCustomFieldEntries(item)\n for (const key of Object.keys(normalized)) {\n if (key.startsWith('cf:')) delete normalized[key]\n }\n return { ...normalized, ...cfEntries }\n },\n },\n actions: {\n create: {\n commandId: 'sales.quotes.adjustments.upsert',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const payload = upsertSchema.parse(withScopedPayload(raw ?? {}, ctx, translate))\n return { body: payload }\n },\n response: ({ result }) => ({ id: result?.adjustmentId ?? null, quoteId: result?.quoteId ?? null }),\n status: 201,\n },\n update: {\n commandId: 'sales.quotes.adjustments.upsert',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const payload = upsertSchema.parse(withScopedPayload(raw ?? {}, ctx, translate))\n return { body: payload }\n },\n response: ({ result }) => ({ id: result?.adjustmentId ?? null, quoteId: result?.quoteId ?? null }),\n },\n delete: {\n commandId: 'sales.quotes.adjustments.delete',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const payload = deleteSchema.parse(\n withScopedPayload(\n {\n ...((raw as any)?.body ?? {}),\n ...((raw as any)?.query ?? {}),\n },\n ctx,\n translate\n )\n )\n if (!payload.id || !payload.quoteId) {\n throw new CrudHttpError(400, { error: translate('sales.documents.detail.error', 'Document not found or inaccessible.') })\n }\n return { body: payload }\n },\n response: () => ({ ok: true }),\n },\n },\n})\n\nconst { GET, POST, PUT, DELETE } = crud\n\nexport const metadata = routeMetadata\nexport { GET, POST, PUT, DELETE }\n\nconst adjustmentSchema = z.object({\n id: z.string().uuid(),\n quote_id: z.string().uuid(),\n quote_line_id: z.string().uuid().nullable().optional(),\n scope: z.string(),\n kind: z.string(),\n code: z.string().nullable().optional(),\n label: z.string().nullable().optional(),\n calculator_key: z.string().nullable().optional(),\n promotion_id: z.string().uuid().nullable().optional(),\n rate: z.number(),\n amount_net: z.number(),\n amount_gross: z.number(),\n currency_code: z.string().nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n position: z.number(),\n created_at: z.string(),\n updated_at: z.string(),\n})\n\nexport const openApi = createSalesCrudOpenApi({\n resourceName: 'Quote adjustment',\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(adjustmentSchema),\n create: {\n schema: upsertSchema,\n responseSchema: z.object({ id: z.string().uuid().nullable(), quoteId: z.string().uuid().nullable() }),\n description: 'Creates a quote adjustment and recalculates totals.',\n },\n update: {\n schema: upsertSchema,\n responseSchema: z.object({ id: z.string().uuid().nullable(), quoteId: z.string().uuid().nullable() }),\n description: 'Updates a quote adjustment and recalculates totals.',\n },\n del: {\n schema: deleteSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Deletes a quote adjustment and recalculates totals.',\n },\n})\n"],
5
- "mappings": "AAAA,SAAS,SAAS;AAClB,SAAS,qBAAqB;AAC9B,SAAS,2BAA2B;AACpC,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,+BAA+B,wBAAwB,+BAA+B;AAC/F,SAAS,yBAAyB;AAClC,SAAS,SAAS;AAClB,YAAY,OAAO;AACnB,SAAS,kCAAkC,oCAAoC;AAE/E,MAAM,gBAAgB,EAAE,OAAO,CAAC,CAAC,EAAE,YAAY;AAE/C,MAAM,aAAa,EAChB,OAAO;AAAA,EACN,MAAM,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;AAAA,EACxC,UAAU,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAAA,EACtD,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EACpC,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,SAAS,EAAE,KAAK,CAAC,OAAO,MAAM,CAAC,EAAE,SAAS;AAC5C,CAAC,EACA,YAAY;AAEf,MAAM,gBAAgB;AAAA,EACpB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,mBAAmB,EAAE;AAAA,EACjE,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,qBAAqB,EAAE;AAAA,EACpE,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,qBAAqB,EAAE;AAAA,EACnE,QAAQ,EAAE,aAAa,MAAM,iBAAiB,CAAC,qBAAqB,EAAE;AACxE;AAEA,MAAM,eAAe,4BAClB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAC3C,YAAY,qBAAqB;AAEpC,MAAM,eAAe,EAAE,OAAO;AAAA,EAC5B,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,EACpB,SAAS,EAAE,OAAO,EAAE,KAAK;AAC3B,CAAC;AAED,MAAM,OAAO,cAAc;AAAA,EACzB,UAAU;AAAA,EACV,KAAK;AAAA,IACH,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,UAAU;AAAA,IACV,aAAa;AAAA,IACb,iBAAiB;AAAA,EACnB;AAAA,EACA,MAAM;AAAA,IACJ,QAAQ;AAAA,IACR,UAAU,EAAE,MAAM;AAAA,IAClB,sBAAsB,EAAE,WAAW,CAAC,EAAE,MAAM,sBAAsB,EAAE;AAAA,IACpE,QAAQ;AAAA,MACN,EAAE;AAAA,MACF;AAAA,MACA;AAAA,MACA,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,IACJ;AAAA,IACA,cAAc;AAAA,MACZ,WAAW,EAAE;AAAA,MACb,WAAW,EAAE;AAAA,MACb,UAAU,EAAE;AAAA,IACd;AAAA,IACA,cAAc,OAAO,OAAO,QAAQ;AAClC,YAAM,UAAmC,CAAC;AAC1C,UAAI,MAAM,QAAS,SAAQ,WAAW,EAAE,KAAK,MAAM,QAAQ;AAC3D,UAAI;AACF,cAAM,KAAK,IAAI,UAAU,QAAQ,IAAI;AACrC,cAAM,YAAY,MAAM,iCAAiC;AAAA,UACvD,UAAU,EAAE,MAAM;AAAA,UAClB;AAAA,UACA;AAAA,UACA,UAAU,IAAI,MAAM,YAAY;AAAA,QAClC,CAAC;AACD,eAAO,OAAO,SAAS,SAAS;AAAA,MAClC,QAAQ;AAAA,MAER;AACA,aAAO;AAAA,IACT;AAAA,IACA,eAAe,CAAC,SAAc;AAC5B,UAAI,CAAC,KAAM,QAAO;AAClB,YAAM,aAAa,EAAE,GAAG,KAAK;AAC7B,YAAM,YAAY,6BAA6B,IAAI;AACnD,iBAAW,OAAO,OAAO,KAAK,UAAU,GAAG;AACzC,YAAI,IAAI,WAAW,KAAK,EAAG,QAAO,WAAW,GAAG;AAAA,MAClD;AACA,aAAO,EAAE,GAAG,YAAY,GAAG,UAAU;AAAA,IACvC;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,UAAU,OAAO,EAAE,KAAK,IAAI,MAAM;AAChC,cAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,cAAM,UAAU,aAAa,MAAM,kBAAkB,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC;AAC/E,eAAO,EAAE,MAAM,QAAQ;AAAA,MACzB;AAAA,MACA,UAAU,CAAC,EAAE,OAAO,OAAO,EAAE,IAAI,QAAQ,gBAAgB,MAAM,SAAS,QAAQ,WAAW,KAAK;AAAA,MAChG,QAAQ;AAAA,IACV;AAAA,IACA,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,UAAU,OAAO,EAAE,KAAK,IAAI,MAAM;AAChC,cAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,cAAM,UAAU,aAAa,MAAM,kBAAkB,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC;AAC/E,eAAO,EAAE,MAAM,QAAQ;AAAA,MACzB;AAAA,MACA,UAAU,CAAC,EAAE,OAAO,OAAO,EAAE,IAAI,QAAQ,gBAAgB,MAAM,SAAS,QAAQ,WAAW,KAAK;AAAA,IAClG;AAAA,IACA,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,UAAU,OAAO,EAAE,KAAK,IAAI,MAAM;AAChC,cAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,cAAM,UAAU,aAAa;AAAA,UAC3B;AAAA,YACE;AAAA,cACE,GAAK,KAAa,QAAQ,CAAC;AAAA,cAC3B,GAAK,KAAa,SAAS,CAAC;AAAA,YAC9B;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,YAAI,CAAC,QAAQ,MAAM,CAAC,QAAQ,SAAS;AACnC,gBAAM,IAAI,cAAc,KAAK,EAAE,OAAO,UAAU,gCAAgC,qCAAqC,EAAE,CAAC;AAAA,QAC1H;AACA,eAAO,EAAE,MAAM,QAAQ;AAAA,MACzB;AAAA,MACA,UAAU,OAAO,EAAE,IAAI,KAAK;AAAA,IAC9B;AAAA,EACF;AACF,CAAC;AAED,MAAM,EAAE,KAAK,MAAM,KAAK,OAAO,IAAI;AAE5B,MAAM,WAAW;AAGxB,MAAM,mBAAmB,EAAE,OAAO;AAAA,EAChC,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,EACpB,UAAU,EAAE,OAAO,EAAE,KAAK;AAAA,EAC1B,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EACrD,OAAO,EAAE,OAAO;AAAA,EAChB,MAAM,EAAE,OAAO;AAAA,EACf,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACrC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACtC,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC/C,cAAc,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EACpD,MAAM,EAAE,OAAO;AAAA,EACf,YAAY,EAAE,OAAO;AAAA,EACrB,cAAc,EAAE,OAAO;AAAA,EACvB,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC9C,UAAU,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EAChE,UAAU,EAAE,OAAO;AAAA,EACnB,YAAY,EAAE,OAAO;AAAA,EACrB,YAAY,EAAE,OAAO;AACvB,CAAC;AAEM,MAAM,UAAU,uBAAuB;AAAA,EAC5C,cAAc;AAAA,EACd,aAAa;AAAA,EACb,oBAAoB,8BAA8B,gBAAgB;AAAA,EAClE,QAAQ;AAAA,IACN,QAAQ;AAAA,IACR,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAAA,IACpG,aAAa;AAAA,EACf;AAAA,EACA,QAAQ;AAAA,IACN,QAAQ;AAAA,IACR,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAAA,IACpG,aAAa;AAAA,EACf;AAAA,EACA,KAAK;AAAA,IACH,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,aAAa;AAAA,EACf;AACF,CAAC;",
4
+ "sourcesContent": ["import { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/core'\nimport { makeCrudRoute } from '@open-mercato/shared/lib/crud/factory'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { CrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { SalesQuoteAdjustment } from '../../data/entities'\nimport {\n enforceAdjustmentSign,\n quoteAdjustmentCreateSchema,\n} from '../../data/validators'\nimport { createPagedListResponseSchema, createSalesCrudOpenApi, defaultOkResponseSchema } from '../openapi'\nimport { withScopedPayload } from '../utils'\nimport { E } from '#generated/entities.ids.generated'\nimport * as F from '#generated/entities/sales_quote_adjustment'\nimport { buildCustomFieldFiltersFromQuery, extractAllCustomFieldEntries } from '@open-mercato/shared/lib/crud/custom-fields'\n\nconst rawBodySchema = z.object({}).passthrough()\n\nconst listSchema = z\n .object({\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n quoteId: z.string().uuid().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n })\n .passthrough()\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['sales.quotes.view'] },\n POST: { requireAuth: true, requireFeatures: ['sales.quotes.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['sales.quotes.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['sales.quotes.manage'] },\n}\n\nconst upsertSchema = quoteAdjustmentCreateSchema\n .extend({ id: z.string().uuid().optional() })\n .superRefine(enforceAdjustmentSign)\n\nconst deleteSchema = z.object({\n id: z.string().uuid(),\n quoteId: z.string().uuid(),\n})\n\nconst crud = makeCrudRoute({\n metadata: routeMetadata,\n orm: {\n entity: SalesQuoteAdjustment,\n idField: 'id',\n orgField: 'organizationId',\n tenantField: 'tenantId',\n softDeleteField: 'deletedAt',\n },\n list: {\n schema: listSchema,\n entityId: E.sales.sales_quote_adjustment,\n decorateCustomFields: { entityIds: [E.sales.sales_quote_adjustment] },\n fields: [\n F.id,\n 'quote_id',\n 'quote_line_id',\n F.scope,\n F.kind,\n F.code,\n F.label,\n F.calculator_key,\n F.promotion_id,\n F.rate,\n F.amount_net,\n F.amount_gross,\n F.currency_code,\n F.metadata,\n F.position,\n F.created_at,\n F.updated_at,\n ],\n sortFieldMap: {\n createdAt: F.created_at,\n updatedAt: F.updated_at,\n position: F.position,\n },\n buildFilters: async (query, ctx) => {\n const filters: Record<string, unknown> = {}\n if (query.quoteId) filters.quote_id = { $eq: query.quoteId }\n try {\n const em = ctx.container.resolve<EntityManager>('em')\n const cfFilters = await buildCustomFieldFiltersFromQuery({\n entityId: E.sales.sales_quote_adjustment,\n query,\n em,\n tenantId: ctx.auth?.tenantId ?? null,\n })\n Object.assign(filters, cfFilters)\n } catch {\n // ignore custom field filters when unavailable\n }\n return filters\n },\n transformItem: (item: any) => {\n if (!item) return item\n const normalized = { ...item }\n const cfEntries = extractAllCustomFieldEntries(item)\n for (const key of Object.keys(normalized)) {\n if (key.startsWith('cf:')) delete normalized[key]\n }\n return { ...normalized, ...cfEntries }\n },\n },\n actions: {\n create: {\n commandId: 'sales.quotes.adjustments.upsert',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const payload = upsertSchema.parse(withScopedPayload(raw ?? {}, ctx, translate))\n return { body: payload }\n },\n response: ({ result }) => ({ id: result?.adjustmentId ?? null, quoteId: result?.quoteId ?? null }),\n status: 201,\n },\n update: {\n commandId: 'sales.quotes.adjustments.upsert',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const payload = upsertSchema.parse(withScopedPayload(raw ?? {}, ctx, translate))\n return { body: payload }\n },\n response: ({ result }) => ({ id: result?.adjustmentId ?? null, quoteId: result?.quoteId ?? null }),\n },\n delete: {\n commandId: 'sales.quotes.adjustments.delete',\n schema: rawBodySchema,\n mapInput: async ({ raw, ctx }) => {\n const { translate } = await resolveTranslations()\n const payload = deleteSchema.parse(\n withScopedPayload(\n {\n ...((raw as any)?.body ?? {}),\n ...((raw as any)?.query ?? {}),\n },\n ctx,\n translate\n )\n )\n if (!payload.id || !payload.quoteId) {\n throw new CrudHttpError(400, { error: translate('sales.documents.detail.error', 'Document not found or inaccessible.') })\n }\n return { body: payload }\n },\n response: () => ({ ok: true }),\n },\n },\n})\n\nconst { GET, POST, PUT, DELETE } = crud\n\nexport const metadata = routeMetadata\nexport { GET, POST, PUT, DELETE }\n\nconst adjustmentSchema = z.object({\n id: z.string().uuid(),\n quote_id: z.string().uuid(),\n quote_line_id: z.string().uuid().nullable().optional(),\n scope: z.string(),\n kind: z.string(),\n code: z.string().nullable().optional(),\n label: z.string().nullable().optional(),\n calculator_key: z.string().nullable().optional(),\n promotion_id: z.string().uuid().nullable().optional(),\n rate: z.number(),\n amount_net: z.number(),\n amount_gross: z.number(),\n currency_code: z.string().nullable().optional(),\n metadata: z.record(z.string(), z.unknown()).nullable().optional(),\n position: z.number(),\n created_at: z.string(),\n updated_at: z.string(),\n})\n\nexport const openApi = createSalesCrudOpenApi({\n resourceName: 'Quote adjustment',\n querySchema: listSchema,\n listResponseSchema: createPagedListResponseSchema(adjustmentSchema),\n create: {\n schema: upsertSchema,\n responseSchema: z.object({ id: z.string().uuid().nullable(), quoteId: z.string().uuid().nullable() }),\n description: 'Creates a quote adjustment and recalculates totals.',\n },\n update: {\n schema: upsertSchema,\n responseSchema: z.object({ id: z.string().uuid().nullable(), quoteId: z.string().uuid().nullable() }),\n description: 'Updates a quote adjustment and recalculates totals.',\n },\n del: {\n schema: deleteSchema,\n responseSchema: defaultOkResponseSchema,\n description: 'Deletes a quote adjustment and recalculates totals.',\n },\n})\n"],
5
+ "mappings": "AAAA,SAAS,SAAS;AAElB,SAAS,qBAAqB;AAC9B,SAAS,2BAA2B;AACpC,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,+BAA+B,wBAAwB,+BAA+B;AAC/F,SAAS,yBAAyB;AAClC,SAAS,SAAS;AAClB,YAAY,OAAO;AACnB,SAAS,kCAAkC,oCAAoC;AAE/E,MAAM,gBAAgB,EAAE,OAAO,CAAC,CAAC,EAAE,YAAY;AAE/C,MAAM,aAAa,EAChB,OAAO;AAAA,EACN,MAAM,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;AAAA,EACxC,UAAU,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAAA,EACtD,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EACpC,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,SAAS,EAAE,KAAK,CAAC,OAAO,MAAM,CAAC,EAAE,SAAS;AAC5C,CAAC,EACA,YAAY;AAEf,MAAM,gBAAgB;AAAA,EACpB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,mBAAmB,EAAE;AAAA,EACjE,MAAM,EAAE,aAAa,MAAM,iBAAiB,CAAC,qBAAqB,EAAE;AAAA,EACpE,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,qBAAqB,EAAE;AAAA,EACnE,QAAQ,EAAE,aAAa,MAAM,iBAAiB,CAAC,qBAAqB,EAAE;AACxE;AAEA,MAAM,eAAe,4BAClB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAC3C,YAAY,qBAAqB;AAEpC,MAAM,eAAe,EAAE,OAAO;AAAA,EAC5B,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,EACpB,SAAS,EAAE,OAAO,EAAE,KAAK;AAC3B,CAAC;AAED,MAAM,OAAO,cAAc;AAAA,EACzB,UAAU;AAAA,EACV,KAAK;AAAA,IACH,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,UAAU;AAAA,IACV,aAAa;AAAA,IACb,iBAAiB;AAAA,EACnB;AAAA,EACA,MAAM;AAAA,IACJ,QAAQ;AAAA,IACR,UAAU,EAAE,MAAM;AAAA,IAClB,sBAAsB,EAAE,WAAW,CAAC,EAAE,MAAM,sBAAsB,EAAE;AAAA,IACpE,QAAQ;AAAA,MACN,EAAE;AAAA,MACF;AAAA,MACA;AAAA,MACA,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,MACF,EAAE;AAAA,IACJ;AAAA,IACA,cAAc;AAAA,MACZ,WAAW,EAAE;AAAA,MACb,WAAW,EAAE;AAAA,MACb,UAAU,EAAE;AAAA,IACd;AAAA,IACA,cAAc,OAAO,OAAO,QAAQ;AAClC,YAAM,UAAmC,CAAC;AAC1C,UAAI,MAAM,QAAS,SAAQ,WAAW,EAAE,KAAK,MAAM,QAAQ;AAC3D,UAAI;AACF,cAAM,KAAK,IAAI,UAAU,QAAuB,IAAI;AACpD,cAAM,YAAY,MAAM,iCAAiC;AAAA,UACvD,UAAU,EAAE,MAAM;AAAA,UAClB;AAAA,UACA;AAAA,UACA,UAAU,IAAI,MAAM,YAAY;AAAA,QAClC,CAAC;AACD,eAAO,OAAO,SAAS,SAAS;AAAA,MAClC,QAAQ;AAAA,MAER;AACA,aAAO;AAAA,IACT;AAAA,IACA,eAAe,CAAC,SAAc;AAC5B,UAAI,CAAC,KAAM,QAAO;AAClB,YAAM,aAAa,EAAE,GAAG,KAAK;AAC7B,YAAM,YAAY,6BAA6B,IAAI;AACnD,iBAAW,OAAO,OAAO,KAAK,UAAU,GAAG;AACzC,YAAI,IAAI,WAAW,KAAK,EAAG,QAAO,WAAW,GAAG;AAAA,MAClD;AACA,aAAO,EAAE,GAAG,YAAY,GAAG,UAAU;AAAA,IACvC;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,UAAU,OAAO,EAAE,KAAK,IAAI,MAAM;AAChC,cAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,cAAM,UAAU,aAAa,MAAM,kBAAkB,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC;AAC/E,eAAO,EAAE,MAAM,QAAQ;AAAA,MACzB;AAAA,MACA,UAAU,CAAC,EAAE,OAAO,OAAO,EAAE,IAAI,QAAQ,gBAAgB,MAAM,SAAS,QAAQ,WAAW,KAAK;AAAA,MAChG,QAAQ;AAAA,IACV;AAAA,IACA,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,UAAU,OAAO,EAAE,KAAK,IAAI,MAAM;AAChC,cAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,cAAM,UAAU,aAAa,MAAM,kBAAkB,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC;AAC/E,eAAO,EAAE,MAAM,QAAQ;AAAA,MACzB;AAAA,MACA,UAAU,CAAC,EAAE,OAAO,OAAO,EAAE,IAAI,QAAQ,gBAAgB,MAAM,SAAS,QAAQ,WAAW,KAAK;AAAA,IAClG;AAAA,IACA,QAAQ;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,UAAU,OAAO,EAAE,KAAK,IAAI,MAAM;AAChC,cAAM,EAAE,UAAU,IAAI,MAAM,oBAAoB;AAChD,cAAM,UAAU,aAAa;AAAA,UAC3B;AAAA,YACE;AAAA,cACE,GAAK,KAAa,QAAQ,CAAC;AAAA,cAC3B,GAAK,KAAa,SAAS,CAAC;AAAA,YAC9B;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AACA,YAAI,CAAC,QAAQ,MAAM,CAAC,QAAQ,SAAS;AACnC,gBAAM,IAAI,cAAc,KAAK,EAAE,OAAO,UAAU,gCAAgC,qCAAqC,EAAE,CAAC;AAAA,QAC1H;AACA,eAAO,EAAE,MAAM,QAAQ;AAAA,MACzB;AAAA,MACA,UAAU,OAAO,EAAE,IAAI,KAAK;AAAA,IAC9B;AAAA,EACF;AACF,CAAC;AAED,MAAM,EAAE,KAAK,MAAM,KAAK,OAAO,IAAI;AAE5B,MAAM,WAAW;AAGxB,MAAM,mBAAmB,EAAE,OAAO;AAAA,EAChC,IAAI,EAAE,OAAO,EAAE,KAAK;AAAA,EACpB,UAAU,EAAE,OAAO,EAAE,KAAK;AAAA,EAC1B,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EACrD,OAAO,EAAE,OAAO;AAAA,EAChB,MAAM,EAAE,OAAO;AAAA,EACf,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACrC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACtC,gBAAgB,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC/C,cAAc,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS;AAAA,EACpD,MAAM,EAAE,OAAO;AAAA,EACf,YAAY,EAAE,OAAO;AAAA,EACrB,cAAc,EAAE,OAAO;AAAA,EACvB,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EAC9C,UAAU,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,EAAE,SAAS,EAAE,SAAS;AAAA,EAChE,UAAU,EAAE,OAAO;AAAA,EACnB,YAAY,EAAE,OAAO;AAAA,EACrB,YAAY,EAAE,OAAO;AACvB,CAAC;AAEM,MAAM,UAAU,uBAAuB;AAAA,EAC5C,cAAc;AAAA,EACd,aAAa;AAAA,EACb,oBAAoB,8BAA8B,gBAAgB;AAAA,EAClE,QAAQ;AAAA,IACN,QAAQ;AAAA,IACR,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAAA,IACpG,aAAa;AAAA,EACf;AAAA,EACA,QAAQ;AAAA,IACN,QAAQ;AAAA,IACR,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AAAA,IACpG,aAAa;AAAA,EACf;AAAA,EACA,KAAK;AAAA,IACH,QAAQ;AAAA,IACR,gBAAgB;AAAA,IAChB,aAAa;AAAA,EACf;AACF,CAAC;",
6
6
  "names": []
7
7
  }
@@ -57,6 +57,9 @@ import {
57
57
  } from "../../customers/data/entities.js";
58
58
  import {
59
59
  enforceAdjustmentSign,
60
+ validateReturnAdjustmentWithinRemaining,
61
+ RETURN_ADJUSTMENT_EXCEEDS_REMAINING_GROSS_MESSAGE,
62
+ RETURN_ADJUSTMENT_EXCEEDS_REMAINING_NET_MESSAGE,
60
63
  quoteCreateSchema,
61
64
  quoteLineCreateSchema,
62
65
  quoteAdjustmentCreateSchema,
@@ -5599,6 +5602,57 @@ const orderAdjustmentUpsertCommand = {
5599
5602
  shippingMethodCode: order.shippingMethodCode ?? null,
5600
5603
  paymentMethodCode: order.paymentMethodCode ?? null
5601
5604
  });
5605
+ const effectiveAdjustment = nextAdjustments.find(
5606
+ (adj) => adj.id === adjustmentId
5607
+ );
5608
+ if (effectiveAdjustment?.kind === "return") {
5609
+ const baselineAdjustments = nextAdjustments.filter(
5610
+ (adj) => adj.id !== adjustmentId
5611
+ );
5612
+ const baselineCalculation = await salesCalculationService.calculateDocumentTotals({
5613
+ documentKind: "order",
5614
+ lines: calcLines,
5615
+ adjustments: baselineAdjustments,
5616
+ context: calculationContext,
5617
+ existingTotals: resolveExistingPaymentTotals(order)
5618
+ });
5619
+ const issues = validateReturnAdjustmentWithinRemaining({
5620
+ kind: "return",
5621
+ amountNet: effectiveAdjustment.amountNet ?? effectiveAdjustment.amountGross ?? 0,
5622
+ amountGross: effectiveAdjustment.amountGross ?? effectiveAdjustment.amountNet ?? 0,
5623
+ remainingNet: Number(
5624
+ baselineCalculation.totals?.grandTotalNetAmount ?? 0
5625
+ ),
5626
+ remainingGross: Number(
5627
+ baselineCalculation.totals?.grandTotalGrossAmount ?? 0
5628
+ )
5629
+ });
5630
+ if (issues.length > 0) {
5631
+ const { translate } = await resolveTranslations();
5632
+ const grossIssue = issues.find((issue) => issue.path === "amountGross");
5633
+ const netIssue = issues.find((issue) => issue.path === "amountNet");
5634
+ const fieldErrors = {};
5635
+ if (grossIssue) {
5636
+ fieldErrors.amountGross = translate(
5637
+ "sales.adjustments.error.returnExceedsRemainingGrandTotalGross",
5638
+ RETURN_ADJUSTMENT_EXCEEDS_REMAINING_GROSS_MESSAGE
5639
+ );
5640
+ }
5641
+ if (netIssue) {
5642
+ fieldErrors.amountNet = translate(
5643
+ "sales.adjustments.error.returnExceedsRemainingGrandTotalNet",
5644
+ RETURN_ADJUSTMENT_EXCEEDS_REMAINING_NET_MESSAGE
5645
+ );
5646
+ }
5647
+ throw new CrudHttpError(400, {
5648
+ error: fieldErrors.amountGross ?? fieldErrors.amountNet ?? translate(
5649
+ "sales.adjustments.error.returnExceedsRemainingGrandTotalGross",
5650
+ RETURN_ADJUSTMENT_EXCEEDS_REMAINING_GROSS_MESSAGE
5651
+ ),
5652
+ fieldErrors
5653
+ });
5654
+ }
5655
+ }
5602
5656
  const calculation = await salesCalculationService.calculateDocumentTotals({
5603
5657
  documentKind: "order",
5604
5658
  lines: calcLines,
@@ -5942,6 +5996,56 @@ const quoteAdjustmentUpsertCommand = {
5942
5996
  shippingMethodCode: quote.shippingMethodCode ?? null,
5943
5997
  paymentMethodCode: quote.paymentMethodCode ?? null
5944
5998
  });
5999
+ const effectiveAdjustment = nextAdjustments.find(
6000
+ (adj) => adj.id === adjustmentId
6001
+ );
6002
+ if (effectiveAdjustment?.kind === "return") {
6003
+ const baselineAdjustments = nextAdjustments.filter(
6004
+ (adj) => adj.id !== adjustmentId
6005
+ );
6006
+ const baselineCalculation = await salesCalculationService.calculateDocumentTotals({
6007
+ documentKind: "quote",
6008
+ lines: calcLines,
6009
+ adjustments: baselineAdjustments,
6010
+ context: calculationContext
6011
+ });
6012
+ const issues = validateReturnAdjustmentWithinRemaining({
6013
+ kind: "return",
6014
+ amountNet: effectiveAdjustment.amountNet ?? effectiveAdjustment.amountGross ?? 0,
6015
+ amountGross: effectiveAdjustment.amountGross ?? effectiveAdjustment.amountNet ?? 0,
6016
+ remainingNet: Number(
6017
+ baselineCalculation.totals?.grandTotalNetAmount ?? 0
6018
+ ),
6019
+ remainingGross: Number(
6020
+ baselineCalculation.totals?.grandTotalGrossAmount ?? 0
6021
+ )
6022
+ });
6023
+ if (issues.length > 0) {
6024
+ const { translate } = await resolveTranslations();
6025
+ const grossIssue = issues.find((issue) => issue.path === "amountGross");
6026
+ const netIssue = issues.find((issue) => issue.path === "amountNet");
6027
+ const fieldErrors = {};
6028
+ if (grossIssue) {
6029
+ fieldErrors.amountGross = translate(
6030
+ "sales.adjustments.error.returnExceedsRemainingGrandTotalGross",
6031
+ RETURN_ADJUSTMENT_EXCEEDS_REMAINING_GROSS_MESSAGE
6032
+ );
6033
+ }
6034
+ if (netIssue) {
6035
+ fieldErrors.amountNet = translate(
6036
+ "sales.adjustments.error.returnExceedsRemainingGrandTotalNet",
6037
+ RETURN_ADJUSTMENT_EXCEEDS_REMAINING_NET_MESSAGE
6038
+ );
6039
+ }
6040
+ throw new CrudHttpError(400, {
6041
+ error: fieldErrors.amountGross ?? fieldErrors.amountNet ?? translate(
6042
+ "sales.adjustments.error.returnExceedsRemainingGrandTotalGross",
6043
+ RETURN_ADJUSTMENT_EXCEEDS_REMAINING_GROSS_MESSAGE
6044
+ ),
6045
+ fieldErrors
6046
+ });
6047
+ }
6048
+ }
5945
6049
  const calculation = await salesCalculationService.calculateDocumentTotals({
5946
6050
  documentKind: "quote",
5947
6051
  lines: calcLines,