feat(finance): implement project finance and rate card management features

- Added new controllers for managing project finance and rate cards, including CRUD operations for rate card roles and project finance tasks.
- Introduced API routes for project finance and rate card functionalities, enhancing the backend structure.
- Developed frontend components for displaying and managing project finance data, including a finance drawer and rate card settings.
- Enhanced localization files to support new UI elements and ensure consistency across multiple languages.
- Implemented utility functions for handling man-days and financial calculations, improving overall functionality.
This commit is contained in:
chamikaJ
2025-07-24 15:23:34 +05:30
parent 4b54f2cc17
commit 4ffc3465e3
51 changed files with 10202 additions and 169 deletions

View File

@@ -0,0 +1,133 @@
import { API_BASE_URL } from '@/shared/constants';
import { IServerResponse } from '@/types/common.types';
import apiClient from '../api-client';
import {
IProjectFinanceResponse,
ITaskBreakdownResponse,
IProjectFinanceTask,
} from '@/types/project/project-finance.types';
const rootUrl = `${API_BASE_URL}/project-finance`;
type BillableFilterType = 'all' | 'billable' | 'non-billable';
export const projectFinanceApiService = {
getProjectTasks: async (
projectId: string,
groupBy: 'status' | 'priority' | 'phases' = 'status',
billableFilter: BillableFilterType = 'billable'
): Promise<IServerResponse<IProjectFinanceResponse>> => {
const response = await apiClient.get<IServerResponse<IProjectFinanceResponse>>(
`${rootUrl}/project/${projectId}/tasks`,
{
params: {
group_by: groupBy,
billable_filter: billableFilter,
},
}
);
return response.data;
},
getSubTasks: async (
projectId: string,
parentTaskId: string,
billableFilter: BillableFilterType = 'billable'
): Promise<IServerResponse<IProjectFinanceTask[]>> => {
const response = await apiClient.get<IServerResponse<IProjectFinanceTask[]>>(
`${rootUrl}/project/${projectId}/tasks/${parentTaskId}/subtasks`,
{
params: {
billable_filter: billableFilter,
},
}
);
return response.data;
},
getTaskBreakdown: async (taskId: string): Promise<IServerResponse<ITaskBreakdownResponse>> => {
const response = await apiClient.get<IServerResponse<ITaskBreakdownResponse>>(
`${rootUrl}/task/${taskId}/breakdown`
);
return response.data;
},
updateTaskFixedCost: async (taskId: string, fixedCost: number): Promise<IServerResponse<any>> => {
const response = await apiClient.put<IServerResponse<any>>(
`${rootUrl}/task/${taskId}/fixed-cost`,
{ fixed_cost: fixedCost }
);
return response.data;
},
updateProjectCurrency: async (
projectId: string,
currency: string
): Promise<IServerResponse<any>> => {
const response = await apiClient.put<IServerResponse<any>>(
`${rootUrl}/project/${projectId}/currency`,
{ currency }
);
return response.data;
},
updateProjectBudget: async (projectId: string, budget: number): Promise<IServerResponse<any>> => {
const response = await apiClient.put<IServerResponse<any>>(
`${rootUrl}/project/${projectId}/budget`,
{ budget }
);
return response.data;
},
updateProjectCalculationMethod: async (
projectId: string,
calculationMethod: 'hourly' | 'man_days',
hoursPerDay?: number
): Promise<IServerResponse<any>> => {
const response = await apiClient.put<IServerResponse<any>>(
`${rootUrl}/project/${projectId}/calculation-method`,
{
calculation_method: calculationMethod,
hours_per_day: hoursPerDay,
}
);
return response.data;
},
updateTaskEstimatedManDays: async (
taskId: string,
estimatedManDays: number
): Promise<IServerResponse<any>> => {
const response = await apiClient.put<IServerResponse<any>>(
`${rootUrl}/task/${taskId}/estimated-man-days`,
{ estimated_man_days: estimatedManDays }
);
return response.data;
},
updateRateCardManDayRate: async (
rateCardRoleId: string,
manDayRate: number
): Promise<IServerResponse<any>> => {
const response = await apiClient.put<IServerResponse<any>>(
`${rootUrl}/rate-card-role/${rateCardRoleId}/man-day-rate`,
{ man_day_rate: manDayRate }
);
return response.data;
},
exportFinanceData: async (
projectId: string,
groupBy: 'status' | 'priority' | 'phases' = 'status',
billableFilter: BillableFilterType = 'billable'
): Promise<Blob> => {
const response = await apiClient.get(`${rootUrl}/project/${projectId}/export`, {
params: {
groupBy,
billable_filter: billableFilter,
},
responseType: 'blob',
});
return response.data;
},
};