@dalmore/api-contracts 0.0.0-dev.2047f71 → 0.0.0-dev.3af7603

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 (37) hide show
  1. package/common/types/account-setting.types.ts +31 -0
  2. package/common/types/activity.types.ts +1 -1
  3. package/common/types/bonus-tier.types.ts +33 -0
  4. package/common/types/cart.types.ts +4 -1
  5. package/common/types/common.types.ts +16 -6
  6. package/common/types/dashboard.types.ts +2 -9
  7. package/common/types/disbursements.types.ts +119 -3
  8. package/common/types/file.types.ts +20 -4
  9. package/common/types/i-will-do-it-later.types.ts +68 -0
  10. package/common/types/index.ts +2 -0
  11. package/common/types/individuals.types.ts +2 -15
  12. package/common/types/issuer-offering.types.ts +14 -24
  13. package/common/types/issuer-payment-method.types.ts +41 -0
  14. package/common/types/issuer.types.ts +9 -0
  15. package/common/types/notification.types.ts +239 -29
  16. package/common/types/offering.types.ts +5 -15
  17. package/common/types/site.types.ts +2 -9
  18. package/common/types/{trade-line-item.type.ts → trade-line-item.types.ts} +2 -9
  19. package/common/types/trade.types.ts +64 -1
  20. package/common/types/transaction.types.ts +12 -1
  21. package/common/types/user.types.ts +15 -28
  22. package/contracts/clients/cart/index.ts +80 -0
  23. package/contracts/clients/index.ts +10 -0
  24. package/contracts/clients/issuer-payment-methods/index.ts +39 -0
  25. package/contracts/clients/payment-methods/index.ts +85 -0
  26. package/contracts/clients/trade-line-items/index.ts +66 -0
  27. package/contracts/clients/trades/index.ts +65 -1
  28. package/contracts/clients/transactions/index.ts +37 -0
  29. package/contracts/compliance/bonus-tiers/index.ts +21 -2
  30. package/contracts/compliance/trade-line-items/index.ts +1 -1
  31. package/contracts/compliance/users/index.ts +21 -0
  32. package/contracts/investors/bonus-tiers/index.ts +18 -0
  33. package/contracts/investors/individuals/index.ts +22 -0
  34. package/contracts/investors/trade-line-items/index.ts +1 -1
  35. package/contracts/issuers/bonus-tiers/index.ts +18 -0
  36. package/contracts/issuers/disbursements/index.ts +36 -0
  37. package/package.json +1 -1
@@ -1,58 +1,268 @@
1
1
  import { extendZodWithOpenApi } from '@anatine/zod-openapi';
2
2
  import { z } from 'zod';
3
3
  import { TypeID } from 'typeid-js';
4
- import { accountIdSchema } from './account.types';
4
+ import { IBaseEntity } from './entity.types';
5
5
 
6
6
  extendZodWithOpenApi(z);
