@dalmore/api-contracts 0.0.0-dev.2dc8e92 → 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.
- package/common/types/account-setting.types.ts +31 -0
- package/common/types/activity.types.ts +1 -1
- package/common/types/api-key-logs.types.ts +1 -1
- package/common/types/asset.types.ts +14 -14
- package/common/types/bonus-tier.types.ts +33 -0
- package/common/types/cart.types.ts +4 -1
- package/common/types/common.types.ts +16 -6
- package/common/types/dashboard.types.ts +2 -9
- package/common/types/disbursements.types.ts +119 -3
- package/common/types/file.types.ts +20 -4
- package/common/types/i-will-do-it-later.types.ts +68 -0
- package/common/types/index.ts +2 -0
- package/common/types/individuals.types.ts +2 -15
- package/common/types/issuer-offering.types.ts +113 -30
- package/common/types/issuer-payment-method.types.ts +41 -0
- package/common/types/issuer.types.ts +9 -0
- package/common/types/notification.types.ts +239 -29
- package/common/types/offering.types.ts +106 -20
- package/common/types/site.types.ts +2 -9
- package/common/types/{trade-line-item.type.ts → trade-line-item.types.ts} +2 -9
- package/common/types/trade.types.ts +71 -1
- package/common/types/transaction.types.ts +12 -1
- package/common/types/user.types.ts +15 -28
- package/contracts/clients/cart/index.ts +80 -0
- package/contracts/clients/index.ts +10 -0
- package/contracts/clients/issuer-payment-methods/index.ts +39 -0
- package/contracts/clients/payment-methods/index.ts +85 -0
- package/contracts/clients/trade-line-items/index.ts +66 -0
- package/contracts/clients/trades/index.ts +65 -1
- package/contracts/clients/transactions/index.ts +37 -0
- package/contracts/compliance/bonus-tiers/index.ts +21 -2
- package/contracts/compliance/trade-line-items/index.ts +1 -1
- package/contracts/compliance/users/index.ts +21 -0
- package/contracts/investors/bonus-tiers/index.ts +18 -0
- package/contracts/investors/individuals/index.ts +22 -0
- package/contracts/investors/trade-line-items/index.ts +1 -1
- package/contracts/issuers/bonus-tiers/index.ts +18 -0
- package/contracts/issuers/disbursements/index.ts +36 -0
- package/package.json +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { extendZodWithOpenApi } from '@anatine/zod-openapi';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { TypeID } from 'typeid-js';
|
|
4
|
+
import { IBaseEntity } from './entity.types';
|
|
5
|
+
|
|
6
|
+
extendZodWithOpenApi(z);
|
|
7
|
+
|
|
8
|
+
export const accountSettingIdSchema = z.string().refine(
|
|
9
|
+
(value) => {
|
|
10
|
+
try {
|
|
11
|
+
const tid = TypeID.fromString(value);
|
|
12
|
+
return tid.getType() === 'account_setting';
|
|
13
|
+
} catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
message:
|
|
19
|
+
'Invalid account setting ID format. Must be a valid TypeID with "account_setting" prefix.',
|
|
20
|
+
},
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
export const IAccountSettingZod = IBaseEntity.extend({
|
|
24
|
+
id: accountSettingIdSchema.openapi({
|
|
25
|
+
example: 'account_setting_01j5y5ghx8fvc83dmx3pznq7hv',
|
|
26
|
+
}),
|
|
27
|
+
accountId: z.string().openapi({
|
|
28
|
+
example: 'account_01j5y5ghx8fvc83dmx3pznq7hv',
|
|
29
|
+
}),
|
|
30
|
+
});
|
|
31
|
+
export type IAccountSettingZod = z.infer<typeof IAccountSettingZod>;
|
|
@@ -199,7 +199,7 @@ export const ActivityZod = IBaseEntity.extend({
|
|
|
199
199
|
userId: z.string().nullable(),
|
|
200
200
|
activityTypeId: z.string(),
|
|
201
201
|
accountId: z.string().nullable(),
|
|
202
|
-
user: UserForActivityZod,
|
|
202
|
+
user: UserForActivityZod.nullable(),
|
|
203
203
|
activityType: ActivityTypeZod,
|
|
204
204
|
targetObject: z.string().nullable().optional(),
|
|
205
205
|
__entity: z.string().optional(),
|
|
@@ -12,7 +12,7 @@ export const ApiLogsFiltersZod = z.object({
|
|
|
12
12
|
endpoint: z.string().optional(),
|
|
13
13
|
apiKeyId: apiKeyIdSchema.optional(),
|
|
14
14
|
method: z.nativeEnum(HttpMethod).optional(),
|
|
15
|
-
status: z.nativeEnum(HttpStatus).optional(),
|
|
15
|
+
status: z.preprocess(Number, z.nativeEnum(HttpStatus)).optional(),
|
|
16
16
|
from: dateSchema.optional().openapi({ example: 'MM/DD/YYYY' }),
|
|
17
17
|
to: dateSchema.optional().openapi({ example: 'MM/DD/YYYY' }),
|
|
18
18
|
});
|
|
@@ -29,7 +29,7 @@ export const assetIdSchema = z.string().refine(
|
|
|
29
29
|
message: `Invalid asset ID format. Must be a valid TypeID with "asset" prefix. Example: asset_01j5y5ghx5fg68d663j1fvy2x7`,
|
|
30
30
|
},
|
|
31
31
|
);
|
|
32
|
-
export enum
|
|
32
|
+
export enum AssetTemplateType {
|
|
33
33
|
STANDARD = 'STANDARD',
|
|
34
34
|
TIERED = 'TIERED',
|
|
35
35
|
}
|
|
@@ -51,7 +51,7 @@ export const IAsset = IBaseEntity.extend({
|
|
|
51
51
|
.lazy(() => IOffering)
|
|
52
52
|
.optional()
|
|
53
53
|
.nullable(), // Use z.lazy here
|
|
54
|
-
template: z.nativeEnum(
|
|
54
|
+
template: z.nativeEnum(AssetTemplateType),
|
|
55
55
|
tiers: z.array(z.number().positive()).nullable(),
|
|
56
56
|
enableBonus: z.boolean(),
|
|
57
57
|
});
|
|
@@ -102,16 +102,16 @@ const PostAssetBase = z.object({
|
|
|
102
102
|
.optional()
|
|
103
103
|
.openapi({ example: DurationType.DAY }),
|
|
104
104
|
template: z
|
|
105
|
-
.nativeEnum(
|
|
106
|
-
.default(
|
|
107
|
-
.openapi({ example:
|
|
105
|
+
.nativeEnum(AssetTemplateType)
|
|
106
|
+
.default(AssetTemplateType.STANDARD)
|
|
107
|
+
.openapi({ example: AssetTemplateType.STANDARD }),
|
|
108
108
|
tiers: z.array(z.number().positive()).nullable().optional(),
|
|
109
109
|
enableBonus: z.boolean().default(false).openapi({ example: false }),
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
-
const postAssetRefinement = (data: any, ctx: any) => {
|
|
112
|
+
export const postAssetRefinement = (data: any, ctx: any) => {
|
|
113
113
|
// If type is bond, yield and duration must be provided (cannot be null or undefined)
|
|
114
|
-
if (data.type === AssetType.BOND) {
|
|
114
|
+
if (data.assetType === AssetType.BOND || data.type === AssetType.BOND) {
|
|
115
115
|
if (data.yield === null || data.yield === undefined) {
|
|
116
116
|
ctx.addIssue({
|
|
117
117
|
path: ['yield'],
|
|
@@ -139,7 +139,7 @@ const postAssetRefinement = (data: any, ctx: any) => {
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
// If type is stock, yield and duration must be either null or undefined
|
|
142
|
-
if (data.type === AssetType.STOCK) {
|
|
142
|
+
if (data.assetType === AssetType.STOCK || data.type === AssetType.STOCK) {
|
|
143
143
|
if (data.yield !== null && data.yield !== undefined) {
|
|
144
144
|
ctx.addIssue({
|
|
145
145
|
path: ['yield'],
|
|
@@ -162,7 +162,7 @@ const postAssetRefinement = (data: any, ctx: any) => {
|
|
|
162
162
|
});
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
-
if (data.template ===
|
|
165
|
+
if (data.template === AssetTemplateType.TIERED) {
|
|
166
166
|
if (data.tiers === null || data.tiers === undefined) {
|
|
167
167
|
ctx.addIssue({
|
|
168
168
|
path: ['tiers'],
|
|
@@ -172,7 +172,7 @@ const postAssetRefinement = (data: any, ctx: any) => {
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
// If template is STANDARD, tiers must be null or undefined
|
|
175
|
-
if (data.template ===
|
|
175
|
+
if (data.template === AssetTemplateType.STANDARD) {
|
|
176
176
|
if (data.tiers !== null && data.tiers !== undefined) {
|
|
177
177
|
ctx.addIssue({
|
|
178
178
|
path: ['tiers'],
|
|
@@ -233,9 +233,9 @@ export const PutAsset = z.object({
|
|
|
233
233
|
.optional()
|
|
234
234
|
.openapi({ example: DurationType.DAY }),
|
|
235
235
|
template: z
|
|
236
|
-
.nativeEnum(
|
|
237
|
-
.default(
|
|
238
|
-
.openapi({ example:
|
|
236
|
+
.nativeEnum(AssetTemplateType)
|
|
237
|
+
.default(AssetTemplateType.STANDARD)
|
|
238
|
+
.openapi({ example: AssetTemplateType.STANDARD })
|
|
239
239
|
.nullable()
|
|
240
240
|
.optional(),
|
|
241
241
|
tiers: z.array(z.number().positive()).nullable().optional(),
|
|
@@ -262,7 +262,7 @@ export const AssetsIncludeQuery = z.object({
|
|
|
262
262
|
assetsInclude.options.includes(include as any),
|
|
263
263
|
),
|
|
264
264
|
{
|
|
265
|
-
message: `Invalid include option provided. Valid options are: ${assetsInclude.options.join(',
|
|
265
|
+
message: `Invalid include option provided. Valid options are: ${assetsInclude.options.join(',')}`,
|
|
266
266
|
},
|
|
267
267
|
)
|
|
268
268
|
.openapi({
|
|
@@ -98,6 +98,15 @@ export type EstimateBonusTierCalculationZod = z.infer<
|
|
|
98
98
|
typeof EstimateBonusTierCalculationZod
|
|
99
99
|
>;
|
|
100
100
|
|
|
101
|
+
export const ComplianceEstimateBonusTierCalculationZod =
|
|
102
|
+
EstimateBonusTierCalculationZod.and(
|
|
103
|
+
z.object({
|
|
104
|
+
accountId: accountIdSchema,
|
|
105
|
+
}),
|
|
106
|
+
);
|
|
107
|
+
export type ComplianceEstimateBonusTierCalculationZod = z.infer<
|
|
108
|
+
typeof ComplianceEstimateBonusTierCalculationZod
|
|
109
|
+
>;
|
|
101
110
|
export const EstimateBonusTierCalculationResponseZod = z.object({
|
|
102
111
|
bonusTierId: bonusTierIdSchema
|
|
103
112
|
.nullable()
|
|
@@ -145,3 +154,27 @@ export const CompliancePostBonusTierZod = PostBonusTierZod.extend({
|
|
|
145
154
|
export type CompliancePostBonusTierZod = z.infer<
|
|
146
155
|
typeof CompliancePostBonusTierZod
|
|
147
156
|
>;
|
|
157
|
+
export const PurchaseCalculationZod = z.object({
|
|
158
|
+
assetId: assetIdSchema,
|
|
159
|
+
totalAmount: z.number().positive().openapi({ example: 1000 }),
|
|
160
|
+
purchasedShares: z.number().positive().int().openapi({ example: 100 }),
|
|
161
|
+
});
|
|
162
|
+
export type PurchaseCalculationZod = z.infer<typeof PurchaseCalculationZod>;
|
|
163
|
+
|
|
164
|
+
export const PurchaseCalculationResponseZod = z.object({
|
|
165
|
+
bonusTierId: bonusTierIdSchema
|
|
166
|
+
.nullable()
|
|
167
|
+
.openapi({ example: 'bonus_tier_01j5y5ghx5fg68d663j1fvy2x7' }),
|
|
168
|
+
assetId: assetIdSchema.openapi({
|
|
169
|
+
example: 'asset_00041061050r3gg28a1c60t3gf',
|
|
170
|
+
}),
|
|
171
|
+
type: z
|
|
172
|
+
.nativeEnum(BonusType)
|
|
173
|
+
.nullable()
|
|
174
|
+
.openapi({ example: BonusType.PERCENTAGE }),
|
|
175
|
+
bonusShares: z.number().int().openapi({ example: 100 }),
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
export type PurchaseCalculationResponseZod = z.infer<
|
|
179
|
+
typeof PurchaseCalculationResponseZod
|
|
180
|
+
>;
|
|
@@ -3,6 +3,7 @@ import { extendZodWithOpenApi } from '@anatine/zod-openapi';
|
|
|
3
3
|
import { TradeStatus } from './common.types';
|
|
4
4
|
import { investorAccountIdSchema } from './investor-account.types';
|
|
5
5
|
import { paymentMethodIdSchema } from './payment-methods.types';
|
|
6
|
+
import { userIdSchema } from './user.types';
|
|
6
7
|
|
|
7
8
|
extendZodWithOpenApi(z);
|
|
8
9
|
|
|
@@ -10,7 +11,9 @@ export const PlaceTradeResponse = z.object({
|
|
|
10
11
|
tradeStatus: z.nativeEnum(TradeStatus).optional(),
|
|
11
12
|
});
|
|
12
13
|
export const PlaceTradeBody = z.object({});
|
|
13
|
-
|
|
14
|
+
export const ClientPlacetradeBody = z.object({
|
|
15
|
+
userId: userIdSchema,
|
|
16
|
+
});
|
|
14
17
|
export const PatchCartBody = z.object({
|
|
15
18
|
investorAccountId: investorAccountIdSchema.optional(),
|
|
16
19
|
paymentMethodId: paymentMethodIdSchema.optional(),
|
|
@@ -111,6 +111,10 @@ export enum HttpMethod {
|
|
|
111
111
|
OPTIONS = 'OPTIONS',
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
export enum UserStatus {
|
|
115
|
+
ACTIVE = 'ACTIVE',
|
|
116
|
+
LOCKED = 'LOCKED',
|
|
117
|
+
}
|
|
114
118
|
export const SENSITIVE_PATTERNS = [
|
|
115
119
|
/password/i,
|
|
116
120
|
/credit.*card/i,
|
|
@@ -200,11 +204,6 @@ export enum UserType {
|
|
|
200
204
|
DEMO = 'DEMO',
|
|
201
205
|
}
|
|
202
206
|
|
|
203
|
-
export enum UserStatus {
|
|
204
|
-
ACTIVE = 'ACTIVE',
|
|
205
|
-
LOCKED = 'LOCKED',
|
|
206
|
-
}
|
|
207
|
-
|
|
208
207
|
export enum UserRole {
|
|
209
208
|
API_KEY = 'API_KEY',
|
|
210
209
|
IMPORT = 'IMPORT',
|
|
@@ -306,7 +305,7 @@ export const AuthUserReq = BaseAuthReq.extend({
|
|
|
306
305
|
lastName: z.string(),
|
|
307
306
|
email: z.string().email(),
|
|
308
307
|
provider: z.string(),
|
|
309
|
-
|
|
308
|
+
locked: z.boolean(),
|
|
310
309
|
lastLoginAt: z.date().nullable(),
|
|
311
310
|
loginCount: z.number(),
|
|
312
311
|
requiresTwoFactorSetup: z.boolean().optional(),
|
|
@@ -1518,3 +1517,14 @@ export const SUBJECT_TYPE_MAP: Record<BulkExportType, string> = {
|
|
|
1518
1517
|
[BulkExportType.SECONDARY_CUSTOMERS]: 'Secondary Customers',
|
|
1519
1518
|
[BulkExportType.SECONDARY_TRADES]: 'Secondary Trades',
|
|
1520
1519
|
};
|
|
1520
|
+
|
|
1521
|
+
export const StringToBooleanSchema = z.preprocess(
|
|
1522
|
+
(val) =>
|
|
1523
|
+
val === 'true' || val === '1'
|
|
1524
|
+
? true
|
|
1525
|
+
: val === 'false' || val === '0'
|
|
1526
|
+
? false
|
|
1527
|
+
: val,
|
|
1528
|
+
z.boolean(),
|
|
1529
|
+
);
|
|
1530
|
+
export type StringToBooleanSchema = z.infer<typeof StringToBooleanSchema>;
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
FileLabels,
|
|
8
8
|
IPaginationMeta,
|
|
9
9
|
OfferingType,
|
|
10
|
+
StringToBooleanSchema,
|
|
10
11
|
} from './common.types';
|
|
11
12
|
import { accountIdSchema } from './account.types';
|
|
12
13
|
|
|
@@ -330,15 +331,7 @@ export const GetInvestmentDashboardQueryZod = z.object({
|
|
|
330
331
|
offerings: OfferingsArrayQueryZod.optional(),
|
|
331
332
|
offeringTypes: OfferingTypesQueryZod.optional(),
|
|
332
333
|
timeFilteringType: z.nativeEnum(DashboardTimeFilteringType),
|
|
333
|
-
debug:
|
|
334
|
-
(val) =>
|
|
335
|
-
val === 'true' || val === '1'
|
|
336
|
-
? true
|
|
337
|
-
: val === 'false' || val === '0'
|
|
338
|
-
? false
|
|
339
|
-
: val,
|
|
340
|
-
z.boolean().optional(),
|
|
341
|
-
),
|
|
334
|
+
debug: StringToBooleanSchema.optional(),
|
|
342
335
|
});
|
|
343
336
|
export type GetInvestmentDashboardQueryZod = z.infer<
|
|
344
337
|
typeof GetInvestmentDashboardQueryZod
|
|
@@ -11,14 +11,17 @@ import {
|
|
|
11
11
|
import { tradeIdSchema } from './trade.types';
|
|
12
12
|
import { accountIdSchema } from './account.types';
|
|
13
13
|
import { TypeID } from 'typeid-js';
|
|
14
|
-
import { issuerIdSchema } from './issuer.types';
|
|
15
|
-
import {
|
|
14
|
+
import { IIssuer, issuerIdSchema } from './issuer.types';
|
|
15
|
+
import {
|
|
16
|
+
IIssuerBankAccount,
|
|
17
|
+
issuerBankAccountIdSchema,
|
|
18
|
+
} from './issuer-bank-account.types';
|
|
16
19
|
import { userIdSchema, UserZod } from './user.types';
|
|
17
20
|
import {
|
|
18
21
|
PostDisbursementAdjustmentZod,
|
|
19
22
|
DisbursementAdjustmentType,
|
|
20
23
|
} from './disbursement-adjustment.types';
|
|
21
|
-
import { escrowAccountIdSchema } from './escrow-account.types';
|
|
24
|
+
import { IEscrowAccount, escrowAccountIdSchema } from './escrow-account.types';
|
|
22
25
|
|
|
23
26
|
export const disbursementIdSchema = z.string().refine(
|
|
24
27
|
(value) => {
|
|
@@ -308,3 +311,116 @@ export const DisbursementSummaryZod = z.object({
|
|
|
308
311
|
amountToBeTransferred: z.number(),
|
|
309
312
|
});
|
|
310
313
|
export type DisbursementSummaryZod = z.infer<typeof DisbursementSummaryZod>;
|
|
314
|
+
|
|
315
|
+
// GET /disbursements/preview query parameters
|
|
316
|
+
export const GetDisbursementPreviewQueryZod = z.object({
|
|
317
|
+
offeringId: offeringIdSchema,
|
|
318
|
+
selectedTrades: z
|
|
319
|
+
.string()
|
|
320
|
+
.optional()
|
|
321
|
+
.transform((str) => (str ? str.split(',') : []))
|
|
322
|
+
.refine(
|
|
323
|
+
(ids) =>
|
|
324
|
+
ids.every((id) => {
|
|
325
|
+
try {
|
|
326
|
+
const tid = TypeID.fromString(id);
|
|
327
|
+
return tid.getType() === 'trade';
|
|
328
|
+
} catch {
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
}),
|
|
332
|
+
{
|
|
333
|
+
message: 'All selected trades must be valid trade IDs',
|
|
334
|
+
},
|
|
335
|
+
)
|
|
336
|
+
.openapi({
|
|
337
|
+
example: 'trade_01abc123,trade_01def456',
|
|
338
|
+
}),
|
|
339
|
+
});
|
|
340
|
+
export type GetDisbursementPreviewQueryZod = z.infer<
|
|
341
|
+
typeof GetDisbursementPreviewQueryZod
|
|
342
|
+
>;
|
|
343
|
+
|
|
344
|
+
// Context fields for disbursement preview
|
|
345
|
+
export const DisbursementPreviewContextZod = z.object({
|
|
346
|
+
issuer: z.lazy(() => IIssuer).nullable(),
|
|
347
|
+
offering: z.lazy(() => IOffering).nullable(),
|
|
348
|
+
escrowAccount: z.lazy(() => IEscrowAccount).nullable(),
|
|
349
|
+
destinationBank: z.lazy(() => IIssuerBankAccount).nullable(),
|
|
350
|
+
});
|
|
351
|
+
export type DisbursementPreviewContextZod = z.infer<
|
|
352
|
+
typeof DisbursementPreviewContextZod
|
|
353
|
+
>;
|
|
354
|
+
|
|
355
|
+
// Balance values for disbursement preview
|
|
356
|
+
export const DisbursementPreviewBalanceZod = z.object({
|
|
357
|
+
totalRaised: z.number(),
|
|
358
|
+
totalDisbursed: z.number(),
|
|
359
|
+
pending: z.number(),
|
|
360
|
+
refundPool: z.number(),
|
|
361
|
+
availableForDisbursement: z.number(),
|
|
362
|
+
});
|
|
363
|
+
export type DisbursementPreviewBalanceZod = z.infer<
|
|
364
|
+
typeof DisbursementPreviewBalanceZod
|
|
365
|
+
>;
|
|
366
|
+
|
|
367
|
+
// Trade summary for disbursement preview
|
|
368
|
+
export const DisbursementPreviewTradeSummaryZod = z.object({
|
|
369
|
+
selectedTradesCount: z.number(),
|
|
370
|
+
selectedTradesTotalAmount: z.number(),
|
|
371
|
+
});
|
|
372
|
+
export type DisbursementPreviewTradeSummaryZod = z.infer<
|
|
373
|
+
typeof DisbursementPreviewTradeSummaryZod
|
|
374
|
+
>;
|
|
375
|
+
|
|
376
|
+
// Contingency validation result
|
|
377
|
+
export const DisbursementPreviewContingencyZod = z.object({
|
|
378
|
+
contingencyPassed: z.boolean(),
|
|
379
|
+
contingencyMessage: z.string().nullable(),
|
|
380
|
+
contingencyAmount: z.number(),
|
|
381
|
+
});
|
|
382
|
+
export type DisbursementPreviewContingencyZod = z.infer<
|
|
383
|
+
typeof DisbursementPreviewContingencyZod
|
|
384
|
+
>;
|
|
385
|
+
|
|
386
|
+
// Amount defaults and constraints
|
|
387
|
+
export const DisbursementPreviewAmountZod = z.object({
|
|
388
|
+
defaultAmount: z.number(),
|
|
389
|
+
minAmount: z.number(),
|
|
390
|
+
maxAmount: z.number(),
|
|
391
|
+
});
|
|
392
|
+
export type DisbursementPreviewAmountZod = z.infer<
|
|
393
|
+
typeof DisbursementPreviewAmountZod
|
|
394
|
+
>;
|
|
395
|
+
|
|
396
|
+
// Complete response for GET /disbursements/preview
|
|
397
|
+
export const DisbursementPreviewZod = z.object({
|
|
398
|
+
context: DisbursementPreviewContextZod,
|
|
399
|
+
balance: DisbursementPreviewBalanceZod,
|
|
400
|
+
tradeSummary: DisbursementPreviewTradeSummaryZod,
|
|
401
|
+
contingency: DisbursementPreviewContingencyZod,
|
|
402
|
+
amount: DisbursementPreviewAmountZod,
|
|
403
|
+
});
|
|
404
|
+
export type DisbursementPreviewZod = z.infer<typeof DisbursementPreviewZod>;
|
|
405
|
+
|
|
406
|
+
export const EligibleOfferingZod = z.object({
|
|
407
|
+
offeringId: offeringIdSchema,
|
|
408
|
+
offeringName: z.string(),
|
|
409
|
+
availableAmount: z.number(),
|
|
410
|
+
});
|
|
411
|
+
export type EligibleOfferingZod = z.infer<typeof EligibleOfferingZod>;
|
|
412
|
+
|
|
413
|
+
export const IPaginatedEligibleOffering = z.object({
|
|
414
|
+
items: z.array(EligibleOfferingZod),
|
|
415
|
+
meta: IPaginationMeta,
|
|
416
|
+
});
|
|
417
|
+
export type IPaginatedEligibleOffering = z.infer<
|
|
418
|
+
typeof IPaginatedEligibleOffering
|
|
419
|
+
>;
|
|
420
|
+
|
|
421
|
+
export const EligibleOfferingsFiltersZod = z.object({
|
|
422
|
+
search: z.string().optional(),
|
|
423
|
+
});
|
|
424
|
+
export type EligibleOfferingsFiltersZod = z.infer<
|
|
425
|
+
typeof EligibleOfferingsFiltersZod
|
|
426
|
+
>;
|
|
@@ -17,7 +17,7 @@ import { KybZod } from './kyb.types';
|
|
|
17
17
|
import { IIndividualZod, individualIdSchema } from './individuals.types';
|
|
18
18
|
import { LegalEntityZod } from './legal-entity.types';
|
|
19
19
|
import { IInvestorAccount } from './investor-account.types';
|
|
20
|
-
import { TradeZod } from './trade.types';
|
|
20
|
+
import { tradeIdSchema, TradeZod } from './trade.types';
|
|
21
21
|
|
|
22
22
|
extendZodWithOpenApi(z);
|
|
23
23
|
|
|
@@ -168,13 +168,13 @@ export type PostFileQueryParams = z.infer<typeof PostFileQueryParams>;
|
|
|
168
168
|
|
|
169
169
|
/**
|
|
170
170
|
* CLIENT portal specific schema for file uploads
|
|
171
|
-
* Only allows INDIVIDUALS as target for file uploads
|
|
171
|
+
* Only allows INDIVIDUALS and TRADES as target for file uploads
|
|
172
172
|
*/
|
|
173
173
|
export const ClientPostFileQueryParams = z.object({
|
|
174
174
|
name: z.string().min(1).max(100).openapi({ example: 'file_name' }),
|
|
175
175
|
category: z.string().max(50).openapi({ example: 'application' }),
|
|
176
176
|
label: FileLabelsEnum.openapi({ example: FileLabels.OTHER }),
|
|
177
|
-
targetId: individualIdSchema.openapi({
|
|
177
|
+
targetId: z.union([individualIdSchema, tradeIdSchema]).openapi({
|
|
178
178
|
example: 'individual_01kcrsny60fb9rjc8bbqc3b80c',
|
|
179
179
|
}),
|
|
180
180
|
metadata: metadataSchema.nullable().optional(),
|
|
@@ -314,8 +314,23 @@ export const reviewFiles = z.object({
|
|
|
314
314
|
});
|
|
315
315
|
export type reviewFiles = z.infer<typeof reviewFiles>;
|
|
316
316
|
|
|
317
|
+
/**
|
|
318
|
+
* Zod preprocessor that trims strings and converts empty/whitespace-only strings to null
|
|
319
|
+
*/
|
|
320
|
+
const trimAndNullifyString = z.preprocess((val) => {
|
|
321
|
+
if (typeof val === 'string') {
|
|
322
|
+
const trimmed = val.trim();
|
|
323
|
+
return trimmed === '' ? null : trimmed;
|
|
324
|
+
}
|
|
325
|
+
return val;
|
|
326
|
+
}, z.unknown());
|
|
327
|
+
|
|
317
328
|
export const PatchFileMetadata = z.object({
|
|
318
|
-
corrected: z.record(z.string(),
|
|
329
|
+
corrected: z.record(z.string(), trimAndNullifyString),
|
|
330
|
+
expectedCorrected: z
|
|
331
|
+
.record(z.string(), trimAndNullifyString)
|
|
332
|
+
.nullable()
|
|
333
|
+
.optional(),
|
|
319
334
|
});
|
|
320
335
|
export type PatchFileMetadata = z.infer<typeof PatchFileMetadata>;
|
|
321
336
|
|
|
@@ -343,6 +358,7 @@ export const FileMetadataSchema = z.object({
|
|
|
343
358
|
},
|
|
344
359
|
),
|
|
345
360
|
corrected: z.record(z.any()).optional(),
|
|
361
|
+
expectedCorrected: z.record(z.any()).optional(),
|
|
346
362
|
});
|
|
347
363
|
export type FileMetadata = z.infer<typeof FileMetadataSchema>;
|
|
348
364
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PortalType, TargetTableEnum } from './common.types';
|
|
3
|
+
import { TaskPriority, TaskType } from './task.types';
|
|
4
|
+
|
|
5
|
+
export enum IWillDoItLaterType {
|
|
6
|
+
KYC = 'KYC',
|
|
7
|
+
// Future types can be added here:
|
|
8
|
+
// AIC = 'AIC',
|
|
9
|
+
// AML = 'AML',
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const IWillDoItLaterBodySchema = z.object({
|
|
13
|
+
type: z.nativeEnum(IWillDoItLaterType).default(IWillDoItLaterType.KYC),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export type IWillDoItLaterBodyType = z.infer<typeof IWillDoItLaterBodySchema>;
|
|
17
|
+
|
|
18
|
+
export const IWillDoItLaterResponseSchema = z.object({
|
|
19
|
+
message: z.string(),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export type IWillDoItLaterResponseType = z.infer<
|
|
23
|
+
typeof IWillDoItLaterResponseSchema
|
|
24
|
+
>;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @description Context required for processing "I'll do it later" actions.
|
|
28
|
+
*/
|
|
29
|
+
export interface IWillDoItLaterContext {
|
|
30
|
+
/** The ID of the target entity */
|
|
31
|
+
targetId: string;
|
|
32
|
+
/** The table name of the target entity */
|
|
33
|
+
targetTable: (typeof TargetTableEnum)[number];
|
|
34
|
+
/** The account ID associated with the action */
|
|
35
|
+
accountId: string;
|
|
36
|
+
/** The user ID who will be assigned the task */
|
|
37
|
+
assigneeId: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @description Configuration for each "I'll do it later" action type.
|
|
42
|
+
* Maps action types to their corresponding task configuration.
|
|
43
|
+
*/
|
|
44
|
+
export interface IWillDoItLaterTaskConfig {
|
|
45
|
+
taskType: TaskType;
|
|
46
|
+
portalType: PortalType;
|
|
47
|
+
title: string;
|
|
48
|
+
description: string;
|
|
49
|
+
priority: TaskPriority;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @description Mapping of "I'll do it later" types to their task configurations.
|
|
54
|
+
* This allows for easy extension of new action types without modifying the service logic.
|
|
55
|
+
*/
|
|
56
|
+
export const IWillDoItLaterTaskConfigMap: Record<
|
|
57
|
+
IWillDoItLaterType,
|
|
58
|
+
IWillDoItLaterTaskConfig
|
|
59
|
+
> = {
|
|
60
|
+
[IWillDoItLaterType.KYC]: {
|
|
61
|
+
taskType: TaskType.COMPLETE_KYC,
|
|
62
|
+
portalType: PortalType.INVESTOR,
|
|
63
|
+
title: 'Complete KYC',
|
|
64
|
+
description:
|
|
65
|
+
'We are unable to verify your KYC information. Please complete your KYC.',
|
|
66
|
+
priority: TaskPriority.HIGH,
|
|
67
|
+
},
|
|
68
|
+
};
|
package/common/types/index.ts
CHANGED
|
@@ -42,6 +42,8 @@ export * from './domain-filter.types';
|
|
|
42
42
|
export * from './aic.types';
|
|
43
43
|
export * from './default-theme-config.types';
|
|
44
44
|
export * from './offering-reports.types';
|
|
45
|
+
export * from './i-will-do-it-later.types';
|
|
46
|
+
export * from './payment-methods.types';
|
|
45
47
|
|
|
46
48
|
export enum Versions {
|
|
47
49
|
V1 = 'v1',
|
|
@@ -12,9 +12,7 @@ import {
|
|
|
12
12
|
InvestorAccountType,
|
|
13
13
|
SetupStatusType,
|
|
14
14
|
SetupStepType,
|
|
15
|
-
ComplianceReview,
|
|
16
15
|
RetirementAccountType,
|
|
17
|
-
TradeStatus,
|
|
18
16
|
EmploymentStatus,
|
|
19
17
|
SourceOfIncome,
|
|
20
18
|
AMLProvider,
|
|
@@ -60,8 +58,8 @@ export enum aicQuestionnaireQuestionType {
|
|
|
60
58
|
}
|
|
61
59
|
|
|
62
60
|
export enum FilterBy {
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
ALL = 'ALL',
|
|
62
|
+
PENDING_TRADES = 'PENDING_TRADES',
|
|
65
63
|
}
|
|
66
64
|
|
|
67
65
|
export const aicQuestionnaireQuestion = z.object({
|
|
@@ -243,17 +241,6 @@ export const IndividualFiltersZod = z.object({
|
|
|
243
241
|
|
|
244
242
|
export const ComplianceIndividualFiltersZod = IndividualFiltersZod.extend({
|
|
245
243
|
filterBy: z.nativeEnum(FilterBy).optional(),
|
|
246
|
-
tradeStatus: z.nativeEnum(TradeStatus).optional(),
|
|
247
|
-
complianceReview: z.nativeEnum(ComplianceReview).optional(),
|
|
248
|
-
hasPendingTrades: z.preprocess(
|
|
249
|
-
(val) =>
|
|
250
|
-
val === 'true' || val === '1'
|
|
251
|
-
? true
|
|
252
|
-
: val === 'false' || val === '0'
|
|
253
|
-
? false
|
|
254
|
-
: val,
|
|
255
|
-
z.boolean().optional(),
|
|
256
|
-
),
|
|
257
244
|
});
|
|
258
245
|
|
|
259
246
|
/**
|