@cranberry-money/shared-services 1.1.0 → 1.3.0
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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/services/portfolios/allocations/index.d.ts +7 -0
- package/dist/services/portfolios/allocations/index.d.ts.map +1 -0
- package/dist/services/portfolios/allocations/index.js +6 -0
- package/dist/services/portfolios/allocations/service.d.ts +6 -0
- package/dist/services/portfolios/allocations/service.d.ts.map +1 -0
- package/dist/services/portfolios/allocations/service.js +19 -0
- package/dist/services/portfolios/allocations/types.d.ts +17 -0
- package/dist/services/portfolios/allocations/types.d.ts.map +1 -0
- package/dist/services/portfolios/allocations/types.js +4 -0
- package/dist/services/portfolios/allocations/utils.d.ts +3 -0
- package/dist/services/portfolios/allocations/utils.d.ts.map +1 -0
- package/dist/services/portfolios/allocations/utils.js +7 -0
- package/dist/services/portfolios/holdings/index.d.ts +7 -0
- package/dist/services/portfolios/holdings/index.d.ts.map +1 -0
- package/dist/services/portfolios/holdings/index.js +6 -0
- package/dist/services/portfolios/holdings/service.d.ts +10 -0
- package/dist/services/portfolios/holdings/service.d.ts.map +1 -0
- package/dist/services/portfolios/holdings/service.js +53 -0
- package/dist/services/portfolios/holdings/types.d.ts +42 -0
- package/dist/services/portfolios/holdings/types.d.ts.map +1 -0
- package/dist/services/portfolios/holdings/types.js +4 -0
- package/dist/services/portfolios/holdings/utils.d.ts +8 -0
- package/dist/services/portfolios/holdings/utils.d.ts.map +1 -0
- package/dist/services/portfolios/holdings/utils.js +82 -0
- package/dist/services/portfolios/index.d.ts +10 -0
- package/dist/services/portfolios/index.d.ts.map +1 -0
- package/dist/services/portfolios/index.js +10 -0
- package/dist/services/portfolios/service.d.ts +7 -0
- package/dist/services/portfolios/service.d.ts.map +1 -0
- package/dist/services/portfolios/service.js +19 -0
- package/dist/services/portfolios/types.d.ts +29 -0
- package/dist/services/portfolios/types.d.ts.map +1 -0
- package/dist/services/portfolios/types.js +1 -0
- package/dist/services/portfolios/utils.d.ts +5 -0
- package/dist/services/portfolios/utils.d.ts.map +1 -0
- package/dist/services/portfolios/utils.js +26 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export * from './services/AuthService';
|
|
|
14
14
|
export * from './services/PortfolioService';
|
|
15
15
|
export * as AccountsService from './services/accounts';
|
|
16
16
|
export * as AuthService from './services/auth';
|
|
17
|
+
export * as PortfoliosService from './services/portfolios';
|
|
17
18
|
export * from './query/QueryClient';
|
|
18
19
|
export * from './query/useAuth';
|
|
19
20
|
export * from './query/usePortfolios';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAG3C,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACb,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAGrB,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAG5C,OAAO,KAAK,eAAe,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,WAAW,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAG3C,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACb,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAGrB,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAG5C,OAAO,KAAK,eAAe,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,WAAW,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,iBAAiB,MAAM,uBAAuB,CAAC;AAG3D,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ export * from './services/PortfolioService';
|
|
|
18
18
|
// New functional domain services
|
|
19
19
|
export * as AccountsService from './services/accounts';
|
|
20
20
|
export * as AuthService from './services/auth';
|
|
21
|
+
export * as PortfoliosService from './services/portfolios';
|
|
21
22
|
// React Query integration
|
|
22
23
|
export * from './query/QueryClient';
|
|
23
24
|
export * from './query/useAuth';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/allocations/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AssetAllocation, AssetAllocationPayload } from './types';
|
|
2
|
+
export declare const getPortfolioAllocations: (portfolioUuid: string) => Promise<import("axios").AxiosResponse<AssetAllocation[], any>>;
|
|
3
|
+
export declare const createAssetAllocation: (data: AssetAllocationPayload) => Promise<import("axios").AxiosResponse<AssetAllocation, any>>;
|
|
4
|
+
export declare const updateAssetAllocation: (uuid: string, data: Partial<AssetAllocationPayload>) => Promise<import("axios").AxiosResponse<AssetAllocation, any>>;
|
|
5
|
+
export declare const deleteAssetAllocation: (uuid: string) => Promise<import("axios").AxiosResponse<void, any>>;
|
|
6
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/allocations/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAKvE,eAAO,MAAM,uBAAuB,GAAI,eAAe,MAAM,mEAK5D,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,MAAM,sBAAsB,iEAEjE,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,EAAE,MAAM,OAAO,CAAC,sBAAsB,CAAC,iEAExF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,sDAEjD,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { webApiClient } from '../../../api/apiClient';
|
|
2
|
+
import { API_ENDPOINTS } from '../constants';
|
|
3
|
+
// ASSET ALLOCATIONS API FUNCTIONS
|
|
4
|
+
// Fetch allocations for a specific portfolio
|
|
5
|
+
export const getPortfolioAllocations = (portfolioUuid) => {
|
|
6
|
+
// Always sort by created_at to show allocations in their creation order
|
|
7
|
+
return webApiClient.get(`${API_ENDPOINTS.PORTFOLIOS}${portfolioUuid}/allocations/`, {
|
|
8
|
+
params: { order_by: 'created_at' },
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
export const createAssetAllocation = (data) => {
|
|
12
|
+
return webApiClient.post(API_ENDPOINTS.ASSET_ALLOCATIONS, data);
|
|
13
|
+
};
|
|
14
|
+
export const updateAssetAllocation = (uuid, data) => {
|
|
15
|
+
return webApiClient.patch(`${API_ENDPOINTS.ASSET_ALLOCATIONS}${uuid}/`, data);
|
|
16
|
+
};
|
|
17
|
+
export const deleteAssetAllocation = (uuid) => {
|
|
18
|
+
return webApiClient.delete(`${API_ENDPOINTS.ASSET_ALLOCATIONS}${uuid}/`);
|
|
19
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asset Allocations types and interfaces
|
|
3
|
+
*/
|
|
4
|
+
export interface AssetAllocation {
|
|
5
|
+
uuid: string;
|
|
6
|
+
portfolio: string;
|
|
7
|
+
instrument: string;
|
|
8
|
+
instrumentName: string;
|
|
9
|
+
instrumentSymbol: string;
|
|
10
|
+
percentage: string;
|
|
11
|
+
}
|
|
12
|
+
export interface AssetAllocationPayload {
|
|
13
|
+
portfolio: string;
|
|
14
|
+
instrument: string;
|
|
15
|
+
percentage: string | number;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/allocations/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB;AAGD,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC;CAC7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/allocations/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK/C,eAAO,MAAM,mBAAmB,GAAI,aAAa,eAAe,EAAE,KAAG,OAKpE,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// ASSET ALLOCATIONS UTILITY FUNCTIONS
|
|
2
|
+
// Utility function to validate if allocation percentages sum to 100%
|
|
3
|
+
export const validateAllocations = (allocations) => {
|
|
4
|
+
const totalPercentage = allocations.reduce((sum, allocation) => sum + parseFloat(allocation.percentage), 0);
|
|
5
|
+
// Allow for small floating point errors (e.g., 99.99 or 100.01)
|
|
6
|
+
return Math.abs(totalPercentage - 100) < 0.01;
|
|
7
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/holdings/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PaginatedResponse } from '../../../api/types';
|
|
2
|
+
import type { AssetHolding, AssetHoldingSnapshot, AssetHoldingFilters, AssetHoldingSnapshotFilters } from './types';
|
|
3
|
+
export type PaginatedAssetHoldings = PaginatedResponse<AssetHolding>;
|
|
4
|
+
export type PaginatedAssetHoldingSnapshots = PaginatedResponse<AssetHoldingSnapshot>;
|
|
5
|
+
export declare const getAssetHoldings: (filters?: AssetHoldingFilters) => Promise<import("axios").AxiosResponse<PaginatedAssetHoldings, any>>;
|
|
6
|
+
export declare const getPortfolioHoldings: (portfolioUuid: string, orderBy?: string) => Promise<import("axios").AxiosResponse<AssetHolding[], any>>;
|
|
7
|
+
export declare const getAssetHoldingByUuid: (uuid: string) => Promise<import("axios").AxiosResponse<AssetHolding, any>>;
|
|
8
|
+
export declare const getAssetHoldingSnapshots: (filters?: AssetHoldingSnapshotFilters) => Promise<import("axios").AxiosResponse<PaginatedAssetHoldingSnapshots, any>>;
|
|
9
|
+
export declare const getAssetHoldingSnapshotById: (id: number) => Promise<import("axios").AxiosResponse<AssetHoldingSnapshot, any>>;
|
|
10
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/holdings/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE5D,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,SAAS,CAAC;AAGpH,MAAM,MAAM,sBAAsB,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;AACrE,MAAM,MAAM,8BAA8B,GAAG,iBAAiB,CAAC,oBAAoB,CAAC,CAAC;AAKrF,eAAO,MAAM,gBAAgB,GAAI,UAAU,mBAAmB,wEAW7D,CAAC;AAGF,eAAO,MAAM,oBAAoB,GAAI,eAAe,MAAM,EAAE,UAAU,MAAM,gEAK3E,CAAC;AAGF,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,8DAEjD,CAAC;AAKF,eAAO,MAAM,wBAAwB,GAAI,UAAU,2BAA2B,gFAW7E,CAAC;AAGF,eAAO,MAAM,2BAA2B,GAAI,IAAI,MAAM,sEAErD,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { webApiClient } from '../../../api/apiClient';
|
|
2
|
+
import { API_ENDPOINTS } from '../constants';
|
|
3
|
+
// ASSET HOLDINGS API FUNCTIONS
|
|
4
|
+
// Fetch asset holdings with optional filtering
|
|
5
|
+
export const getAssetHoldings = (filters) => {
|
|
6
|
+
const params = {};
|
|
7
|
+
if (filters?.portfolioId)
|
|
8
|
+
params.portfolio_id = filters.portfolioId;
|
|
9
|
+
if (filters?.portfolioUuid)
|
|
10
|
+
params.portfolio_uuid = filters.portfolioUuid;
|
|
11
|
+
if (filters?.instrument)
|
|
12
|
+
params.instrument = filters.instrument;
|
|
13
|
+
if (filters?.minQuantity)
|
|
14
|
+
params.min_quantity = filters.minQuantity.toString();
|
|
15
|
+
if (filters?.maxQuantity)
|
|
16
|
+
params.max_quantity = filters.maxQuantity.toString();
|
|
17
|
+
if (filters?.orderBy)
|
|
18
|
+
params.order_by = filters.orderBy;
|
|
19
|
+
return webApiClient.get(API_ENDPOINTS.ASSET_HOLDINGS, { params });
|
|
20
|
+
};
|
|
21
|
+
// Fetch holdings for a specific portfolio
|
|
22
|
+
export const getPortfolioHoldings = (portfolioUuid, orderBy) => {
|
|
23
|
+
const params = {};
|
|
24
|
+
if (orderBy)
|
|
25
|
+
params.order_by = orderBy;
|
|
26
|
+
return webApiClient.get(`${API_ENDPOINTS.PORTFOLIOS}${portfolioUuid}/holdings/`, { params });
|
|
27
|
+
};
|
|
28
|
+
// Get asset holding by UUID
|
|
29
|
+
export const getAssetHoldingByUuid = (uuid) => {
|
|
30
|
+
return webApiClient.get(`${API_ENDPOINTS.ASSET_HOLDINGS}${uuid}/`);
|
|
31
|
+
};
|
|
32
|
+
// ASSET HOLDING SNAPSHOTS API FUNCTIONS
|
|
33
|
+
// Fetch asset holding snapshots with optional filtering
|
|
34
|
+
export const getAssetHoldingSnapshots = (filters) => {
|
|
35
|
+
const params = {};
|
|
36
|
+
if (filters?.assetHoldingId)
|
|
37
|
+
params.asset_holding_id = filters.assetHoldingId;
|
|
38
|
+
if (filters?.portfolioId)
|
|
39
|
+
params.portfolio_id = filters.portfolioId;
|
|
40
|
+
if (filters?.reason)
|
|
41
|
+
params.reason = filters.reason;
|
|
42
|
+
if (filters?.startDate)
|
|
43
|
+
params.start_date = filters.startDate;
|
|
44
|
+
if (filters?.endDate)
|
|
45
|
+
params.end_date = filters.endDate;
|
|
46
|
+
if (filters?.orderBy)
|
|
47
|
+
params.order_by = filters.orderBy;
|
|
48
|
+
return webApiClient.get(API_ENDPOINTS.ASSET_HOLDING_SNAPSHOTS, { params });
|
|
49
|
+
};
|
|
50
|
+
// Get asset holding snapshot by ID
|
|
51
|
+
export const getAssetHoldingSnapshotById = (id) => {
|
|
52
|
+
return webApiClient.get(`${API_ENDPOINTS.ASSET_HOLDING_SNAPSHOTS}${id}/`);
|
|
53
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asset Holdings types and interfaces
|
|
3
|
+
*/
|
|
4
|
+
export interface AssetHolding {
|
|
5
|
+
uuid: string;
|
|
6
|
+
portfolio: string;
|
|
7
|
+
instrument: any;
|
|
8
|
+
instrumentName: string;
|
|
9
|
+
instrumentSymbol: string;
|
|
10
|
+
quantity: number;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
updatedAt: string;
|
|
13
|
+
}
|
|
14
|
+
export interface AssetHoldingSnapshot {
|
|
15
|
+
id: number;
|
|
16
|
+
assetHolding: string;
|
|
17
|
+
portfolioId: number;
|
|
18
|
+
instrumentName: string;
|
|
19
|
+
instrumentSymbol: string;
|
|
20
|
+
quantity: number;
|
|
21
|
+
snapshotReason: 'TRADE' | 'REBALANCE' | 'VALUATION' | 'AUDIT';
|
|
22
|
+
snapshotDate: string;
|
|
23
|
+
createdAt: string;
|
|
24
|
+
updatedAt: string;
|
|
25
|
+
}
|
|
26
|
+
export interface AssetHoldingFilters {
|
|
27
|
+
portfolioId?: string;
|
|
28
|
+
portfolioUuid?: string;
|
|
29
|
+
instrument?: string;
|
|
30
|
+
minQuantity?: number;
|
|
31
|
+
maxQuantity?: number;
|
|
32
|
+
orderBy?: string;
|
|
33
|
+
}
|
|
34
|
+
export interface AssetHoldingSnapshotFilters {
|
|
35
|
+
assetHoldingId?: string;
|
|
36
|
+
portfolioId?: string;
|
|
37
|
+
reason?: 'TRADE' | 'REBALANCE' | 'VALUATION' | 'AUDIT';
|
|
38
|
+
startDate?: string;
|
|
39
|
+
endDate?: string;
|
|
40
|
+
orderBy?: string;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/holdings/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,GAAG,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,OAAO,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC;IAC9D,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,mBAAmB;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAGD,MAAM,WAAW,2BAA2B;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,WAAW,GAAG,OAAO,CAAC;IACvD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AssetHolding } from './types';
|
|
2
|
+
export declare const calculatePortfolioValue: (holdings: AssetHolding[], prices: Record<string, number>) => number;
|
|
3
|
+
export declare const calculateHoldingAllocations: (holdings: AssetHolding[]) => Record<string, number>;
|
|
4
|
+
export declare const groupHoldingsByInstrument: (holdings: AssetHolding[]) => Record<string, AssetHolding[]>;
|
|
5
|
+
export declare const filterHoldingsByMinQuantity: (holdings: AssetHolding[], minQuantity: number) => AssetHolding[];
|
|
6
|
+
export declare const sortHoldings: (holdings: AssetHolding[], sortBy: "quantity" | "symbol" | "name" | "createdAt", direction?: "asc" | "desc") => AssetHolding[];
|
|
7
|
+
export declare const formatQuantity: (quantity: number) => string;
|
|
8
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/services/portfolios/holdings/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK5C,eAAO,MAAM,uBAAuB,GAAI,UAAU,YAAY,EAAE,EAAE,QAAQ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAG,MAKlG,CAAC;AAGF,eAAO,MAAM,2BAA2B,GAAI,UAAU,YAAY,EAAE,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAW3F,CAAC;AAGF,eAAO,MAAM,yBAAyB,GAAI,UAAU,YAAY,EAAE,KAAG,MAAM,CAAC,MAAM,EAAE,YAAY,EAAE,CAYjG,CAAC;AAGF,eAAO,MAAM,2BAA2B,GAAI,UAAU,YAAY,EAAE,EAAE,aAAa,MAAM,KAAG,YAAY,EAEvG,CAAC;AAGF,eAAO,MAAM,YAAY,GACvB,UAAU,YAAY,EAAE,EACxB,QAAQ,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,WAAW,EACpD,YAAW,KAAK,GAAG,MAAe,KACjC,YAAY,EAsCd,CAAC;AAGF,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,KAAG,MAQjD,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// ASSET HOLDINGS UTILITY FUNCTIONS
|
|
2
|
+
// Calculate total portfolio value based on holdings and prices
|
|
3
|
+
export const calculatePortfolioValue = (holdings, prices) => {
|
|
4
|
+
return holdings.reduce((total, holding) => {
|
|
5
|
+
const price = prices[holding.instrument.uuid] || 0;
|
|
6
|
+
return total + holding.quantity * price;
|
|
7
|
+
}, 0);
|
|
8
|
+
};
|
|
9
|
+
// Calculate holding allocation percentages within a portfolio
|
|
10
|
+
export const calculateHoldingAllocations = (holdings) => {
|
|
11
|
+
const totalQuantity = holdings.reduce((sum, holding) => sum + holding.quantity, 0);
|
|
12
|
+
if (totalQuantity === 0)
|
|
13
|
+
return {};
|
|
14
|
+
const allocations = {};
|
|
15
|
+
holdings.forEach((holding) => {
|
|
16
|
+
allocations[holding.instrument.uuid] = (holding.quantity / totalQuantity) * 100;
|
|
17
|
+
});
|
|
18
|
+
return allocations;
|
|
19
|
+
};
|
|
20
|
+
// Group holdings by instrument for aggregated view
|
|
21
|
+
export const groupHoldingsByInstrument = (holdings) => {
|
|
22
|
+
return holdings.reduce((groups, holding) => {
|
|
23
|
+
const instrumentUuid = holding.instrument.uuid;
|
|
24
|
+
if (!groups[instrumentUuid]) {
|
|
25
|
+
groups[instrumentUuid] = [];
|
|
26
|
+
}
|
|
27
|
+
groups[instrumentUuid].push(holding);
|
|
28
|
+
return groups;
|
|
29
|
+
}, {});
|
|
30
|
+
};
|
|
31
|
+
// Filter holdings with quantities above a threshold
|
|
32
|
+
export const filterHoldingsByMinQuantity = (holdings, minQuantity) => {
|
|
33
|
+
return holdings.filter((holding) => holding.quantity >= minQuantity);
|
|
34
|
+
};
|
|
35
|
+
// Sort holdings by various criteria
|
|
36
|
+
export const sortHoldings = (holdings, sortBy, direction = 'desc') => {
|
|
37
|
+
return [...holdings].sort((a, b) => {
|
|
38
|
+
let valueA;
|
|
39
|
+
let valueB;
|
|
40
|
+
switch (sortBy) {
|
|
41
|
+
case 'quantity':
|
|
42
|
+
valueA = a.quantity;
|
|
43
|
+
valueB = b.quantity;
|
|
44
|
+
break;
|
|
45
|
+
case 'symbol':
|
|
46
|
+
valueA = a.instrumentSymbol;
|
|
47
|
+
valueB = b.instrumentSymbol;
|
|
48
|
+
break;
|
|
49
|
+
case 'name':
|
|
50
|
+
valueA = a.instrumentName;
|
|
51
|
+
valueB = b.instrumentName;
|
|
52
|
+
break;
|
|
53
|
+
case 'createdAt':
|
|
54
|
+
valueA = a.createdAt;
|
|
55
|
+
valueB = b.createdAt;
|
|
56
|
+
break;
|
|
57
|
+
default:
|
|
58
|
+
return 0;
|
|
59
|
+
}
|
|
60
|
+
if (typeof valueA === 'string' && typeof valueB === 'string') {
|
|
61
|
+
const comparison = valueA.localeCompare(valueB);
|
|
62
|
+
return direction === 'asc' ? comparison : -comparison;
|
|
63
|
+
}
|
|
64
|
+
if (typeof valueA === 'number' && typeof valueB === 'number') {
|
|
65
|
+
const comparison = valueA - valueB;
|
|
66
|
+
return direction === 'asc' ? comparison : -comparison;
|
|
67
|
+
}
|
|
68
|
+
return 0;
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
// Format quantity for display with proper units
|
|
72
|
+
export const formatQuantity = (quantity) => {
|
|
73
|
+
if (quantity >= 1000000) {
|
|
74
|
+
return `${(quantity / 1000000).toFixed(1)}M`;
|
|
75
|
+
}
|
|
76
|
+
else if (quantity >= 1000) {
|
|
77
|
+
return `${(quantity / 1000).toFixed(1)}K`;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
return quantity.toString();
|
|
81
|
+
}
|
|
82
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portfolios service exports
|
|
3
|
+
*/
|
|
4
|
+
export * from './constants';
|
|
5
|
+
export * from './types';
|
|
6
|
+
export * from './service';
|
|
7
|
+
export * from './utils';
|
|
8
|
+
export * as Allocations from './allocations';
|
|
9
|
+
export * as Holdings from './holdings';
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/portfolios/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AAGxB,OAAO,KAAK,WAAW,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,QAAQ,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Portfolios service exports
|
|
3
|
+
*/
|
|
4
|
+
export * from './constants';
|
|
5
|
+
export * from './types';
|
|
6
|
+
export * from './service';
|
|
7
|
+
export * from './utils';
|
|
8
|
+
// Sub-services
|
|
9
|
+
export * as Allocations from './allocations';
|
|
10
|
+
export * as Holdings from './holdings';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Portfolio, PaginatedPortfolios, PortfolioPayload, RebalancingTradesGenerationResponse } from './types';
|
|
2
|
+
export declare const getPortfolios: () => Promise<import("axios").AxiosResponse<PaginatedPortfolios, any>>;
|
|
3
|
+
export declare const createPortfolio: (data: PortfolioPayload) => Promise<import("axios").AxiosResponse<Portfolio, any>>;
|
|
4
|
+
export declare const updatePortfolio: (uuid: string, data: Partial<PortfolioPayload>) => Promise<import("axios").AxiosResponse<Portfolio, any>>;
|
|
5
|
+
export declare const getPortfolioByUuid: (uuid: string) => Promise<import("axios").AxiosResponse<Portfolio, any>>;
|
|
6
|
+
export declare const generateRebalancingTrades: (portfolioUuid: string) => Promise<import("axios").AxiosResponse<RebalancingTradesGenerationResponse, any>>;
|
|
7
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/services/portfolios/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,mCAAmC,EAAE,MAAM,SAAS,CAAC;AAGrH,eAAO,MAAM,aAAa,wEAEzB,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,MAAM,gBAAgB,2DAErD,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,2DAE5E,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,2DAE9C,CAAC;AAGF,eAAO,MAAM,yBAAyB,GAAI,eAAe,MAAM,qFAI9D,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { webApiClient } from '../../api/apiClient';
|
|
2
|
+
import { API_ENDPOINTS } from './constants';
|
|
3
|
+
// Portfolio CRUD operations
|
|
4
|
+
export const getPortfolios = () => {
|
|
5
|
+
return webApiClient.get(API_ENDPOINTS.PORTFOLIOS);
|
|
6
|
+
};
|
|
7
|
+
export const createPortfolio = (data) => {
|
|
8
|
+
return webApiClient.post(API_ENDPOINTS.PORTFOLIOS, data);
|
|
9
|
+
};
|
|
10
|
+
export const updatePortfolio = (uuid, data) => {
|
|
11
|
+
return webApiClient.patch(`${API_ENDPOINTS.PORTFOLIOS}${uuid}/`, data);
|
|
12
|
+
};
|
|
13
|
+
export const getPortfolioByUuid = (uuid) => {
|
|
14
|
+
return webApiClient.get(`${API_ENDPOINTS.PORTFOLIOS}${uuid}/`);
|
|
15
|
+
};
|
|
16
|
+
// Portfolio rebalancing operations
|
|
17
|
+
export const generateRebalancingTrades = (portfolioUuid) => {
|
|
18
|
+
return webApiClient.post(`${API_ENDPOINTS.PORTFOLIOS}${portfolioUuid}/generate-rebalancing-trades/`);
|
|
19
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { PaginatedResponse } from '../../api/types';
|
|
2
|
+
export interface Portfolio {
|
|
3
|
+
uuid: string;
|
|
4
|
+
account: string;
|
|
5
|
+
name: string;
|
|
6
|
+
template: string | null;
|
|
7
|
+
marketValue: string;
|
|
8
|
+
createdAt?: string;
|
|
9
|
+
updatedAt?: string;
|
|
10
|
+
}
|
|
11
|
+
export type PaginatedPortfolios = PaginatedResponse<Portfolio>;
|
|
12
|
+
export interface PortfolioPayload {
|
|
13
|
+
account: string;
|
|
14
|
+
name: string;
|
|
15
|
+
template?: string | null;
|
|
16
|
+
}
|
|
17
|
+
export interface RebalancingTradesGenerationResponse {
|
|
18
|
+
status: string;
|
|
19
|
+
message: string;
|
|
20
|
+
tradeCount?: number;
|
|
21
|
+
buyTradeCount?: number;
|
|
22
|
+
sellTradeCount?: number;
|
|
23
|
+
totalTradeValue?: number;
|
|
24
|
+
netCashImpact?: number;
|
|
25
|
+
availableCash?: number;
|
|
26
|
+
requiredMinimum?: number;
|
|
27
|
+
errorType?: 'business_logic' | 'permission' | 'server';
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/portfolios/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,mCAAmC;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,gBAAgB,GAAG,YAAY,GAAG,QAAQ,CAAC;CACxD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const formatPortfolioValue: (value: string | number) => string;
|
|
2
|
+
export declare const calculateTotalValue: (marketValue: string | number, cashBalance: string | number) => number;
|
|
3
|
+
export declare const getMarketAllocation: (marketValue: string | number, totalValue: string | number) => number;
|
|
4
|
+
export declare const getCashAllocation: (cashBalance: string | number, totalValue: string | number) => number;
|
|
5
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/services/portfolios/utils.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,oBAAoB,GAAI,OAAO,MAAM,GAAG,MAAM,KAAG,MAQ7D,CAAC;AAGF,eAAO,MAAM,mBAAmB,GAAI,aAAa,MAAM,GAAG,MAAM,EAAE,aAAa,MAAM,GAAG,MAAM,KAAG,MAIhG,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,aAAa,MAAM,GAAG,MAAM,EAAE,YAAY,MAAM,GAAG,MAAM,KAAG,MAI/F,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,GAAG,MAAM,EAAE,YAAY,MAAM,GAAG,MAAM,KAAG,MAI7F,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Portfolio formatting utilities
|
|
2
|
+
export const formatPortfolioValue = (value) => {
|
|
3
|
+
const numValue = typeof value === 'string' ? parseFloat(value) : value;
|
|
4
|
+
return new Intl.NumberFormat('en-AU', {
|
|
5
|
+
style: 'currency',
|
|
6
|
+
currency: 'AUD',
|
|
7
|
+
minimumFractionDigits: 2,
|
|
8
|
+
maximumFractionDigits: 2,
|
|
9
|
+
}).format(numValue);
|
|
10
|
+
};
|
|
11
|
+
// Portfolio calculation utilities
|
|
12
|
+
export const calculateTotalValue = (marketValue, cashBalance) => {
|
|
13
|
+
const market = typeof marketValue === 'string' ? parseFloat(marketValue || '0') : marketValue;
|
|
14
|
+
const cash = typeof cashBalance === 'string' ? parseFloat(cashBalance || '0') : cashBalance;
|
|
15
|
+
return market + cash;
|
|
16
|
+
};
|
|
17
|
+
export const getMarketAllocation = (marketValue, totalValue) => {
|
|
18
|
+
const market = typeof marketValue === 'string' ? parseFloat(marketValue || '0') : marketValue;
|
|
19
|
+
const total = typeof totalValue === 'string' ? parseFloat(totalValue || '0') : totalValue;
|
|
20
|
+
return total > 0 ? (market / total) * 100 : 0;
|
|
21
|
+
};
|
|
22
|
+
export const getCashAllocation = (cashBalance, totalValue) => {
|
|
23
|
+
const cash = typeof cashBalance === 'string' ? parseFloat(cashBalance || '0') : cashBalance;
|
|
24
|
+
const total = typeof totalValue === 'string' ? parseFloat(totalValue || '0') : totalValue;
|
|
25
|
+
return total > 0 ? (cash / total) * 100 : 0;
|
|
26
|
+
};
|