@open-mercato/core 0.9.1-develop.7477.1.64ba865101 → 0.9.1-develop.7497.1.543ea44c40
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/business_rules/data/validators.js +8 -3
- package/dist/modules/business_rules/data/validators.js.map +2 -2
- package/dist/modules/catalog/api/dictionaries/[key]/route.js +35 -7
- package/dist/modules/catalog/api/dictionaries/[key]/route.js.map +2 -2
- package/dist/modules/communication_channels/lib/email-mime.js +1 -2
- package/dist/modules/communication_channels/lib/email-mime.js.map +2 -2
- package/dist/modules/configs/cli.js +8 -2
- package/dist/modules/configs/cli.js.map +2 -2
- package/dist/modules/customers/api/companies/[id]/people/route.js +3 -0
- package/dist/modules/customers/api/companies/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/companies/route.js +3 -3
- package/dist/modules/customers/api/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/companies/route.js +3 -0
- package/dist/modules/customers/api/deals/[id]/companies/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +3 -0
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/dictionaries/kind-settings/route.js +6 -0
- package/dist/modules/customers/api/dictionaries/kind-settings/route.js.map +2 -2
- package/dist/modules/customers/api/labels/route.js +10 -1
- package/dist/modules/customers/api/labels/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js +6 -0
- package/dist/modules/customers/api/people/[id]/companies/[linkId]/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js +3 -0
- package/dist/modules/customers/api/people/[id]/companies/enriched/route.js.map +2 -2
- package/dist/modules/customers/api/people/[id]/companies/route.js +6 -0
- package/dist/modules/customers/api/people/[id]/companies/route.js.map +2 -2
- package/dist/modules/customers/api/people/route.js +3 -3
- package/dist/modules/customers/api/people/route.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +2 -0
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/components/ActivityTypeEditor.js +11 -5
- package/dist/modules/customers/components/ActivityTypeEditor.js.map +2 -2
- package/dist/modules/customers/components/detail/InlineEditors.js +7 -3
- package/dist/modules/customers/components/detail/InlineEditors.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonHighlights.js +1 -1
- package/dist/modules/customers/components/detail/PersonHighlights.js.map +2 -2
- package/dist/modules/customers/components/detail/PlannedActivitiesSection.js +4 -5
- package/dist/modules/customers/components/detail/PlannedActivitiesSection.js.map +2 -2
- package/dist/modules/data_sync/di.js.map +2 -2
- package/dist/modules/data_sync/lib/sync-schedule-service.js +60 -27
- package/dist/modules/data_sync/lib/sync-schedule-service.js.map +2 -2
- package/dist/modules/messages/commands/messages.js +10 -7
- package/dist/modules/messages/commands/messages.js.map +2 -2
- package/dist/modules/messages/lib/constants.js +3 -1
- package/dist/modules/messages/lib/constants.js.map +2 -2
- package/dist/modules/messages/subscribers/message-notification.js +2 -1
- package/dist/modules/messages/subscribers/message-notification.js.map +2 -2
- package/dist/modules/sales/api/documents/factory.js +3 -4
- package/dist/modules/sales/api/documents/factory.js.map +2 -2
- package/dist/modules/sales/commands/payments.js +9 -1
- package/dist/modules/sales/commands/payments.js.map +2 -2
- package/package.json +7 -7
- package/src/modules/business_rules/data/validators.ts +12 -3
- package/src/modules/catalog/api/dictionaries/[key]/route.ts +49 -7
- package/src/modules/communication_channels/lib/email-mime.ts +1 -2
- package/src/modules/configs/cli.ts +10 -1
- package/src/modules/customers/api/companies/[id]/people/route.ts +3 -0
- package/src/modules/customers/api/companies/route.ts +6 -6
- package/src/modules/customers/api/deals/[id]/companies/route.ts +3 -0
- package/src/modules/customers/api/deals/[id]/people/route.ts +3 -0
- package/src/modules/customers/api/dictionaries/kind-settings/route.ts +6 -0
- package/src/modules/customers/api/labels/route.ts +10 -1
- package/src/modules/customers/api/people/[id]/companies/[linkId]/route.ts +6 -0
- package/src/modules/customers/api/people/[id]/companies/enriched/route.ts +3 -0
- package/src/modules/customers/api/people/[id]/companies/route.ts +6 -0
- package/src/modules/customers/api/people/route.ts +6 -6
- package/src/modules/customers/commands/deals.ts +2 -0
- package/src/modules/customers/components/ActivityTypeEditor.tsx +11 -5
- package/src/modules/customers/components/detail/InlineEditors.tsx +8 -4
- package/src/modules/customers/components/detail/PersonHighlights.tsx +4 -1
- package/src/modules/customers/components/detail/PlannedActivitiesSection.tsx +4 -5
- package/src/modules/customers/i18n/de.json +2 -0
- package/src/modules/customers/i18n/en.json +2 -0
- package/src/modules/customers/i18n/es.json +2 -0
- package/src/modules/customers/i18n/ko.json +2 -0
- package/src/modules/customers/i18n/pl.json +2 -0
- package/src/modules/data_sync/di.ts +1 -0
- package/src/modules/data_sync/lib/sync-schedule-service.ts +80 -28
- package/src/modules/messages/commands/messages.ts +10 -7
- package/src/modules/messages/lib/constants.ts +6 -0
- package/src/modules/messages/subscribers/message-notification.ts +2 -0
- package/src/modules/sales/api/documents/factory.ts +6 -7
- package/src/modules/sales/commands/payments.ts +10 -2
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
resolveActorFeatures,
|
|
19
19
|
resolveMessageChannelThreadAccess,
|
|
20
20
|
} from '../lib/channelThreadAccess'
|
|
21
|
-
import { MESSAGE_ATTACHMENT_ENTITY_ID, MESSAGE_ENTITY_ID } from '../lib/constants'
|
|
21
|
+
import { MESSAGE_ATTACHMENT_ENTITY_ID, MESSAGE_ENTITY_ID, SYSTEM_SENDER_USER_ID } from '../lib/constants'
|
|
22
22
|
import { canUseChannelThreadFallback } from '../lib/routeHelpers'
|
|
23
23
|
import { getMessageTypeOrDefault } from '../lib/message-types-registry'
|
|
24
24
|
import { validateMessageObjectsForType } from '../lib/object-validation'
|
|
@@ -779,24 +779,25 @@ const replyMessageCommand: CommandHandler<unknown, { id: string; externalEmail:
|
|
|
779
779
|
const messageType = getMessageTypeOrDefault(original.type)
|
|
780
780
|
if (messageType.allowReply === false) throw new Error('Reply is not allowed for this message type')
|
|
781
781
|
|
|
782
|
+
const isReplyRecipient = (userId: string) => userId !== input.userId && userId !== SYSTEM_SENDER_USER_ID
|
|
782
783
|
const recipientIds = new Set(
|
|
783
784
|
(input.recipients ?? [])
|
|
784
785
|
.map((recipient) => recipient.userId)
|
|
785
|
-
.filter(
|
|
786
|
+
.filter(isReplyRecipient),
|
|
786
787
|
)
|
|
787
788
|
|
|
788
789
|
if (recipientIds.size === 0) {
|
|
789
790
|
const originalRecipients = await em.find(MessageRecipient, { messageId: original.id, deletedAt: null })
|
|
790
791
|
if (input.replyAll) {
|
|
791
|
-
if (original.senderUserId
|
|
792
|
+
if (isReplyRecipient(original.senderUserId)) recipientIds.add(original.senderUserId)
|
|
792
793
|
for (const recipient of originalRecipients) {
|
|
793
|
-
if (recipient.recipientUserId
|
|
794
|
+
if (isReplyRecipient(recipient.recipientUserId)) recipientIds.add(recipient.recipientUserId)
|
|
794
795
|
}
|
|
795
796
|
} else if (original.senderUserId !== input.userId) {
|
|
796
|
-
recipientIds.add(original.senderUserId)
|
|
797
|
+
if (isReplyRecipient(original.senderUserId)) recipientIds.add(original.senderUserId)
|
|
797
798
|
} else {
|
|
798
799
|
for (const recipient of originalRecipients) {
|
|
799
|
-
if (recipient.recipientUserId
|
|
800
|
+
if (isReplyRecipient(recipient.recipientUserId)) {
|
|
800
801
|
recipientIds.add(recipient.recipientUserId)
|
|
801
802
|
break
|
|
802
803
|
}
|
|
@@ -807,7 +808,9 @@ const replyMessageCommand: CommandHandler<unknown, { id: string; externalEmail:
|
|
|
807
808
|
recipientIds.add(input.userId)
|
|
808
809
|
}
|
|
809
810
|
}
|
|
810
|
-
if (recipientIds.size === 0
|
|
811
|
+
if (recipientIds.size === 0 && original.senderUserId !== SYSTEM_SENDER_USER_ID) {
|
|
812
|
+
throw new Error('No recipients available for reply')
|
|
813
|
+
}
|
|
811
814
|
|
|
812
815
|
let messageId = ''
|
|
813
816
|
let responseExternalEmail: string | null = null
|
|
@@ -5,3 +5,9 @@ export const MESSAGE_ATTACHMENT_PARTITION = 'messages'
|
|
|
5
5
|
// Resource kind used by the command-level OSS optimistic-lock guard so stale
|
|
6
6
|
// draft edits and message actions fail with the structured 409 conflict.
|
|
7
7
|
export const MESSAGE_OPTIMISTIC_LOCK_RESOURCE_KIND = 'messages.message'
|
|
8
|
+
|
|
9
|
+
// Sender of messages composed on behalf of the platform rather than a person —
|
|
10
|
+
// a communication channel's inbound ingest, inbox_ops, warranty_claims. No
|
|
11
|
+
// `users` row exists for it, so it can never be a reply or notification
|
|
12
|
+
// recipient (#6391).
|
|
13
|
+
export const SYSTEM_SENDER_USER_ID = '00000000-0000-0000-0000-000000000000'
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
import { User } from '../../auth/data/entities'
|
|
11
11
|
import { Message } from '../data/entities'
|
|
12
12
|
import { notificationTypes } from '../notifications'
|
|
13
|
+
import { SYSTEM_SENDER_USER_ID } from '../lib/constants'
|
|
13
14
|
import { resolveMessageChannelThreadAccess } from '../lib/channelThreadAccess'
|
|
14
15
|
import {
|
|
15
16
|
EXTERNAL_CONVERSATION_SOURCE_ENTITY_TYPE,
|
|
@@ -156,6 +157,7 @@ async function isChannelRoutedMessage(payload: MessageSentPayload, ctx: Resolver
|
|
|
156
157
|
|
|
157
158
|
export default async function handle(payload: MessageSentPayload, ctx: ResolverContext): Promise<void> {
|
|
158
159
|
const uniqueRecipientUserIds = Array.from(new Set(payload.recipientUserIds))
|
|
160
|
+
.filter((recipientUserId) => recipientUserId !== SYSTEM_SENDER_USER_ID)
|
|
159
161
|
|
|
160
162
|
const typeDef = notificationTypes.find((type) => type.type === 'messages.new')
|
|
161
163
|
if (typeDef && uniqueRecipientUserIds.length > 0) {
|
|
@@ -24,7 +24,7 @@ import { parseScopedCommandInput, resolveCrudRecordId } from '../utils'
|
|
|
24
24
|
import { documentUpdateSchema } from '../../commands/documents'
|
|
25
25
|
import { buildIlikeTerm } from '@open-mercato/shared/lib/db/buildIlikeTerm'
|
|
26
26
|
import { parseBooleanToken } from '@open-mercato/shared/lib/boolean'
|
|
27
|
-
import { parseIdsParam } from '@open-mercato/shared/lib/crud/ids'
|
|
27
|
+
import { isUuidListParam, parseIdsParam, splitIdListParam } from '@open-mercato/shared/lib/crud/ids'
|
|
28
28
|
import type { RbacService } from '@open-mercato/core/modules/auth/services/rbacService'
|
|
29
29
|
import { parseDecryptedFieldValue } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'
|
|
30
30
|
|
|
@@ -111,7 +111,10 @@ const listSchema = z
|
|
|
111
111
|
totalGrossMax: z.coerce.number().optional(),
|
|
112
112
|
dateFrom: z.string().optional(),
|
|
113
113
|
dateTo: z.string().optional(),
|
|
114
|
-
tagIds: z
|
|
114
|
+
tagIds: z
|
|
115
|
+
.string()
|
|
116
|
+
.optional()
|
|
117
|
+
.refine(isUuidListParam, { message: 'tagIds must be a comma-separated list of UUIDs' }),
|
|
115
118
|
tagIdsEmpty: z.string().optional(),
|
|
116
119
|
sortField: z.string().optional(),
|
|
117
120
|
sortDir: z.enum(['asc', 'desc']).optional(),
|
|
@@ -180,11 +183,7 @@ function buildFilters(query: ListQuery, numberColumn: string, kind: DocumentKind
|
|
|
180
183
|
if (Object.keys(dateRange).length) {
|
|
181
184
|
filters.created_at = dateRange
|
|
182
185
|
}
|
|
183
|
-
const
|
|
184
|
-
const tagIds = tagIdsRaw
|
|
185
|
-
.split(',')
|
|
186
|
-
.map((value) => value.trim())
|
|
187
|
-
.filter((value) => value.length > 0)
|
|
186
|
+
const tagIds = splitIdListParam(query.tagIds)
|
|
188
187
|
if (parseBooleanToken(query.tagIdsEmpty) === true) {
|
|
189
188
|
filters.id = { $eq: '00000000-0000-0000-0000-000000000000' }
|
|
190
189
|
} else if (tagIds.length) {
|
|
@@ -250,7 +250,14 @@ export async function restorePaymentSnapshot(em: EntityManager, snapshot: Paymen
|
|
|
250
250
|
em.persist(entity)
|
|
251
251
|
}
|
|
252
252
|
|
|
253
|
-
|
|
253
|
+
const NON_SETTLING_PAYMENT_STATUSES = new Set(['failed', 'canceled', 'cancelled'])
|
|
254
|
+
|
|
255
|
+
export function paymentCountsTowardOrderBalance(payment: Pick<SalesPayment, 'status'>): boolean {
|
|
256
|
+
const status = typeof payment.status === 'string' ? payment.status.trim().toLowerCase() : ''
|
|
257
|
+
return !NON_SETTLING_PAYMENT_STATUSES.has(status)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export async function recomputeOrderPaymentTotals(
|
|
254
261
|
em: EntityManager,
|
|
255
262
|
order: SalesOrder,
|
|
256
263
|
options?: { lock?: boolean }
|
|
@@ -282,10 +289,11 @@ async function recomputeOrderPaymentTotals(
|
|
|
282
289
|
if (paymentId) paymentIds.add(paymentId)
|
|
283
290
|
})
|
|
284
291
|
|
|
285
|
-
const
|
|
292
|
+
const loadedPayments =
|
|
286
293
|
paymentIds.size > 0
|
|
287
294
|
? await findWithDecryption(em, SalesPayment, { id: { $in: Array.from(paymentIds) }, deletedAt: null, ...scope }, {}, scope)
|
|
288
295
|
: await findWithDecryption(em, SalesPayment, { order: orderId, deletedAt: null, ...scope }, {}, scope)
|
|
296
|
+
const payments = loadedPayments.filter(paymentCountsTowardOrderBalance)
|
|
289
297
|
|
|
290
298
|
const resolvePaidAmount = (payment: SalesPayment) => {
|
|
291
299
|
const captured = toNumber(payment.capturedAmount)
|