7
- export enum NotificationChannel {
7
+
8
+ export enum NotificationChannelType {
8
9
  EMAIL = 'EMAIL',
9
10
  SLACK = 'SLACK',
11
+ WEBHOOK = 'WEBHOOK',
10
12
  }
11
- export enum NotificationType {
12
- COMPLIANCE_TRADE_ALERT = 'COMPLIANCE_TRADE_ALERT',
13
- TRADE_ALERT = 'TRADE_ALERT',
13
+
14
+ export enum NotificationRecordStatus {
15
+ PENDING = 'PENDING',
16
+ SENT = 'SENT',
17
+ FAILED = 'FAILED',
14
18
  }
15
19
 
16
- export const notificationIdSchema = z.string().refine(
20
+ export const notificationChannelIdSchema = z.string().refine(
17
21
  (value) => {
18
22
  try {
19
23
  const tid = TypeID.fromString(value);
20
- return tid.getType() === 'notification';
24
+ return tid.getType() === 'notification_channel';
21
25
  } catch {
22
26
  return false;
23
27
  }
24
28
  },
25
29
  {
26
30
  message:
27
- 'Invalid notification ID format. Must be a valid TypeID with "notification" prefix.',
31
+ 'Invalid notification channel ID format. Must be a valid TypeID with "notification_channel" prefix.',
28
32
  },
29
33
  );
30
34
 
31
- export const SendNotificationZod = z.object({
32
- message: z.string(),
35
+ export const notificationChannelTriggerIdSchema = z.string().refine(
36
+ (value) => {
37
+ try {
38
+ const tid = TypeID.fromString(value);
39
+ return tid.getType() === 'notification_channel_trigger';
40
+ } catch {
41
+ return false;
42
+ }
43
+ },
44
+ {
45
+ message:
46
+ 'Invalid notification channel trigger ID format. Must be a valid TypeID with "notification_channel_trigger" prefix.',
47
+ },
48
+ );
49
+
50
+ export const notificationRecordIdSchema = z.string().refine(
51
+ (value) => {
52
+ try {
53
+ const tid = TypeID.fromString(value);
54
+ return tid.getType() === 'notification_record';
55
+ } catch {
56
+ return false;
57
+ }
58
+ },
59
+ {
60
+ message:
61
+ 'Invalid notification record ID format. Must be a valid TypeID with "notification_record" prefix.',
62
+ },
63
+ );
64
+
65
+ export const EmailChannelSettingsSchema = z.object({
66
+ recipients: z.array(z.string().email()).min(1),
67
+ subjectTemplate: z.string().optional(),
68
+ });
69
+ export type EmailChannelSettings = z.infer<typeof EmailChannelSettingsSchema>;
70
+
71
+ export const SlackChannelSettingsSchema = z
72
+ .object({
73
+ webhookUrl: z.string().url().optional(),
74
+ channelEmail: z.string().email().optional(),
75
+ })
76
+ .refine((data) => data.webhookUrl || data.channelEmail, {
77
+ message: 'Either webhookUrl or channelEmail is required',
78
+ });
79
+ export type SlackChannelSettings = z.infer<typeof SlackChannelSettingsSchema>;
80
+
81
+ export const WebhookChannelSettingsSchema = z.object({
82
+ url: z.string().url(),
83
+ method: z.enum(['POST', 'PUT']),
84
+ headers: z.record(z.string()).optional(),
85
+ authType: z.enum(['none', 'bearer', 'basic', 'api_key']).default('none'),
86
+ authValue: z.string().optional(),
87
+ });
88
+ export type WebhookChannelSettings = z.infer<
89
+ typeof WebhookChannelSettingsSchema
90
+ >;
91
+
92
+ export const NotificationChannelSettingsSchema = z.discriminatedUnion('type', [
93
+ z.object({
94
+ type: z.literal(NotificationChannelType.EMAIL),
95
+ config: EmailChannelSettingsSchema,
96
+ }),
97
+ z.object({
98
+ type: z.literal(NotificationChannelType.SLACK),
99
+ config: SlackChannelSettingsSchema,
100
+ }),
101
+ z.object({
102
+ type: z.literal(NotificationChannelType.WEBHOOK),
103
+ config: WebhookChannelSettingsSchema,
104
+ }),
105
+ ]);
106
+ export type NotificationChannelSettings = z.infer<
107
+ typeof NotificationChannelSettingsSchema
108
+ >;
109
+
110
+ export const EmailNotificationPayloadSchema = z.object({
111
+ to: z.array(z.string().email()),
33
112
  subject: z.string(),
34
- buttonText: z.string(),
35
- link: z.string(),
36
- debug: z.boolean().default(false),
37
- notificationChannel: z.nativeEnum(NotificationChannel),
38
- channelName: z.string(),
39
- channelEmail: z.string().email(),
40
- notificationType: z.nativeEnum(NotificationType),
113
+ body: z.string(),
114
+ html: z.string().optional(),
41
115
  });
42
- export type SendNotificationZod = z.infer<typeof SendNotificationZod>;
116
+ export type EmailNotificationPayload = z.infer<
117
+ typeof EmailNotificationPayloadSchema
118
+ >;
43
119
 
44
- const SlackSettingsSchema = z.object({
45
- channelName: z.string().min(1).max(50),
46
- channelEmail: z.string().email(),
120
+ export const SlackNotificationPayloadSchema = z.object({
121
+ webhookUrl: z.string().url().optional(),
122
+ channelEmail: z.string().email().optional(),
123
+ message: z.string(),
124
+ blocks: z.array(z.record(z.unknown())).optional(),
47
125
  });
126
+ export type SlackNotificationPayload = z.infer<
127
+ typeof SlackNotificationPayloadSchema
128
+ >;
48
129
 
49
- export const PostNotificationZod = z.object({
50
- accountId: accountIdSchema,
51
- notificationChannel: z.literal(NotificationChannel.SLACK), // Only Slack for now
52
- notificationType: z.nativeEnum(NotificationType),
53
- enabled: z.boolean().default(true),
54
- debug: z.boolean().default(false),
55
- settings: SlackSettingsSchema,
130
+ export const WebhookNotificationPayloadSchema = z.object({
131
+ url: z.string().url(),
132
+ method: z.enum(['POST', 'PUT']),
133
+ headers: z.record(z.string()),
134
+ body: z.record(z.unknown()),
56
135
  });
136
+ export type WebhookNotificationPayload = z.infer<
137
+ typeof WebhookNotificationPayloadSchema
138
+ >;
139
+
140
+ export const NotificationPayloadSchema = z.discriminatedUnion('type', [
141
+ z.object({
142
+ type: z.literal(NotificationChannelType.EMAIL),
143
+ data: EmailNotificationPayloadSchema,
144
+ }),
145
+ z.object({
146
+ type: z.literal(NotificationChannelType.SLACK),
147
+ data: SlackNotificationPayloadSchema,
148
+ }),
149
+ z.object({
150
+ type: z.literal(NotificationChannelType.WEBHOOK),
151
+ data: WebhookNotificationPayloadSchema,
152
+ }),
153
+ ]);
154
+ export type NotificationPayload = z.infer<typeof NotificationPayloadSchema>;
57
155
 
58
- export type PostNotificationZod = z.infer<typeof PostNotificationZod>;
156
+ export const EmailNotificationResponseSchema = z.object({
157
+ messageId: z.string().optional(),
158
+ accepted: z.array(z.string()).optional(),
159
+ rejected: z.array(z.string()).optional(),
160
+ });
161
+ export type EmailNotificationResponse = z.infer<
162
+ typeof EmailNotificationResponseSchema
163
+ >;
164
+
165
+ export const SlackNotificationResponseSchema = z.object({
166
+ ok: z.boolean().optional(),
167
+ error: z.string().optional(),
168
+ responseBody: z.string().optional(),
169
+ });
170
+ export type SlackNotificationResponse = z.infer<
171
+ typeof SlackNotificationResponseSchema
172
+ >;
173
+
174
+ export const WebhookNotificationResponseSchema = z.object({
175
+ statusCode: z.number(),
176
+ headers: z.record(z.string()).optional(),
177
+ body: z.unknown().optional(),
178
+ });
179
+ export type WebhookNotificationResponse = z.infer<
180
+ typeof WebhookNotificationResponseSchema
181
+ >;
182
+
183
+ export const NotificationResponseSchema = z.discriminatedUnion('type', [
184
+ z.object({
185
+ type: z.literal(NotificationChannelType.EMAIL),
186
+ data: EmailNotificationResponseSchema,
187
+ }),
188
+ z.object({
189
+ type: z.literal(NotificationChannelType.SLACK),
190
+ data: SlackNotificationResponseSchema,
191
+ }),
192
+ z.object({
193
+ type: z.literal(NotificationChannelType.WEBHOOK),
194
+ data: WebhookNotificationResponseSchema,
195
+ }),
196
+ ]);
197
+ export type NotificationResponse = z.infer<typeof NotificationResponseSchema>;
198
+
199
+ export const INotificationChannelZod = IBaseEntity.extend({
200
+ id: notificationChannelIdSchema.openapi({
201
+ example: 'notification_channel_01j5y5ghx8fvc83dmx3pznq7hv',
202
+ }),
203
+ accountSettingsId: z.string().openapi({
204
+ example: 'account_setting_01j5y5ghx8fvc83dmx3pznq7hv',
205
+ }),
206
+ channelType: z.nativeEnum(NotificationChannelType).openapi({
207
+ example: NotificationChannelType.SLACK,
208
+ }),
209
+ name: z.string().openapi({
210
+ example: 'Compliance Alerts',
211
+ }),
212
+ enabled: z.boolean().openapi({
213
+ example: true,
214
+ }),
215
+ settings: NotificationChannelSettingsSchema,
216
+ });
217
+ export type INotificationChannelZod = z.infer<typeof INotificationChannelZod>;
218
+
219
+ export const INotificationChannelTriggerZod = IBaseEntity.extend({
220
+ id: notificationChannelTriggerIdSchema.openapi({
221
+ example: 'notification_channel_trigger_01j5y5ghx8fvc83dmx3pznq7hv',
222
+ }),
223
+ notificationChannelId: notificationChannelIdSchema.openapi({
224
+ example: 'notification_channel_01j5y5ghx8fvc83dmx3pznq7hv',
225
+ }),
226
+ activityTypeId: z.string().openapi({
227
+ example: 'activity_type_01j5y5ghx8fvc83dmx3pznq7hv',
228
+ }),
229
+ enabled: z.boolean().openapi({
230
+ example: true,
231
+ }),
232
+ });
233
+ export type INotificationChannelTriggerZod = z.infer<
234
+ typeof INotificationChannelTriggerZod
235
+ >;
236
+
237
+ export const INotificationRecordZod = IBaseEntity.extend({
238
+ id: notificationRecordIdSchema.openapi({
239
+ example: 'notification_record_01j5y5ghx8fvc83dmx3pznq7hv',
240
+ }),
241
+ notificationChannelId: notificationChannelIdSchema.openapi({
242
+ example: 'notification_channel_01j5y5ghx8fvc83dmx3pznq7hv',
243
+ }),
244
+ activityId: z.string().nullable().openapi({
245
+ example: 'activity_01j5y5ghx8fvc83dmx3pznq7hv',
246
+ }),
247
+ targetTable: z.string().openapi({
248
+ example: 'trades',
249
+ }),
250
+ targetId: z.string().openapi({
251
+ example: 'trade_01j5y5ghx8fvc83dmx3pznq7hv',
252
+ }),
253
+ status: z.nativeEnum(NotificationRecordStatus).openapi({
254
+ example: NotificationRecordStatus.SENT,
255
+ }),
256
+ payload: NotificationPayloadSchema,
257
+ response: NotificationResponseSchema.nullable(),
258
+ errorMessage: z.string().nullable().openapi({
259
+ example: null,
260
+ }),
261
+ retryCount: z.number().openapi({
262
+ example: 0,
263
+ }),
264
+ sentAt: z.date().nullable().openapi({
265
+ example: new Date(),
266
+ }),
267
+ });
268
+ export type INotificationRecordZod = z.infer<typeof INotificationRecordZod>;
@@ -17,6 +17,7 @@ import {
17
17
  OfferingOnboardingStatus,
18
18
  AssetType,
19
19
  DurationType,
20
+ StringToBooleanSchema,
20
21
  } from './common.types';
21
22
  import { IBaseEntity } from './entity.types';
22
23
  import { fileIdSchema, FileZod } from './file.types';
@@ -26,11 +27,7 @@ import {
26
27
  InvestorsOfferingsIncludeQuery,
27
28
  } from './investors-offering.types';
28
29
  import { OfferingStatus } from './issuer-offering.types';
29
- import {
30
- assetIdSchema,
31
- postAssetRefinement,
32
- AssetTemplateType,
33
- } from './asset.types';
30
+ import { postAssetRefinement, AssetTemplateType } from './asset.types';
34
31
 
35
32
  export enum OfferingFeeType {
36
33
  FIXED = 'FIXED',
@@ -184,7 +181,6 @@ export const PatchOfferingBase = z.object({
184
181
  });
185
182
  export const PatchOffering = PatchOfferingBase.merge(
186
183
  z.object({
187
- assetId: assetIdSchema,
188
184
  assetName: z
189
185
  .string()
190
186
  .min(2)
@@ -235,6 +231,7 @@ export const PatchOffering = PatchOfferingBase.merge(
235
231
  .nullable()
236
232
  .optional(),
237
233
  tiers: z.array(z.number().positive()).nullable().optional(),
234
+ enableBonus: z.boolean().optional(),
238
235
  }),
239
236
  );
240
237
  export type PatchOffering = z.infer<typeof PatchOffering>;
@@ -281,6 +278,7 @@ export const PostComplianceOffering = PatchOfferingBase.merge(
281
278
  .default(AssetTemplateType.STANDARD)
282
279
  .openapi({ example: AssetTemplateType.STANDARD }),
283
280
  tiers: z.array(z.number().positive()).nullable().optional(),
281
+ enableBonus: z.boolean().default(false).optional(),
284
282
  }),
285
283
  ).superRefine(postAssetRefinement);
286
284
  export type PostComplianceOffering = z.infer<typeof PostComplianceOffering>;
@@ -349,15 +347,7 @@ export const OfferingFiltersZod = z.object({
349
347
  issuerId: z.lazy(() => issuerIdSchema).optional(),
350
348
  type: z.nativeEnum(OfferingType).optional(),
351
349
  status: z.nativeEnum(ComplianceReview).optional(),
352
- enabled: z.preprocess(
353
- (val) =>
354
- val === 'true' || val === '1'
355
- ? true
356
- : val === 'false' || val === '0'
357
- ? false
358
- : val,
359
- z.boolean().optional(),
360
- ),
350
+ enabled: StringToBooleanSchema.optional(),
361
351
  managedBy: z.nativeEnum(ManagedByType).optional(),
362
352
  versioningType: z.nativeEnum(OfferingVersioningType).optional(),
363
353
  combinedStatus: z.nativeEnum(OfferingStatus).optional(),
@@ -5,6 +5,7 @@ import {
5
5
  AccountStatus,
6
6
  AccountZod,
7
7
  IPaginationMeta,
8
+ StringToBooleanSchema,
8
9
  UrlSchema,
9
10
  } from './common.types';
10
11
  import { accountIdSchema } from './account.types';
@@ -73,15 +74,7 @@ export const SitesParamSchema = z.object({
73
74
  export const SitesFiltersZod = z.object({
74
75
  url: z.string().optional(),
75
76
  accountId: accountIdSchema.optional(),
76
- enabled: z.preprocess(
77
- (val) =>
78
- val === 'true' || val === '1'
79
- ? true
80
- : val === 'false' || val === '0'
81
- ? false
82
- : val,
83
- z.boolean().optional(),
84
- ),
77
+ enabled: StringToBooleanSchema.optional(),
85
78
  });
86
79
 
87
80
  const sitesInclude = z.enum(['account']);
@@ -8,6 +8,7 @@ import {
8
8
  IPaginationMeta,
9
9
  OfferingType,
10
10
  SignatureStatus,
11
+ StringToBooleanSchema,
11
12
  } from './common.types';
12
13
  import { fileIdSchema } from './file.types';
13
14
  import { accountIdSchema } from './account.types';
@@ -107,15 +108,7 @@ export type TradeLineItemQuery = z.infer<typeof TradeLineItemQuery>;
107
108
 
108
109
  export const TradeLineItemFiltersQuery = z.object({
109
110
  accountId: accountIdSchema.optional(),
110
- hasSubdoc: z.preprocess(
111
- (val) =>
112
- val === 'true' || val === '1'
113
- ? true
114
- : val === 'false' || val === '0'
115
- ? false
116
- : val,
117
- z.boolean().optional(),
118
- ),
111
+ hasSubdoc: StringToBooleanSchema.optional(),
119
112
  saStatus: z.nativeEnum(SignatureStatus).optional(),
120
113
  offeringId: z.lazy(() => offeringIdSchema).optional(),
121
114
  search: z.string().max(50).optional(),
@@ -39,7 +39,7 @@ import {
39
39
  import {
40
40
  tradeLineItemIdSchema,
41
41
  TradeLineItemZod,
42
- } from './trade-line-item.type';
42
+ } from './trade-line-item.types';
43
43
  import { TradeAdjustmentZod } from './trade-adjustment.type';
44
44
  import { TransactionZod } from './transaction.types';
45
45
  import { accountIdSchema } from './account.types';
@@ -55,8 +55,71 @@ import {
55
55
  } from './secondary-trade.types';
56
56
  import { InvestorAccount } from '../../investor-accounts/entities/investor-account.entity';
57
57
  import { Trade } from '../../trades/entities/trade.entity';
58
+ import { fileIdSchema } from './file.types';
58
59
 
59
60
  extendZodWithOpenApi(z);
61
+
62
+ // Zod schemas for attach subdoc endpoints
63
+ export const PostAttachSubdocBody = z.object({
64
+ lineItemId: tradeLineItemIdSchema.openapi({
65
+ example: 'trade_line_item_01kctsycw3fq7sj6hedvy62cja',
66
+ }),
67
+ fileId: z
68
+ .lazy(() => fileIdSchema)
69
+ .openapi({ example: 'file_01je6ht4b8fbmttkzh2hs82xqp' }),
70
+ primarySignatureStatus: z
71
+ .nativeEnum(SignatureStatus)
72
+ .openapi({ example: 'SIGNED' }),
73
+ secondarySignatureStatus: z
74
+ .nativeEnum(SignatureStatus)
75
+ .optional()
76
+ .openapi({ example: 'SIGNED' }),
77
+ });
78
+ export type PostAttachSubdocBody = z.infer<typeof PostAttachSubdocBody>;
79
+
80
+ export const PutAttachSubdocBody = z.object({
81
+ lineItemId: tradeLineItemIdSchema
82
+ .optional()
83
+ .openapi({ example: 'trade_line_item_01kctsycw3fq7sj6hedvy62cja' }),
84
+ fileId: z
85
+ .lazy(() => fileIdSchema)
86
+ .optional()
87
+ .openapi({ example: 'file_01je6ht4b8fbmttkzh2hs82xqp' }),
88
+ primarySignatureStatus: z
89
+ .nativeEnum(SignatureStatus)
90
+ .optional()
91
+ .openapi({ example: 'SIGNED' }),
92
+ secondarySignatureStatus: z
93
+ .nativeEnum(SignatureStatus)
94
+ .optional()
95
+ .openapi({ example: 'SIGNED' }),
96
+ });
97
+ export type PutAttachSubdocBody = z.infer<typeof PutAttachSubdocBody>;
98
+
99
+ export const PatchSubdocSignatureBody = z.object({
100
+ lineItemId: tradeLineItemIdSchema.optional().openapi({
101
+ example: 'trade_line_item_01kctsycw3fq7sj6hedvy62cja',
102
+ description:
103
+ 'Optional. If not provided, updates the first line item with an attached subdoc. Required for trades with multiple line items.',
104
+ }),
105
+ primarySignatureStatus: z.nativeEnum(SignatureStatus).optional().openapi({
106
+ example: 'SIGNED',
107
+ description: 'Primary signer signature status',
108
+ }),
109
+ secondarySignatureStatus: z.nativeEnum(SignatureStatus).optional().openapi({
110
+ example: 'SIGNED',
111
+ description:
112
+ 'Secondary signer signature status. Only applicable for JOINT investor accounts.',
113
+ }),
114
+ });
115
+ export type PatchSubdocSignatureBody = z.infer<typeof PatchSubdocSignatureBody>;
116
+
117
+ export const AttachSubdocResponse = z.object({
118
+ success: z.boolean(),
119
+ message: z.string(),
120
+ });
121
+ export type AttachSubdocResponse = z.infer<typeof AttachSubdocResponse>;
122
+
60
123
  export const CheckResultsSchema = z.object({
61
124
  fundingStatus: z.boolean(),
62
125
  agreementStatus: z.boolean(),
@@ -1,10 +1,11 @@
1
+ import { z } from 'zod';
2
+ import { extendZodWithOpenApi } from '@anatine/zod-openapi';
1
3
  import { TypeID } from 'typeid-js';
2
4
  import {
3
5
  dateSchema,
4
6
  InvestorAccountType,
5
7
  numberPrecisionSchema,
6
8
  } from './common.types';
7
- import { z } from 'zod';
8
9
  import { IBaseEntity } from './entity.types';
9
10
  import { accountIdSchema } from './account.types';
10
11
  import {
@@ -18,7 +19,9 @@ import {
18
19
  investorAccountIdSchema,
19
20
  } from './investor-account.types';
20
21
  import { TransactionStatus, TransactionType } from './common.types';
22
+ import { userIdSchema } from './user.types';
21
23
  export { TransactionStatus, TransactionType };
24
+ extendZodWithOpenApi(z);
22
25
 
23
26
  export enum RefundPaymentMethod {
24
27
  CHECK = 'CHECK',
@@ -115,6 +118,14 @@ export type InvestorPostTransactionZod = z.infer<
115
118
  typeof InvestorPostTransactionZod
116
119
  >;
117
120
 
121
+ export const ClientPostTransactionZod = InvestorPostTransactionZod.extend({
122
+ userId: z
123
+ .lazy(() => userIdSchema)
124
+ .openapi({ example: 'user_01j5y5ghx5fg68d663j1fvy2x7' }),
125
+ });
126
+
127
+ export type ClientPostTransactionZod = z.infer<typeof ClientPostTransactionZod>;
128
+
118
129
  export const refundTransactionIdSchema = z.string().refine(
119
130
  (value) => {
120
131
  try {
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { extendZodWithOpenApi } from '@anatine/zod-openapi';
2
3
  import {
3
4
  AccountStatus,
4
5
  AccountWithoutUsersZod,
@@ -7,12 +8,11 @@ import {
7
8
  ManagedByType,
8
9
  OfferingType,
9
10
  PortalType,
11
+ StringToBooleanSchema,
10
12
  UserRole,
11
- UserStatus,
12
13
  UserType,
13
14
  } from './common.types';
14
15
  import { dateOrString, IBaseEntity } from './entity.types';
15
- import { extendZodWithOpenApi } from '@anatine/zod-openapi';
16
16
  import { PhoneZodSchema } from './phone.type';
17
17
  import { IInvestorAccount } from './investor-account.types';
18
18
  import { TradeZod } from './trade.types';
@@ -51,6 +51,11 @@ export const UserDeleteResponse = z.object({
51
51
  });
52
52
  export type UserDeleteResponse = z.infer<typeof UserDeleteResponse>;
53
53
 
54
+ export const UserRestoreResponse = z.object({
55
+ message: z.string(),
56
+ });
57
+ export type UserRestoreResponse = z.infer<typeof UserRestoreResponse>;
58
+
54
59
  export const GetMeResponse = IBaseEntity.extend({
55
60
  accountId: z.string().nullable(),
56
61
  accountName: z.string().nullable(),
@@ -59,7 +64,7 @@ export const GetMeResponse = IBaseEntity.extend({
59
64
  email: z.string().email(),
60
65
  provider: z.string(),
61
66
  active: z.boolean(),
62
- status: z.lazy(() => z.nativeEnum(UserStatus)),
67
+ locked: z.boolean(),
63
68
  lastLoginAt: dateOrString.nullable(),
64
69
  loginCount: z.number(),
65
70
  role: z.string(),
@@ -157,7 +162,7 @@ export const UserZod = IBaseEntity.extend({
157
162
  onboarding: z.string().nullable(),
158
163
  account: AccountWithoutUsersZod.optional(),
159
164
  active: z.boolean(),
160
- status: z.nativeEnum(UserStatus),
165
+ locked: z.boolean(),
161
166
  userLogin: IBaseEntity.extend({
162
167
  firstName: z.string(),
163
168
  lastName: z.string(),
@@ -179,27 +184,9 @@ export const UserFiltersZod = z.object({
179
184
  search: z.string().max(50).optional(),
180
185
  role: z.nativeEnum(UserRole).optional(),
181
186
  portal: z.string().optional(),
182
- status: z.nativeEnum(UserStatus).optional(),
183
- active: z
184
- .string()
185
- .optional()
186
- .refine((v) => !v || v === 'true' || v === 'false', {
187
- message: 'active must be a boolean string',
188
- })
189
- .transform((v) => {
190
- if (!v) return undefined;
191
- return v === 'true';
192
- }),
193
- twoFactorEnabled: z
194
- .string()
195
- .optional()
196
- .refine((v) => !v || v === 'true' || v === 'false', {
197
- message: 'twoFactorEnabled must be a boolean string',
198
- })
199
- .transform((v) => {
200
- if (!v) return undefined;
201
- return v === 'true';
202
- }),
187
+ locked: StringToBooleanSchema.optional(),
188
+ active: StringToBooleanSchema.optional(),
189
+ twoFactorEnabled: StringToBooleanSchema.optional(),
203
190
  });
204
191
 
205
192
  const usersInclude = z.enum(['account', 'role']);
@@ -274,7 +261,7 @@ export type IssuerUsersStatusUpdateResponse = z.infer<
274
261
  >;
275
262
 
276
263
  export const UpdateLockedStatus = z.object({
277
- status: z.nativeEnum(UserStatus),
264
+ locked: z.boolean(),
278
265
  });
279
266
 
280
267
  export type UpdateLockedStatus = z.infer<typeof UpdateLockedStatus>;
@@ -285,7 +272,7 @@ export const UsersSummaryFilterZod = z.object({
285
272
  portalType: z.nativeEnum(PortalType).optional(),
286
273
  search: z.string().trim().max(50).optional(),
287
274
  selectRole: z.nativeEnum(UserRole).optional(),
288
- status: z.nativeEnum(UserStatus).optional(),
275
+ locked: StringToBooleanSchema.optional(),
289
276
  });
290
277
  export type UsersSummaryFilterZod = z.infer<typeof UsersSummaryFilterZod>;
291
278
 
@@ -299,7 +286,7 @@ export const UsersSummaryZod = z.object({
299
286
  portalType: z.string(),
300
287
  loginCount: z.number().int(),
301
288
  lastLogin: z.date(),
302
- status: z.nativeEnum(UserStatus),
289
+ locked: z.boolean(),
303
290
  });
304
291
  export type UsersSummaryZod = z.infer<typeof UsersSummaryZod>;
305
292