@hed-hog/operations 0.0.330 → 0.0.331
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/README.md +5 -5
- package/dist/controllers/operations-collaborators.controller.d.ts +7 -216
- package/dist/controllers/operations-collaborators.controller.d.ts.map +1 -1
- package/dist/controllers/operations-contracts.controller.d.ts +6 -6
- package/dist/controllers/operations-projects.controller.d.ts +25 -0
- package/dist/controllers/operations-projects.controller.d.ts.map +1 -1
- package/dist/controllers/operations-projects.controller.js +48 -0
- package/dist/controllers/operations-projects.controller.js.map +1 -1
- package/dist/controllers/operations-reports.controller.d.ts +1 -1
- package/dist/controllers/operations-tasks.controller.d.ts +34 -9
- package/dist/controllers/operations-tasks.controller.d.ts.map +1 -1
- package/dist/controllers/operations-tasks.controller.js +43 -32
- package/dist/controllers/operations-tasks.controller.js.map +1 -1
- package/dist/controllers/operations-timesheets.controller.d.ts +9 -9
- package/dist/dashboard/components/DashboardLayout.d.ts +30 -0
- package/dist/dashboard/components/DashboardLayout.d.ts.map +1 -0
- package/dist/dashboard/components/DashboardLayout.js +87 -0
- package/dist/dashboard/components/DashboardLayout.js.map +1 -0
- package/dist/dashboard/components/widget-registry.d.ts +23 -0
- package/dist/dashboard/components/widget-registry.d.ts.map +1 -0
- package/dist/dashboard/components/widget-registry.js +245 -0
- package/dist/dashboard/components/widget-registry.js.map +1 -0
- package/dist/dashboard/hooks/useDashboardData.d.ts +20 -0
- package/dist/dashboard/hooks/useDashboardData.d.ts.map +1 -0
- package/dist/dashboard/hooks/useDashboardData.js +24 -0
- package/dist/dashboard/hooks/useDashboardData.js.map +1 -0
- package/dist/dashboard/types/widgets.types.d.ts +233 -0
- package/dist/dashboard/types/widgets.types.d.ts.map +1 -0
- package/dist/dashboard/types/widgets.types.js +6 -0
- package/dist/dashboard/types/widgets.types.js.map +1 -0
- package/dist/dashboard/widgets/CapacityDistribution.d.ts +23 -0
- package/dist/dashboard/widgets/CapacityDistribution.d.ts.map +1 -0
- package/dist/dashboard/widgets/CapacityDistribution.js +11 -0
- package/dist/dashboard/widgets/CapacityDistribution.js.map +1 -0
- package/dist/dashboard/widgets/EffortByProject.d.ts +22 -0
- package/dist/dashboard/widgets/EffortByProject.d.ts.map +1 -0
- package/dist/dashboard/widgets/EffortByProject.js +11 -0
- package/dist/dashboard/widgets/EffortByProject.js.map +1 -0
- package/dist/dashboard/widgets/HeadcountByArea.d.ts +24 -0
- package/dist/dashboard/widgets/HeadcountByArea.d.ts.map +1 -0
- package/dist/dashboard/widgets/HeadcountByArea.js +11 -0
- package/dist/dashboard/widgets/HeadcountByArea.js.map +1 -0
- package/dist/dashboard/widgets/ManagedProjectsStatus.d.ts +18 -0
- package/dist/dashboard/widgets/ManagedProjectsStatus.d.ts.map +1 -0
- package/dist/dashboard/widgets/ManagedProjectsStatus.js +12 -0
- package/dist/dashboard/widgets/ManagedProjectsStatus.js.map +1 -0
- package/dist/dashboard/widgets/MyHoursPeriodKpi.d.ts +22 -0
- package/dist/dashboard/widgets/MyHoursPeriodKpi.d.ts.map +1 -0
- package/dist/dashboard/widgets/MyHoursPeriodKpi.js +12 -0
- package/dist/dashboard/widgets/MyHoursPeriodKpi.js.map +1 -0
- package/dist/dashboard/widgets/MyOpenRequestsKpi.d.ts +19 -0
- package/dist/dashboard/widgets/MyOpenRequestsKpi.d.ts.map +1 -0
- package/dist/dashboard/widgets/MyOpenRequestsKpi.js +17 -0
- package/dist/dashboard/widgets/MyOpenRequestsKpi.js.map +1 -0
- package/dist/dashboard/widgets/MyPendingRequestsList.d.ts +23 -0
- package/dist/dashboard/widgets/MyPendingRequestsList.d.ts.map +1 -0
- package/dist/dashboard/widgets/MyPendingRequestsList.js +14 -0
- package/dist/dashboard/widgets/MyPendingRequestsList.js.map +1 -0
- package/dist/dashboard/widgets/MyProjectAllocationsKpi.d.ts +22 -0
- package/dist/dashboard/widgets/MyProjectAllocationsKpi.d.ts.map +1 -0
- package/dist/dashboard/widgets/MyProjectAllocationsKpi.js +11 -0
- package/dist/dashboard/widgets/MyProjectAllocationsKpi.js.map +1 -0
- package/dist/dashboard/widgets/MyQuickActions.d.ts +23 -0
- package/dist/dashboard/widgets/MyQuickActions.d.ts.map +1 -0
- package/dist/dashboard/widgets/MyQuickActions.js +18 -0
- package/dist/dashboard/widgets/MyQuickActions.js.map +1 -0
- package/dist/dashboard/widgets/MyRelevantDeadlines.d.ts +23 -0
- package/dist/dashboard/widgets/MyRelevantDeadlines.d.ts.map +1 -0
- package/dist/dashboard/widgets/MyRelevantDeadlines.js +22 -0
- package/dist/dashboard/widgets/MyRelevantDeadlines.js.map +1 -0
- package/dist/dashboard/widgets/MyTimesheetStatusKpi.d.ts +17 -0
- package/dist/dashboard/widgets/MyTimesheetStatusKpi.d.ts.map +1 -0
- package/dist/dashboard/widgets/MyTimesheetStatusKpi.js +11 -0
- package/dist/dashboard/widgets/MyTimesheetStatusKpi.js.map +1 -0
- package/dist/dashboard/widgets/MyWeeklyJourney.d.ts +21 -0
- package/dist/dashboard/widgets/MyWeeklyJourney.d.ts.map +1 -0
- package/dist/dashboard/widgets/MyWeeklyJourney.js +19 -0
- package/dist/dashboard/widgets/MyWeeklyJourney.js.map +1 -0
- package/dist/dashboard/widgets/PortfolioCostsKpi.d.ts +19 -0
- package/dist/dashboard/widgets/PortfolioCostsKpi.d.ts.map +1 -0
- package/dist/dashboard/widgets/PortfolioCostsKpi.js +12 -0
- package/dist/dashboard/widgets/PortfolioCostsKpi.js.map +1 -0
- package/dist/dashboard/widgets/PortfolioEffortKpi.d.ts +18 -0
- package/dist/dashboard/widgets/PortfolioEffortKpi.d.ts.map +1 -0
- package/dist/dashboard/widgets/PortfolioEffortKpi.js +8 -0
- package/dist/dashboard/widgets/PortfolioEffortKpi.js.map +1 -0
- package/dist/dashboard/widgets/PortfolioProjectsKpi.d.ts +22 -0
- package/dist/dashboard/widgets/PortfolioProjectsKpi.d.ts.map +1 -0
- package/dist/dashboard/widgets/PortfolioProjectsKpi.js +56 -0
- package/dist/dashboard/widgets/PortfolioProjectsKpi.js.map +1 -0
- package/dist/dashboard/widgets/PortfolioRiskKpi.d.ts +19 -0
- package/dist/dashboard/widgets/PortfolioRiskKpi.d.ts.map +1 -0
- package/dist/dashboard/widgets/PortfolioRiskKpi.js +11 -0
- package/dist/dashboard/widgets/PortfolioRiskKpi.js.map +1 -0
- package/dist/dashboard/widgets/ProjectStatusOverview.d.ts +19 -0
- package/dist/dashboard/widgets/ProjectStatusOverview.d.ts.map +1 -0
- package/dist/dashboard/widgets/ProjectStatusOverview.js +18 -0
- package/dist/dashboard/widgets/ProjectStatusOverview.js.map +1 -0
- package/dist/dashboard/widgets/StrategicDeadlines.d.ts +24 -0
- package/dist/dashboard/widgets/StrategicDeadlines.d.ts.map +1 -0
- package/dist/dashboard/widgets/StrategicDeadlines.js +22 -0
- package/dist/dashboard/widgets/StrategicDeadlines.js.map +1 -0
- package/dist/dashboard/widgets/TeamApprovalQueue.d.ts +24 -0
- package/dist/dashboard/widgets/TeamApprovalQueue.d.ts.map +1 -0
- package/dist/dashboard/widgets/TeamApprovalQueue.js +12 -0
- package/dist/dashboard/widgets/TeamApprovalQueue.js.map +1 -0
- package/dist/dashboard/widgets/TeamCapacityKpi.d.ts +18 -0
- package/dist/dashboard/widgets/TeamCapacityKpi.d.ts.map +1 -0
- package/dist/dashboard/widgets/TeamCapacityKpi.js +19 -0
- package/dist/dashboard/widgets/TeamCapacityKpi.js.map +1 -0
- package/dist/dashboard/widgets/TeamHeadcountKpi.d.ts +22 -0
- package/dist/dashboard/widgets/TeamHeadcountKpi.d.ts.map +1 -0
- package/dist/dashboard/widgets/TeamHeadcountKpi.js +56 -0
- package/dist/dashboard/widgets/TeamHeadcountKpi.js.map +1 -0
- package/dist/dashboard/widgets/TeamHoursKpi.d.ts +19 -0
- package/dist/dashboard/widgets/TeamHoursKpi.d.ts.map +1 -0
- package/dist/dashboard/widgets/TeamHoursKpi.js +13 -0
- package/dist/dashboard/widgets/TeamHoursKpi.js.map +1 -0
- package/dist/dashboard/widgets/TeamPendingApprovalsKpi.d.ts +20 -0
- package/dist/dashboard/widgets/TeamPendingApprovalsKpi.d.ts.map +1 -0
- package/dist/dashboard/widgets/TeamPendingApprovalsKpi.js +11 -0
- package/dist/dashboard/widgets/TeamPendingApprovalsKpi.js.map +1 -0
- package/dist/dashboard/widgets/TeamUtilizationOverview.d.ts +18 -0
- package/dist/dashboard/widgets/TeamUtilizationOverview.d.ts.map +1 -0
- package/dist/dashboard/widgets/TeamUtilizationOverview.js +17 -0
- package/dist/dashboard/widgets/TeamUtilizationOverview.js.map +1 -0
- package/dist/dashboard/widgets/TeamWorkloadAlerts.d.ts +24 -0
- package/dist/dashboard/widgets/TeamWorkloadAlerts.d.ts.map +1 -0
- package/dist/dashboard/widgets/TeamWorkloadAlerts.js +19 -0
- package/dist/dashboard/widgets/TeamWorkloadAlerts.js.map +1 -0
- package/dist/dashboard/widgets/index.d.ts +24 -0
- package/dist/dashboard/widgets/index.d.ts.map +1 -0
- package/dist/dashboard/widgets/index.js +54 -0
- package/dist/dashboard/widgets/index.js.map +1 -0
- package/dist/dto/create-collaborator.dto.d.ts +0 -1
- package/dist/dto/create-collaborator.dto.d.ts.map +1 -1
- package/dist/dto/create-collaborator.dto.js +0 -6
- package/dist/dto/create-collaborator.dto.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/operations.controller.d.ts +42 -0
- package/dist/operations.controller.d.ts.map +1 -1
- package/dist/operations.service.d.ts +182 -268
- package/dist/operations.service.d.ts.map +1 -1
- package/dist/operations.service.js +2147 -1337
- package/dist/operations.service.js.map +1 -1
- package/dist/operations.service.spec.js +345 -174
- package/dist/operations.service.spec.js.map +1 -1
- package/hedhog/data/dashboard_component.yaml +66 -0
- package/hedhog/data/dashboard_item.yaml +25 -25
- package/hedhog/data/route.yaml +61 -0
- package/hedhog/frontend/app/_components/collaborator-form-screen.tsx.ejs +39 -99
- package/hedhog/frontend/app/_components/collaborator-picker.tsx.ejs +158 -0
- package/hedhog/frontend/app/_components/my-project-summary-screen.tsx.ejs +314 -116
- package/hedhog/frontend/app/_components/project-assignments-tab.tsx.ejs +434 -449
- package/hedhog/frontend/app/_components/project-details-screen.tsx.ejs +289 -412
- package/hedhog/frontend/app/_components/project-file-attachments.tsx.ejs +371 -0
- package/hedhog/frontend/app/_components/project-form-screen.tsx.ejs +426 -374
- package/hedhog/frontend/app/_components/task-detail-sheet.tsx.ejs +803 -581
- package/hedhog/frontend/app/_components/task-file-attachments.tsx.ejs +4 -1
- package/hedhog/frontend/app/_components/task-form-fields.tsx.ejs +406 -0
- package/hedhog/frontend/app/_components/task-form-sheet.tsx.ejs +629 -784
- package/hedhog/frontend/app/_components/task-info-display.tsx.ejs +137 -0
- package/hedhog/frontend/app/_components/timesheet-entry-create-sheet.tsx.ejs +306 -0
- package/hedhog/frontend/app/_lib/api.ts.ejs +480 -476
- package/hedhog/frontend/app/_lib/types.ts.ejs +66 -5
- package/hedhog/frontend/app/_lib/utils/format.ts.ejs +0 -2
- package/hedhog/frontend/app/_lib/utils/task-ui.ts.ejs +43 -0
- package/hedhog/frontend/app/approvals/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/collaborator-types/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/collaborators/page.tsx.ejs +59 -8
- package/hedhog/frontend/app/contracts/page.tsx.ejs +29 -8
- package/hedhog/frontend/app/dashboard/widgets/CapacityDistribution.tsx.ejs +84 -0
- package/hedhog/frontend/app/dashboard/widgets/EffortByProject.tsx.ejs +85 -0
- package/hedhog/frontend/app/dashboard/widgets/HeadcountByArea.tsx.ejs +101 -0
- package/hedhog/frontend/app/dashboard/widgets/ManagedProjectsStatus.tsx.ejs +113 -0
- package/hedhog/frontend/app/dashboard/widgets/MyHoursPeriodKpi.tsx.ejs +87 -0
- package/hedhog/frontend/app/dashboard/widgets/MyOpenRequestsKpi.tsx.ejs +97 -0
- package/hedhog/frontend/app/dashboard/widgets/MyPendingRequestsList.tsx.ejs +99 -0
- package/hedhog/frontend/app/dashboard/widgets/MyProjectAllocationsKpi.tsx.ejs +78 -0
- package/hedhog/frontend/app/dashboard/widgets/MyQuickActions.tsx.ejs +130 -0
- package/hedhog/frontend/app/dashboard/widgets/MyRelevantDeadlines.tsx.ejs +144 -0
- package/hedhog/frontend/app/dashboard/widgets/MyTimesheetStatusKpi.tsx.ejs +78 -0
- package/hedhog/frontend/app/dashboard/widgets/MyWeeklyJourney.tsx.ejs +99 -0
- package/hedhog/frontend/app/dashboard/widgets/PortfolioCostsKpi.tsx.ejs +112 -0
- package/hedhog/frontend/app/dashboard/widgets/PortfolioEffortKpi.tsx.ejs +93 -0
- package/hedhog/frontend/app/dashboard/widgets/PortfolioProjectsKpi.tsx.ejs +96 -0
- package/hedhog/frontend/app/dashboard/widgets/PortfolioRiskKpi.tsx.ejs +115 -0
- package/hedhog/frontend/app/dashboard/widgets/ProjectStatusOverview.tsx.ejs +120 -0
- package/hedhog/frontend/app/dashboard/widgets/StrategicDeadlines.tsx.ejs +146 -0
- package/hedhog/frontend/app/dashboard/widgets/TeamApprovalQueue.tsx.ejs +108 -0
- package/hedhog/frontend/app/dashboard/widgets/TeamCapacityKpi.tsx.ejs +97 -0
- package/hedhog/frontend/app/dashboard/widgets/TeamHeadcountKpi.tsx.ejs +100 -0
- package/hedhog/frontend/app/dashboard/widgets/TeamHoursKpi.tsx.ejs +104 -0
- package/hedhog/frontend/app/dashboard/widgets/TeamPendingApprovalsKpi.tsx.ejs +110 -0
- package/hedhog/frontend/app/dashboard/widgets/TeamUtilizationOverview.tsx.ejs +115 -0
- package/hedhog/frontend/app/dashboard/widgets/TeamWorkloadAlerts.tsx.ejs +117 -0
- package/hedhog/frontend/app/dashboard/widgets/index.ts.ejs +26 -0
- package/hedhog/frontend/app/departments/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/my-projects/page.tsx.ejs +14 -10
- package/hedhog/frontend/app/my-tasks/page.tsx.ejs +328 -105
- package/hedhog/frontend/app/project-cost-categories/page.tsx.ejs +58 -52
- package/hedhog/frontend/app/project-cost-types/page.tsx.ejs +58 -51
- package/hedhog/frontend/app/projects/page.tsx.ejs +376 -30
- package/hedhog/frontend/app/schedule-adjustments/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/time-off/page.tsx.ejs +6 -1
- package/hedhog/frontend/app/timesheets/page.tsx.ejs +10 -4
- package/hedhog/frontend/messages/en.json +238 -46
- package/hedhog/frontend/messages/operations/en.json +61 -52
- package/hedhog/frontend/messages/operations/pt.json +59 -43
- package/hedhog/frontend/messages/pt.json +238 -46
- package/hedhog/frontend/widgets/capacity-distribution.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/effort-by-project.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/headcount-by-area.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/index.ts.ejs +25 -0
- package/hedhog/frontend/widgets/managed-projects-status.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/my-hours-period-kpi.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/my-open-requests-kpi.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/my-pending-requests-list.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/my-project-allocations-kpi.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/my-quick-actions.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/my-relevant-deadlines.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/my-timesheet-status-kpi.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/my-weekly-journey.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/portfolio-costs-kpi.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/portfolio-effort-kpi.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/portfolio-projects-kpi.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/portfolio-risk-kpi.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/project-status-overview.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/shared-operations-widget.tsx.ejs +170 -0
- package/hedhog/frontend/widgets/strategic-deadlines.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/team-approval-queue.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/team-capacity-kpi.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/team-headcount-kpi.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/team-hours-kpi.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/team-pending-approvals-kpi.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/team-utilization-overview.tsx.ejs +17 -0
- package/hedhog/frontend/widgets/team-workload-alerts.tsx.ejs +17 -0
- package/hedhog/table/operations_collaborator.yaml +8 -13
- package/hedhog/table/operations_project.yaml +1 -1
- package/hedhog/table/operations_project_file.yaml +23 -0
- package/hedhog/table/operations_task.yaml +76 -69
- package/hedhog/table/operations_task_activity.yaml +51 -0
- package/package.json +6 -5
- package/src/controllers/operations-projects.controller.ts +41 -8
- package/src/controllers/operations-tasks.controller.ts +156 -166
- package/src/dashboard/README.md +214 -0
- package/src/dashboard/components/DashboardLayout.tsx +131 -0
- package/src/dashboard/components/widget-registry.ts +255 -0
- package/src/dashboard/hooks/useDashboardData.ts +29 -0
- package/src/dashboard/types/widgets.types.ts +237 -0
- package/src/dashboard/widgets/CapacityDistribution.tsx +56 -0
- package/src/dashboard/widgets/EffortByProject.tsx +51 -0
- package/src/dashboard/widgets/HeadcountByArea.tsx +57 -0
- package/src/dashboard/widgets/ManagedProjectsStatus.tsx +53 -0
- package/src/dashboard/widgets/MyHoursPeriodKpi.tsx +87 -0
- package/src/dashboard/widgets/MyOpenRequestsKpi.tsx +51 -0
- package/src/dashboard/widgets/MyPendingRequestsList.tsx +63 -0
- package/src/dashboard/widgets/MyProjectAllocationsKpi.tsx +57 -0
- package/src/dashboard/widgets/MyQuickActions.tsx +62 -0
- package/src/dashboard/widgets/MyRelevantDeadlines.tsx +84 -0
- package/src/dashboard/widgets/MyTimesheetStatusKpi.tsx +65 -0
- package/src/dashboard/widgets/MyWeeklyJourney.tsx +57 -0
- package/src/dashboard/widgets/PortfolioCostsKpi.tsx +48 -0
- package/src/dashboard/widgets/PortfolioEffortKpi.tsx +41 -0
- package/src/dashboard/widgets/PortfolioRiskKpi.tsx +50 -0
- package/src/dashboard/widgets/ProjectStatusOverview.tsx +52 -0
- package/src/dashboard/widgets/StrategicDeadlines.tsx +93 -0
- package/src/dashboard/widgets/TeamApprovalQueue.tsx +70 -0
- package/src/dashboard/widgets/TeamCapacityKpi.tsx +50 -0
- package/src/dashboard/widgets/TeamHoursKpi.tsx +51 -0
- package/src/dashboard/widgets/TeamPendingApprovalsKpi.tsx +53 -0
- package/src/dashboard/widgets/TeamUtilizationOverview.tsx +62 -0
- package/src/dashboard/widgets/TeamWorkloadAlerts.tsx +81 -0
- package/src/dashboard/widgets/index.ts +26 -0
- package/src/dto/create-collaborator.dto.ts +4 -11
- package/src/index.ts +3 -0
- package/src/operations.service.spec.ts +988 -764
- package/src/operations.service.ts +4277 -2535
|
@@ -1,476 +1,480 @@
|
|
|
1
|
-
type RequestFn = (input: {
|
|
2
|
-
url: string;
|
|
3
|
-
method: string;
|
|
4
|
-
data?: unknown;
|
|
5
|
-
}) => Promise<{ data: unknown }>;
|
|
6
|
-
|
|
7
|
-
export function getOperationsErrorMessage(error: unknown, fallback: string) {
|
|
8
|
-
if (error && typeof error === 'object') {
|
|
9
|
-
const requestError = error as {
|
|
10
|
-
message?: string;
|
|
11
|
-
response?: {
|
|
12
|
-
data?: {
|
|
13
|
-
message?: string | string[];
|
|
14
|
-
};
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const message =
|
|
19
|
-
requestError.response?.data?.message ?? requestError.message;
|
|
20
|
-
|
|
21
|
-
if (Array.isArray(message)) {
|
|
22
|
-
const combined = message.filter(Boolean).join(' ');
|
|
23
|
-
if (combined.trim()) {
|
|
24
|
-
return combined;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (typeof message === 'string' && message.trim()) {
|
|
29
|
-
return message;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return fallback;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export async function fetchOperations<T>(request: RequestFn, url: string) {
|
|
37
|
-
const response = await request({
|
|
38
|
-
url,
|
|
39
|
-
method: 'GET',
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
return response.data as T;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export async function mutateOperations<T>(
|
|
46
|
-
request: RequestFn,
|
|
47
|
-
url: string,
|
|
48
|
-
method: 'POST' | 'PATCH' | 'DELETE',
|
|
49
|
-
data?: unknown
|
|
50
|
-
) {
|
|
51
|
-
const response = await request({
|
|
52
|
-
url,
|
|
53
|
-
method,
|
|
54
|
-
data,
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
return response.data as T;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ─── Cost Types ───────────────────────────────────────────────────────────────
|
|
61
|
-
|
|
62
|
-
export type CostType = {
|
|
63
|
-
id: number;
|
|
64
|
-
slug: string;
|
|
65
|
-
name: string;
|
|
66
|
-
code?: string | null;
|
|
67
|
-
category?: string | null;
|
|
68
|
-
description?: string | null;
|
|
69
|
-
defaultRecurrence?: 'monthly' | 'one_time' | 'yearly' | null;
|
|
70
|
-
isAllocatable?: boolean | null;
|
|
71
|
-
isDepreciable?: boolean | null;
|
|
72
|
-
isActive: boolean;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
export function fetchCostTypes(
|
|
76
|
-
request: RequestFn,
|
|
77
|
-
args: {
|
|
78
|
-
search?: string;
|
|
79
|
-
active?: boolean;
|
|
80
|
-
page?: number;
|
|
81
|
-
pageSize?: number;
|
|
82
|
-
} = {}
|
|
83
|
-
) {
|
|
84
|
-
const { search, active, page, pageSize } = args;
|
|
85
|
-
const params = new URLSearchParams();
|
|
86
|
-
if (search?.trim()) {
|
|
87
|
-
params.set('search', search.trim());
|
|
88
|
-
}
|
|
89
|
-
if (active !== undefined) {
|
|
90
|
-
params.set('active', String(active));
|
|
91
|
-
}
|
|
92
|
-
if (page !== undefined) {
|
|
93
|
-
params.set('page', String(page));
|
|
94
|
-
}
|
|
95
|
-
if (pageSize !== undefined) {
|
|
96
|
-
params.set('pageSize', String(pageSize));
|
|
97
|
-
}
|
|
98
|
-
const qs = params.toString();
|
|
99
|
-
return fetchOperations<CostType[]>(
|
|
100
|
-
request,
|
|
101
|
-
qs ? `/operations/cost-types?${qs}` : '/operations/cost-types'
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export function createCostType(
|
|
106
|
-
request: RequestFn,
|
|
107
|
-
data: {
|
|
108
|
-
name: string;
|
|
109
|
-
slug?: string | null;
|
|
110
|
-
code?: string | null;
|
|
111
|
-
category?: string | null;
|
|
112
|
-
description?: string | null;
|
|
113
|
-
defaultRecurrence?: string | null;
|
|
114
|
-
isAllocatable?: boolean | null;
|
|
115
|
-
isDepreciable?: boolean | null;
|
|
116
|
-
isActive?: boolean;
|
|
117
|
-
}
|
|
118
|
-
) {
|
|
119
|
-
return mutateOperations<CostType>(
|
|
120
|
-
request,
|
|
121
|
-
'/operations/cost-types',
|
|
122
|
-
'POST',
|
|
123
|
-
data
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// ─── Collaborators ────────────────────────────────────────────────────────────
|
|
128
|
-
|
|
129
|
-
export function fetchCollaborators(request: RequestFn) {
|
|
130
|
-
return fetchOperations<import('./types').OperationsCollaborator[]>(
|
|
131
|
-
request,
|
|
132
|
-
'/operations/collaborators'
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// ─── Collaborator Costs ───────────────────────────────────────────────────────
|
|
137
|
-
|
|
138
|
-
export type CollaboratorCost = {
|
|
139
|
-
id: number;
|
|
140
|
-
collaboratorId: number;
|
|
141
|
-
costTypeId: number;
|
|
142
|
-
costTypeName: string;
|
|
143
|
-
costTypeSlug: string;
|
|
144
|
-
amount: string;
|
|
145
|
-
currency: string;
|
|
146
|
-
recurrence: 'one_time' | 'monthly' | 'yearly';
|
|
147
|
-
allocatable?: boolean;
|
|
148
|
-
/** ISO date string — mapped to startDate going forward */
|
|
149
|
-
referenceDate: string | null;
|
|
150
|
-
startDate?: string | null;
|
|
151
|
-
endDate?: string | null;
|
|
152
|
-
depreciationMonths?: number | null;
|
|
153
|
-
description: string | null;
|
|
154
|
-
notes?: string | null;
|
|
155
|
-
createdAt: string;
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
export function fetchCollaboratorCosts(
|
|
159
|
-
request: RequestFn,
|
|
160
|
-
collaboratorId: number
|
|
161
|
-
) {
|
|
162
|
-
return fetchOperations<CollaboratorCost[]>(
|
|
163
|
-
request,
|
|
164
|
-
`/operations/collaborators/${collaboratorId}/costs`
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export function createCollaboratorCost(
|
|
169
|
-
request: RequestFn,
|
|
170
|
-
collaboratorId: number,
|
|
171
|
-
data: {
|
|
172
|
-
costTypeId: number;
|
|
173
|
-
amount: number;
|
|
174
|
-
currency?: string;
|
|
175
|
-
recurrence?: string;
|
|
176
|
-
allocatable?: boolean;
|
|
177
|
-
referenceDate?: string | null;
|
|
178
|
-
startDate?: string | null;
|
|
179
|
-
endDate?: string | null;
|
|
180
|
-
depreciationMonths?: number | null;
|
|
181
|
-
description?: string | null;
|
|
182
|
-
notes?: string | null;
|
|
183
|
-
}
|
|
184
|
-
) {
|
|
185
|
-
return mutateOperations<CollaboratorCost>(
|
|
186
|
-
request,
|
|
187
|
-
`/operations/collaborators/${collaboratorId}/costs`,
|
|
188
|
-
'POST',
|
|
189
|
-
data
|
|
190
|
-
);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export function updateCollaboratorCost(
|
|
194
|
-
request: RequestFn,
|
|
195
|
-
collaboratorId: number,
|
|
196
|
-
costId: number,
|
|
197
|
-
data: Partial<{
|
|
198
|
-
costTypeId: number;
|
|
199
|
-
amount: number;
|
|
200
|
-
currency: string;
|
|
201
|
-
recurrence: string;
|
|
202
|
-
allocatable: boolean;
|
|
203
|
-
referenceDate: string | null;
|
|
204
|
-
startDate: string | null;
|
|
205
|
-
endDate: string | null;
|
|
206
|
-
depreciationMonths: number | null;
|
|
207
|
-
description: string | null;
|
|
208
|
-
notes: string | null;
|
|
209
|
-
}>
|
|
210
|
-
) {
|
|
211
|
-
return mutateOperations<CollaboratorCost>(
|
|
212
|
-
request,
|
|
213
|
-
`/operations/collaborators/${collaboratorId}/costs/${costId}`,
|
|
214
|
-
'PATCH',
|
|
215
|
-
data
|
|
216
|
-
);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export function deleteCollaboratorCost(
|
|
220
|
-
request: RequestFn,
|
|
221
|
-
collaboratorId: number,
|
|
222
|
-
costId: number
|
|
223
|
-
) {
|
|
224
|
-
return mutateOperations<{ success: boolean }>(
|
|
225
|
-
request,
|
|
226
|
-
`/operations/collaborators/${collaboratorId}/costs/${costId}`,
|
|
227
|
-
'DELETE'
|
|
228
|
-
);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// ─── Currencies ───────────────────────────────────────────────────────────────
|
|
232
|
-
|
|
233
|
-
export type Currency = Record<string, unknown> & {
|
|
234
|
-
id: number;
|
|
235
|
-
code: string;
|
|
236
|
-
name: string;
|
|
237
|
-
symbol: string;
|
|
238
|
-
status: 'active' | 'inactive';
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
export function listCurrencies(
|
|
242
|
-
request: RequestFn,
|
|
243
|
-
params?: Record<string, string>
|
|
244
|
-
) {
|
|
245
|
-
const qs = params ? new URLSearchParams(params).toString() : '';
|
|
246
|
-
return fetchOperations<Currency[]>(
|
|
247
|
-
request,
|
|
248
|
-
qs ? `/finance/currencies?${qs}` : '/finance/currencies'
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// ─── Project Cost Categories ──────────────────────────────────────────────────
|
|
253
|
-
|
|
254
|
-
export function listProjectCostCategories(
|
|
255
|
-
request: RequestFn,
|
|
256
|
-
params?: Record<string, string>
|
|
257
|
-
) {
|
|
258
|
-
const qs = params ? new URLSearchParams(params).toString() : '';
|
|
259
|
-
return fetchOperations(
|
|
260
|
-
request,
|
|
261
|
-
qs
|
|
262
|
-
? `/operations/project-cost-categories?${qs}`
|
|
263
|
-
: '/operations/project-cost-categories'
|
|
264
|
-
);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
export function createProjectCostCategory(request: RequestFn, data: unknown) {
|
|
268
|
-
return mutateOperations(
|
|
269
|
-
request,
|
|
270
|
-
'/operations/project-cost-categories',
|
|
271
|
-
'POST',
|
|
272
|
-
data
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
export function updateProjectCostCategory(
|
|
277
|
-
request: RequestFn,
|
|
278
|
-
id: number,
|
|
279
|
-
data: unknown
|
|
280
|
-
) {
|
|
281
|
-
return mutateOperations(
|
|
282
|
-
request,
|
|
283
|
-
`/operations/project-cost-categories/${id}`,
|
|
284
|
-
'PATCH',
|
|
285
|
-
data
|
|
286
|
-
);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
export function deleteProjectCostCategory(request: RequestFn, id: number) {
|
|
290
|
-
return mutateOperations(
|
|
291
|
-
request,
|
|
292
|
-
`/operations/project-cost-categories/${id}`,
|
|
293
|
-
'DELETE'
|
|
294
|
-
);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
// ─── Project Cost Types ───────────────────────────────────────────────────────
|
|
298
|
-
|
|
299
|
-
export function listProjectCostTypes(
|
|
300
|
-
request: RequestFn,
|
|
301
|
-
params?: Record<string, string>
|
|
302
|
-
) {
|
|
303
|
-
const qs = params ? new URLSearchParams(params).toString() : '';
|
|
304
|
-
return fetchOperations(
|
|
305
|
-
request,
|
|
306
|
-
qs
|
|
307
|
-
? `/operations/project-cost-types?${qs}`
|
|
308
|
-
: '/operations/project-cost-types'
|
|
309
|
-
);
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
export function createProjectCostType(request: RequestFn, data: unknown) {
|
|
313
|
-
return mutateOperations(
|
|
314
|
-
request,
|
|
315
|
-
'/operations/project-cost-types',
|
|
316
|
-
'POST',
|
|
317
|
-
data
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
export function updateProjectCostType(
|
|
322
|
-
request: RequestFn,
|
|
323
|
-
id: number,
|
|
324
|
-
data: unknown
|
|
325
|
-
) {
|
|
326
|
-
return mutateOperations(
|
|
327
|
-
request,
|
|
328
|
-
`/operations/project-cost-types/${id}`,
|
|
329
|
-
'PATCH',
|
|
330
|
-
data
|
|
331
|
-
);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
export function deleteProjectCostType(request: RequestFn, id: number) {
|
|
335
|
-
return mutateOperations(
|
|
336
|
-
request,
|
|
337
|
-
`/operations/project-cost-types/${id}`,
|
|
338
|
-
'DELETE'
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// ─── Project Costs ────────────────────────────────────────────────────────────
|
|
343
|
-
|
|
344
|
-
export function listProjectCosts(
|
|
345
|
-
request: RequestFn,
|
|
346
|
-
projectId: number,
|
|
347
|
-
params?: Record<string, string>
|
|
348
|
-
) {
|
|
349
|
-
const qs = params ? new URLSearchParams(params).toString() : '';
|
|
350
|
-
return fetchOperations(
|
|
351
|
-
request,
|
|
352
|
-
qs
|
|
353
|
-
? `/operations/projects/${projectId}/costs?${qs}`
|
|
354
|
-
: `/operations/projects/${projectId}/costs`
|
|
355
|
-
);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
export function getProjectCostsSummary(request: RequestFn, projectId: number) {
|
|
359
|
-
return fetchOperations(
|
|
360
|
-
request,
|
|
361
|
-
`/operations/projects/${projectId}/costs/summary`
|
|
362
|
-
);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
export function getFullProjectCostSummary(
|
|
366
|
-
request: RequestFn,
|
|
367
|
-
projectId: number
|
|
368
|
-
) {
|
|
369
|
-
return fetchOperations(
|
|
370
|
-
request,
|
|
371
|
-
`/operations/projects/${projectId}/cost-summary`
|
|
372
|
-
);
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
export function createProjectCost(
|
|
376
|
-
request: RequestFn,
|
|
377
|
-
projectId: number,
|
|
378
|
-
data: unknown
|
|
379
|
-
) {
|
|
380
|
-
return mutateOperations(
|
|
381
|
-
request,
|
|
382
|
-
`/operations/projects/${projectId}/costs`,
|
|
383
|
-
'POST',
|
|
384
|
-
data
|
|
385
|
-
);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
export function updateProjectCost(
|
|
389
|
-
request: RequestFn,
|
|
390
|
-
projectId: number,
|
|
391
|
-
costId: number,
|
|
392
|
-
data: unknown
|
|
393
|
-
) {
|
|
394
|
-
return mutateOperations(
|
|
395
|
-
request,
|
|
396
|
-
`/operations/projects/${projectId}/costs/${costId}`,
|
|
397
|
-
'PATCH',
|
|
398
|
-
data
|
|
399
|
-
);
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
export function deleteProjectCost(
|
|
403
|
-
request: RequestFn,
|
|
404
|
-
projectId: number,
|
|
405
|
-
costId: number
|
|
406
|
-
) {
|
|
407
|
-
return mutateOperations(
|
|
408
|
-
request,
|
|
409
|
-
`/operations/projects/${projectId}/costs/${costId}`,
|
|
410
|
-
'DELETE'
|
|
411
|
-
);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
export function getProjectCostReport(
|
|
415
|
-
request: RequestFn,
|
|
416
|
-
projectId: number,
|
|
417
|
-
filters?: Record<string, unknown>
|
|
418
|
-
) {
|
|
419
|
-
const params = filters
|
|
420
|
-
? '?' +
|
|
421
|
-
new URLSearchParams(
|
|
422
|
-
Object.entries(filters)
|
|
423
|
-
.filter(([, v]) => v !== undefined && v !== null)
|
|
424
|
-
.map(([k, v]) => [k, String(v)])
|
|
425
|
-
).toString()
|
|
426
|
-
: '';
|
|
427
|
-
return fetchOperations(
|
|
428
|
-
request,
|
|
429
|
-
`/operations/projects/${projectId}/costs/report${params}`
|
|
430
|
-
);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
// ─── Task Comments ────────────────────────────────────────────────────────────
|
|
434
|
-
|
|
435
|
-
export function
|
|
436
|
-
return fetchOperations(request, `/operations/tasks/${taskId}/
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
export function
|
|
440
|
-
request
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
1
|
+
type RequestFn = (input: {
|
|
2
|
+
url: string;
|
|
3
|
+
method: string;
|
|
4
|
+
data?: unknown;
|
|
5
|
+
}) => Promise<{ data: unknown }>;
|
|
6
|
+
|
|
7
|
+
export function getOperationsErrorMessage(error: unknown, fallback: string) {
|
|
8
|
+
if (error && typeof error === 'object') {
|
|
9
|
+
const requestError = error as {
|
|
10
|
+
message?: string;
|
|
11
|
+
response?: {
|
|
12
|
+
data?: {
|
|
13
|
+
message?: string | string[];
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const message =
|
|
19
|
+
requestError.response?.data?.message ?? requestError.message;
|
|
20
|
+
|
|
21
|
+
if (Array.isArray(message)) {
|
|
22
|
+
const combined = message.filter(Boolean).join(' ');
|
|
23
|
+
if (combined.trim()) {
|
|
24
|
+
return combined;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (typeof message === 'string' && message.trim()) {
|
|
29
|
+
return message;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return fallback;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function fetchOperations<T>(request: RequestFn, url: string) {
|
|
37
|
+
const response = await request({
|
|
38
|
+
url,
|
|
39
|
+
method: 'GET',
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return response.data as T;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function mutateOperations<T>(
|
|
46
|
+
request: RequestFn,
|
|
47
|
+
url: string,
|
|
48
|
+
method: 'POST' | 'PATCH' | 'DELETE',
|
|
49
|
+
data?: unknown
|
|
50
|
+
) {
|
|
51
|
+
const response = await request({
|
|
52
|
+
url,
|
|
53
|
+
method,
|
|
54
|
+
data,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
return response.data as T;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ─── Cost Types ───────────────────────────────────────────────────────────────
|
|
61
|
+
|
|
62
|
+
export type CostType = {
|
|
63
|
+
id: number;
|
|
64
|
+
slug: string;
|
|
65
|
+
name: string;
|
|
66
|
+
code?: string | null;
|
|
67
|
+
category?: string | null;
|
|
68
|
+
description?: string | null;
|
|
69
|
+
defaultRecurrence?: 'monthly' | 'one_time' | 'yearly' | null;
|
|
70
|
+
isAllocatable?: boolean | null;
|
|
71
|
+
isDepreciable?: boolean | null;
|
|
72
|
+
isActive: boolean;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export function fetchCostTypes(
|
|
76
|
+
request: RequestFn,
|
|
77
|
+
args: {
|
|
78
|
+
search?: string;
|
|
79
|
+
active?: boolean;
|
|
80
|
+
page?: number;
|
|
81
|
+
pageSize?: number;
|
|
82
|
+
} = {}
|
|
83
|
+
) {
|
|
84
|
+
const { search, active, page, pageSize } = args;
|
|
85
|
+
const params = new URLSearchParams();
|
|
86
|
+
if (search?.trim()) {
|
|
87
|
+
params.set('search', search.trim());
|
|
88
|
+
}
|
|
89
|
+
if (active !== undefined) {
|
|
90
|
+
params.set('active', String(active));
|
|
91
|
+
}
|
|
92
|
+
if (page !== undefined) {
|
|
93
|
+
params.set('page', String(page));
|
|
94
|
+
}
|
|
95
|
+
if (pageSize !== undefined) {
|
|
96
|
+
params.set('pageSize', String(pageSize));
|
|
97
|
+
}
|
|
98
|
+
const qs = params.toString();
|
|
99
|
+
return fetchOperations<CostType[]>(
|
|
100
|
+
request,
|
|
101
|
+
qs ? `/operations/cost-types?${qs}` : '/operations/cost-types'
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function createCostType(
|
|
106
|
+
request: RequestFn,
|
|
107
|
+
data: {
|
|
108
|
+
name: string;
|
|
109
|
+
slug?: string | null;
|
|
110
|
+
code?: string | null;
|
|
111
|
+
category?: string | null;
|
|
112
|
+
description?: string | null;
|
|
113
|
+
defaultRecurrence?: string | null;
|
|
114
|
+
isAllocatable?: boolean | null;
|
|
115
|
+
isDepreciable?: boolean | null;
|
|
116
|
+
isActive?: boolean;
|
|
117
|
+
}
|
|
118
|
+
) {
|
|
119
|
+
return mutateOperations<CostType>(
|
|
120
|
+
request,
|
|
121
|
+
'/operations/cost-types',
|
|
122
|
+
'POST',
|
|
123
|
+
data
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ─── Collaborators ────────────────────────────────────────────────────────────
|
|
128
|
+
|
|
129
|
+
export function fetchCollaborators(request: RequestFn) {
|
|
130
|
+
return fetchOperations<import('./types').OperationsCollaborator[]>(
|
|
131
|
+
request,
|
|
132
|
+
'/operations/collaborators'
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// ─── Collaborator Costs ───────────────────────────────────────────────────────
|
|
137
|
+
|
|
138
|
+
export type CollaboratorCost = {
|
|
139
|
+
id: number;
|
|
140
|
+
collaboratorId: number;
|
|
141
|
+
costTypeId: number;
|
|
142
|
+
costTypeName: string;
|
|
143
|
+
costTypeSlug: string;
|
|
144
|
+
amount: string;
|
|
145
|
+
currency: string;
|
|
146
|
+
recurrence: 'one_time' | 'monthly' | 'yearly';
|
|
147
|
+
allocatable?: boolean;
|
|
148
|
+
/** ISO date string — mapped to startDate going forward */
|
|
149
|
+
referenceDate: string | null;
|
|
150
|
+
startDate?: string | null;
|
|
151
|
+
endDate?: string | null;
|
|
152
|
+
depreciationMonths?: number | null;
|
|
153
|
+
description: string | null;
|
|
154
|
+
notes?: string | null;
|
|
155
|
+
createdAt: string;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export function fetchCollaboratorCosts(
|
|
159
|
+
request: RequestFn,
|
|
160
|
+
collaboratorId: number
|
|
161
|
+
) {
|
|
162
|
+
return fetchOperations<CollaboratorCost[]>(
|
|
163
|
+
request,
|
|
164
|
+
`/operations/collaborators/${collaboratorId}/costs`
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function createCollaboratorCost(
|
|
169
|
+
request: RequestFn,
|
|
170
|
+
collaboratorId: number,
|
|
171
|
+
data: {
|
|
172
|
+
costTypeId: number;
|
|
173
|
+
amount: number;
|
|
174
|
+
currency?: string;
|
|
175
|
+
recurrence?: string;
|
|
176
|
+
allocatable?: boolean;
|
|
177
|
+
referenceDate?: string | null;
|
|
178
|
+
startDate?: string | null;
|
|
179
|
+
endDate?: string | null;
|
|
180
|
+
depreciationMonths?: number | null;
|
|
181
|
+
description?: string | null;
|
|
182
|
+
notes?: string | null;
|
|
183
|
+
}
|
|
184
|
+
) {
|
|
185
|
+
return mutateOperations<CollaboratorCost>(
|
|
186
|
+
request,
|
|
187
|
+
`/operations/collaborators/${collaboratorId}/costs`,
|
|
188
|
+
'POST',
|
|
189
|
+
data
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function updateCollaboratorCost(
|
|
194
|
+
request: RequestFn,
|
|
195
|
+
collaboratorId: number,
|
|
196
|
+
costId: number,
|
|
197
|
+
data: Partial<{
|
|
198
|
+
costTypeId: number;
|
|
199
|
+
amount: number;
|
|
200
|
+
currency: string;
|
|
201
|
+
recurrence: string;
|
|
202
|
+
allocatable: boolean;
|
|
203
|
+
referenceDate: string | null;
|
|
204
|
+
startDate: string | null;
|
|
205
|
+
endDate: string | null;
|
|
206
|
+
depreciationMonths: number | null;
|
|
207
|
+
description: string | null;
|
|
208
|
+
notes: string | null;
|
|
209
|
+
}>
|
|
210
|
+
) {
|
|
211
|
+
return mutateOperations<CollaboratorCost>(
|
|
212
|
+
request,
|
|
213
|
+
`/operations/collaborators/${collaboratorId}/costs/${costId}`,
|
|
214
|
+
'PATCH',
|
|
215
|
+
data
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function deleteCollaboratorCost(
|
|
220
|
+
request: RequestFn,
|
|
221
|
+
collaboratorId: number,
|
|
222
|
+
costId: number
|
|
223
|
+
) {
|
|
224
|
+
return mutateOperations<{ success: boolean }>(
|
|
225
|
+
request,
|
|
226
|
+
`/operations/collaborators/${collaboratorId}/costs/${costId}`,
|
|
227
|
+
'DELETE'
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ─── Currencies ───────────────────────────────────────────────────────────────
|
|
232
|
+
|
|
233
|
+
export type Currency = Record<string, unknown> & {
|
|
234
|
+
id: number;
|
|
235
|
+
code: string;
|
|
236
|
+
name: string;
|
|
237
|
+
symbol: string;
|
|
238
|
+
status: 'active' | 'inactive';
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
export function listCurrencies(
|
|
242
|
+
request: RequestFn,
|
|
243
|
+
params?: Record<string, string>
|
|
244
|
+
) {
|
|
245
|
+
const qs = params ? new URLSearchParams(params).toString() : '';
|
|
246
|
+
return fetchOperations<Currency[]>(
|
|
247
|
+
request,
|
|
248
|
+
qs ? `/finance/currencies?${qs}` : '/finance/currencies'
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// ─── Project Cost Categories ──────────────────────────────────────────────────
|
|
253
|
+
|
|
254
|
+
export function listProjectCostCategories(
|
|
255
|
+
request: RequestFn,
|
|
256
|
+
params?: Record<string, string>
|
|
257
|
+
) {
|
|
258
|
+
const qs = params ? new URLSearchParams(params).toString() : '';
|
|
259
|
+
return fetchOperations(
|
|
260
|
+
request,
|
|
261
|
+
qs
|
|
262
|
+
? `/operations/project-cost-categories?${qs}`
|
|
263
|
+
: '/operations/project-cost-categories'
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export function createProjectCostCategory(request: RequestFn, data: unknown) {
|
|
268
|
+
return mutateOperations(
|
|
269
|
+
request,
|
|
270
|
+
'/operations/project-cost-categories',
|
|
271
|
+
'POST',
|
|
272
|
+
data
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export function updateProjectCostCategory(
|
|
277
|
+
request: RequestFn,
|
|
278
|
+
id: number,
|
|
279
|
+
data: unknown
|
|
280
|
+
) {
|
|
281
|
+
return mutateOperations(
|
|
282
|
+
request,
|
|
283
|
+
`/operations/project-cost-categories/${id}`,
|
|
284
|
+
'PATCH',
|
|
285
|
+
data
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function deleteProjectCostCategory(request: RequestFn, id: number) {
|
|
290
|
+
return mutateOperations(
|
|
291
|
+
request,
|
|
292
|
+
`/operations/project-cost-categories/${id}`,
|
|
293
|
+
'DELETE'
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// ─── Project Cost Types ───────────────────────────────────────────────────────
|
|
298
|
+
|
|
299
|
+
export function listProjectCostTypes(
|
|
300
|
+
request: RequestFn,
|
|
301
|
+
params?: Record<string, string>
|
|
302
|
+
) {
|
|
303
|
+
const qs = params ? new URLSearchParams(params).toString() : '';
|
|
304
|
+
return fetchOperations(
|
|
305
|
+
request,
|
|
306
|
+
qs
|
|
307
|
+
? `/operations/project-cost-types?${qs}`
|
|
308
|
+
: '/operations/project-cost-types'
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
export function createProjectCostType(request: RequestFn, data: unknown) {
|
|
313
|
+
return mutateOperations(
|
|
314
|
+
request,
|
|
315
|
+
'/operations/project-cost-types',
|
|
316
|
+
'POST',
|
|
317
|
+
data
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export function updateProjectCostType(
|
|
322
|
+
request: RequestFn,
|
|
323
|
+
id: number,
|
|
324
|
+
data: unknown
|
|
325
|
+
) {
|
|
326
|
+
return mutateOperations(
|
|
327
|
+
request,
|
|
328
|
+
`/operations/project-cost-types/${id}`,
|
|
329
|
+
'PATCH',
|
|
330
|
+
data
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export function deleteProjectCostType(request: RequestFn, id: number) {
|
|
335
|
+
return mutateOperations(
|
|
336
|
+
request,
|
|
337
|
+
`/operations/project-cost-types/${id}`,
|
|
338
|
+
'DELETE'
|
|
339
|
+
);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// ─── Project Costs ────────────────────────────────────────────────────────────
|
|
343
|
+
|
|
344
|
+
export function listProjectCosts(
|
|
345
|
+
request: RequestFn,
|
|
346
|
+
projectId: number,
|
|
347
|
+
params?: Record<string, string>
|
|
348
|
+
) {
|
|
349
|
+
const qs = params ? new URLSearchParams(params).toString() : '';
|
|
350
|
+
return fetchOperations(
|
|
351
|
+
request,
|
|
352
|
+
qs
|
|
353
|
+
? `/operations/projects/${projectId}/costs?${qs}`
|
|
354
|
+
: `/operations/projects/${projectId}/costs`
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export function getProjectCostsSummary(request: RequestFn, projectId: number) {
|
|
359
|
+
return fetchOperations(
|
|
360
|
+
request,
|
|
361
|
+
`/operations/projects/${projectId}/costs/summary`
|
|
362
|
+
);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
export function getFullProjectCostSummary(
|
|
366
|
+
request: RequestFn,
|
|
367
|
+
projectId: number
|
|
368
|
+
) {
|
|
369
|
+
return fetchOperations(
|
|
370
|
+
request,
|
|
371
|
+
`/operations/projects/${projectId}/cost-summary`
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function createProjectCost(
|
|
376
|
+
request: RequestFn,
|
|
377
|
+
projectId: number,
|
|
378
|
+
data: unknown
|
|
379
|
+
) {
|
|
380
|
+
return mutateOperations(
|
|
381
|
+
request,
|
|
382
|
+
`/operations/projects/${projectId}/costs`,
|
|
383
|
+
'POST',
|
|
384
|
+
data
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export function updateProjectCost(
|
|
389
|
+
request: RequestFn,
|
|
390
|
+
projectId: number,
|
|
391
|
+
costId: number,
|
|
392
|
+
data: unknown
|
|
393
|
+
) {
|
|
394
|
+
return mutateOperations(
|
|
395
|
+
request,
|
|
396
|
+
`/operations/projects/${projectId}/costs/${costId}`,
|
|
397
|
+
'PATCH',
|
|
398
|
+
data
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
export function deleteProjectCost(
|
|
403
|
+
request: RequestFn,
|
|
404
|
+
projectId: number,
|
|
405
|
+
costId: number
|
|
406
|
+
) {
|
|
407
|
+
return mutateOperations(
|
|
408
|
+
request,
|
|
409
|
+
`/operations/projects/${projectId}/costs/${costId}`,
|
|
410
|
+
'DELETE'
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export function getProjectCostReport(
|
|
415
|
+
request: RequestFn,
|
|
416
|
+
projectId: number,
|
|
417
|
+
filters?: Record<string, unknown>
|
|
418
|
+
) {
|
|
419
|
+
const params = filters
|
|
420
|
+
? '?' +
|
|
421
|
+
new URLSearchParams(
|
|
422
|
+
Object.entries(filters)
|
|
423
|
+
.filter(([, v]) => v !== undefined && v !== null)
|
|
424
|
+
.map(([k, v]) => [k, String(v)])
|
|
425
|
+
).toString()
|
|
426
|
+
: '';
|
|
427
|
+
return fetchOperations(
|
|
428
|
+
request,
|
|
429
|
+
`/operations/projects/${projectId}/costs/report${params}`
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// ─── Task Comments ────────────────────────────────────────────────────────────
|
|
434
|
+
|
|
435
|
+
export function fetchTaskActivities(request: RequestFn, taskId: number) {
|
|
436
|
+
return fetchOperations(request, `/operations/tasks/${taskId}/activities`);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export function fetchTaskComments(request: RequestFn, taskId: number) {
|
|
440
|
+
return fetchOperations(request, `/operations/tasks/${taskId}/comments`);
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export function createTaskComment(
|
|
444
|
+
request: RequestFn,
|
|
445
|
+
taskId: number,
|
|
446
|
+
content: string
|
|
447
|
+
) {
|
|
448
|
+
return mutateOperations(
|
|
449
|
+
request,
|
|
450
|
+
`/operations/tasks/${taskId}/comments`,
|
|
451
|
+
'POST',
|
|
452
|
+
{ content }
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
export function updateTaskComment(
|
|
457
|
+
request: RequestFn,
|
|
458
|
+
taskId: number,
|
|
459
|
+
commentId: number,
|
|
460
|
+
content: string
|
|
461
|
+
) {
|
|
462
|
+
return mutateOperations(
|
|
463
|
+
request,
|
|
464
|
+
`/operations/tasks/${taskId}/comments/${commentId}`,
|
|
465
|
+
'PATCH',
|
|
466
|
+
{ content }
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
export function deleteTaskComment(
|
|
471
|
+
request: RequestFn,
|
|
472
|
+
taskId: number,
|
|
473
|
+
commentId: number
|
|
474
|
+
) {
|
|
475
|
+
return mutateOperations(
|
|
476
|
+
request,
|
|
477
|
+
`/operations/tasks/${taskId}/comments/${commentId}`,
|
|
478
|
+
'DELETE'
|
|
479
|
+
);
|
|
480
|
+
}
|