@hed-hog/operations 0.0.329 → 0.0.330
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/controllers/operations-tasks.controller.d.ts +4 -4
- package/dist/operations.service.d.ts +4 -4
- package/dist/operations.service.d.ts.map +1 -1
- package/dist/operations.service.js +24 -4
- package/dist/operations.service.js.map +1 -1
- package/dist/operations.service.spec.js +1 -1
- package/dist/operations.service.spec.js.map +1 -1
- package/hedhog/data/dashboard_component_role.yaml +8 -8
- package/hedhog/data/dashboard_role.yaml +1 -1
- package/hedhog/data/menu.yaml +6 -16
- package/hedhog/data/role.yaml +1 -1
- package/hedhog/data/route.yaml +55 -55
- package/hedhog/frontend/app/_components/async-options-combobox.tsx.ejs +15 -9
- package/hedhog/frontend/app/_components/project-costs-section.tsx.ejs +51 -81
- package/hedhog/frontend/app/_components/project-details-screen.tsx.ejs +39 -11
- package/hedhog/frontend/app/_components/project-form-screen.tsx.ejs +21 -4
- package/hedhog/frontend/app/_components/task-file-attachments.tsx.ejs +10 -8
- package/hedhog/frontend/app/_lib/hooks/use-values-visibility.ts.ejs +61 -0
- package/hedhog/frontend/app/approvals/page.tsx.ejs +5 -1
- package/hedhog/frontend/app/collaborators/page.tsx.ejs +68 -34
- package/hedhog/frontend/app/my-projects/page.tsx.ejs +45 -6
- package/hedhog/frontend/app/my-tasks/page.tsx.ejs +1 -1
- package/hedhog/frontend/app/projects/page.tsx.ejs +60 -5
- package/hedhog/frontend/app/reports/collaborators/page.tsx.ejs +65 -52
- package/hedhog/frontend/app/reports/projects/page.tsx.ejs +80 -82
- package/hedhog/frontend/app/schedule-adjustments/page.tsx.ejs +7 -1
- package/hedhog/frontend/messages/en.json +223 -16
- package/hedhog/frontend/messages/pt.json +223 -16
- package/package.json +4 -4
- package/src/operations.service.spec.ts +1 -1
- package/src/operations.service.ts +25 -5
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
"manageDepartments": "Manage departments",
|
|
23
23
|
"manageCollaboratorTypes": "Manage relationship types",
|
|
24
24
|
"manageTemplates": "Manage templates",
|
|
25
|
-
"useTemplate": "Use template"
|
|
25
|
+
"useTemplate": "Use template",
|
|
26
|
+
"showValues": "Show values",
|
|
27
|
+
"hideValues": "Hide values"
|
|
26
28
|
},
|
|
27
29
|
"filters": {
|
|
28
30
|
"allStatuses": "All statuses",
|
|
@@ -110,11 +112,11 @@
|
|
|
110
112
|
"noTemplatesFound": "No templates found.",
|
|
111
113
|
"loading": "Loading..."
|
|
112
114
|
},
|
|
113
|
-
"states": {
|
|
114
|
-
"loading": "Loading...",
|
|
115
|
-
"emptyTitle": "No records found",
|
|
116
|
-
"emptyDescription": "Adjust the current filters or create a new record.",
|
|
117
|
-
"noAccessTitle": "Access required"
|
|
115
|
+
"states": {
|
|
116
|
+
"loading": "Loading...",
|
|
117
|
+
"emptyTitle": "No records found",
|
|
118
|
+
"emptyDescription": "Adjust the current filters or create a new record.",
|
|
119
|
+
"noAccessTitle": "Access required"
|
|
118
120
|
}
|
|
119
121
|
},
|
|
120
122
|
"DashboardPage": {
|
|
@@ -619,6 +621,9 @@
|
|
|
619
621
|
"done": "Done",
|
|
620
622
|
"doneDescription": "Completed tasks."
|
|
621
623
|
},
|
|
624
|
+
"labels": {
|
|
625
|
+
"progress": "Progress"
|
|
626
|
+
},
|
|
622
627
|
"status": {
|
|
623
628
|
"todo": "To do",
|
|
624
629
|
"doing": "In progress",
|
|
@@ -967,7 +972,22 @@
|
|
|
967
972
|
"deleteTitle": "Delete task",
|
|
968
973
|
"deleteDescription": "Are you sure you want to permanently delete this task? This action cannot be undone."
|
|
969
974
|
},
|
|
970
|
-
"emptyArchivedDescription": "There are no archived tasks in this project."
|
|
975
|
+
"emptyArchivedDescription": "There are no archived tasks in this project.",
|
|
976
|
+
"commentsSection": {
|
|
977
|
+
"title": "Comments",
|
|
978
|
+
"noComments": "No comments yet.",
|
|
979
|
+
"defaultUser": "Unknown user",
|
|
980
|
+
"ariaEditComment": "Edit comment",
|
|
981
|
+
"ariaDeleteComment": "Delete comment",
|
|
982
|
+
"saveButton": "Save",
|
|
983
|
+
"cancelButton": "Cancel",
|
|
984
|
+
"submitButton": "Add comment",
|
|
985
|
+
"errors": {
|
|
986
|
+
"addComment": "Unable to add the comment.",
|
|
987
|
+
"editComment": "Unable to update the comment.",
|
|
988
|
+
"deleteComment": "Unable to delete the comment."
|
|
989
|
+
}
|
|
990
|
+
}
|
|
971
991
|
},
|
|
972
992
|
"ContractsPage": {
|
|
973
993
|
"title": "Contracts",
|
|
@@ -1989,15 +2009,15 @@
|
|
|
1989
2009
|
"category": "Category",
|
|
1990
2010
|
"billable": "Billable",
|
|
1991
2011
|
"reimbursable": "Reimbursable",
|
|
1992
|
-
"all": "All",
|
|
1993
|
-
"yes": "Yes",
|
|
1994
|
-
"no": "No",
|
|
1995
|
-
"planned": "Planned",
|
|
1996
|
-
"realized": "Realized",
|
|
1997
|
-
"statuses": {
|
|
1998
|
-
"planned": "Planned",
|
|
1999
|
-
"approved": "Approved",
|
|
2000
|
-
"realized": "Realized",
|
|
2012
|
+
"all": "All",
|
|
2013
|
+
"yes": "Yes",
|
|
2014
|
+
"no": "No",
|
|
2015
|
+
"planned": "Planned",
|
|
2016
|
+
"realized": "Realized",
|
|
2017
|
+
"statuses": {
|
|
2018
|
+
"planned": "Planned",
|
|
2019
|
+
"approved": "Approved",
|
|
2020
|
+
"realized": "Realized",
|
|
2001
2021
|
"cancelled": "Cancelled"
|
|
2002
2022
|
},
|
|
2003
2023
|
"colDate": "Date",
|
|
@@ -2125,5 +2145,192 @@
|
|
|
2125
2145
|
"statusBreakdown": "Planned × Approved × Realized",
|
|
2126
2146
|
"noData": "Not enough data"
|
|
2127
2147
|
}
|
|
2148
|
+
},
|
|
2149
|
+
"TaskFileAttachments": {
|
|
2150
|
+
"uploadError": "Upload error",
|
|
2151
|
+
"error": "Error",
|
|
2152
|
+
"empty": "No attached files",
|
|
2153
|
+
"dropzone": {
|
|
2154
|
+
"ariaLabel": "Click or drop files to attach",
|
|
2155
|
+
"dragging": "Drop files here",
|
|
2156
|
+
"idle": "Click or drag files to attach"
|
|
2157
|
+
},
|
|
2158
|
+
"actions": {
|
|
2159
|
+
"openInNewTab": "Open in a new tab",
|
|
2160
|
+
"removeFile": "Remove file"
|
|
2161
|
+
}
|
|
2162
|
+
},
|
|
2163
|
+
"ReportsCollaboratorsPage": {
|
|
2164
|
+
"title": "Collaborators Report",
|
|
2165
|
+
"description": "Executive dashboard with costs, profit, current capacity, and planning for the next 12 months.",
|
|
2166
|
+
"breadcrumb": "Reports / Collaborators",
|
|
2167
|
+
"actions": {
|
|
2168
|
+
"clear": "Clear"
|
|
2169
|
+
},
|
|
2170
|
+
"filters": {
|
|
2171
|
+
"start": "Start",
|
|
2172
|
+
"end": "End",
|
|
2173
|
+
"department": "Department",
|
|
2174
|
+
"contract": "Contract",
|
|
2175
|
+
"scenario": "Scenario",
|
|
2176
|
+
"all": "All"
|
|
2177
|
+
},
|
|
2178
|
+
"scenario": {
|
|
2179
|
+
"base": "Base",
|
|
2180
|
+
"growth": "Growth",
|
|
2181
|
+
"conservative": "Conservative"
|
|
2182
|
+
},
|
|
2183
|
+
"allocationStatus": {
|
|
2184
|
+
"overload": "Overloaded",
|
|
2185
|
+
"idle": "Idle",
|
|
2186
|
+
"healthy": "Healthy"
|
|
2187
|
+
},
|
|
2188
|
+
"cards": {
|
|
2189
|
+
"headcount": {
|
|
2190
|
+
"title": "Headcount",
|
|
2191
|
+
"description": "Collaborators in scope"
|
|
2192
|
+
},
|
|
2193
|
+
"cost": {
|
|
2194
|
+
"title": "Total cost",
|
|
2195
|
+
"perAllocatedHour": "per allocated hour",
|
|
2196
|
+
"perCapacityHour": "per capacity hour"
|
|
2197
|
+
},
|
|
2198
|
+
"revenue": {
|
|
2199
|
+
"title": "Generated value",
|
|
2200
|
+
"description": "{hours} billable"
|
|
2201
|
+
},
|
|
2202
|
+
"margin": {
|
|
2203
|
+
"title": "Margin"
|
|
2204
|
+
},
|
|
2205
|
+
"utilization": {
|
|
2206
|
+
"title": "Utilization",
|
|
2207
|
+
"description": "Committed billable hours over total capacity"
|
|
2208
|
+
},
|
|
2209
|
+
"freeCapacity": {
|
|
2210
|
+
"title": "Free capacity",
|
|
2211
|
+
"description": "{percent} available"
|
|
2212
|
+
},
|
|
2213
|
+
"overtime": {
|
|
2214
|
+
"title": "Overtime",
|
|
2215
|
+
"description": "{count} people overloaded"
|
|
2216
|
+
},
|
|
2217
|
+
"scenario": {
|
|
2218
|
+
"title": "12-month scenario",
|
|
2219
|
+
"description": "Projection calculated by the backend"
|
|
2220
|
+
}
|
|
2221
|
+
},
|
|
2222
|
+
"table": {
|
|
2223
|
+
"title": "Collaborator breakdown",
|
|
2224
|
+
"description": "Fixed cost in period, generated value, profit, committed capacity, and executive recommendation.",
|
|
2225
|
+
"hoursBillableOf": "{billable} bill. of {allocated}",
|
|
2226
|
+
"headers": {
|
|
2227
|
+
"collaborator": "Collaborator",
|
|
2228
|
+
"cost": "Cost",
|
|
2229
|
+
"generatedValue": "Generated value",
|
|
2230
|
+
"profit": "Profit",
|
|
2231
|
+
"hours": "Hours",
|
|
2232
|
+
"allocation": "Allocation",
|
|
2233
|
+
"risk": "Risk",
|
|
2234
|
+
"recommendation": "Recommendation"
|
|
2235
|
+
}
|
|
2236
|
+
}
|
|
2237
|
+
},
|
|
2238
|
+
"ReportsProjectsPage": {
|
|
2239
|
+
"title": "Projects Report",
|
|
2240
|
+
"description": "Executive dashboard with revenue, cost, profit, deadlines, risk, and planning for the next 12 months.",
|
|
2241
|
+
"breadcrumb": "Reports / Projects",
|
|
2242
|
+
"filters": {
|
|
2243
|
+
"start": "Start",
|
|
2244
|
+
"end": "End",
|
|
2245
|
+
"status": "Status",
|
|
2246
|
+
"client": "Client",
|
|
2247
|
+
"scenario": "Scenario",
|
|
2248
|
+
"all": "All"
|
|
2249
|
+
},
|
|
2250
|
+
"scenario": {
|
|
2251
|
+
"base": "Base",
|
|
2252
|
+
"growth": "Growth",
|
|
2253
|
+
"conservative": "Conservative"
|
|
2254
|
+
},
|
|
2255
|
+
"status": {
|
|
2256
|
+
"on_track": "On track",
|
|
2257
|
+
"attention": "Attention",
|
|
2258
|
+
"late": "Late",
|
|
2259
|
+
"paused": "Paused"
|
|
2260
|
+
},
|
|
2261
|
+
"contractType": {
|
|
2262
|
+
"fixed_price": "Fixed price",
|
|
2263
|
+
"time_materials": "Time / materials",
|
|
2264
|
+
"retainer": "Retainer"
|
|
2265
|
+
},
|
|
2266
|
+
"risk": {
|
|
2267
|
+
"baixo": "low",
|
|
2268
|
+
"médio": "medium",
|
|
2269
|
+
"alto": "high"
|
|
2270
|
+
},
|
|
2271
|
+
"actions": {
|
|
2272
|
+
"clear": "Clear",
|
|
2273
|
+
"viewDetails": "View details"
|
|
2274
|
+
},
|
|
2275
|
+
"cards": {
|
|
2276
|
+
"projects": {
|
|
2277
|
+
"title": "Projects",
|
|
2278
|
+
"tooltip": "Total number of active projects in the filtered period, including those under operational risk.",
|
|
2279
|
+
"description": "{count} under operational risk"
|
|
2280
|
+
},
|
|
2281
|
+
"budget": {
|
|
2282
|
+
"title": "Budget",
|
|
2283
|
+
"tooltip": "Sum of budget_amount across all projects in the filtered period.",
|
|
2284
|
+
"description": "{count} projects in the period"
|
|
2285
|
+
},
|
|
2286
|
+
"allocatedCost": {
|
|
2287
|
+
"title": "Allocated cost",
|
|
2288
|
+
"tooltip": "Cost calculated from allocations: planned weekly hours × collaborator monthly cost × months in period ÷ weekly capacity.",
|
|
2289
|
+
"description": "vs {value} consumed"
|
|
2290
|
+
},
|
|
2291
|
+
"plannedProfit": {
|
|
2292
|
+
"title": "Planned profit",
|
|
2293
|
+
"tooltip": "Difference between total project budget and allocated collaborator cost in the period.",
|
|
2294
|
+
"description": "{value} margin"
|
|
2295
|
+
},
|
|
2296
|
+
"hours": {
|
|
2297
|
+
"title": "Consumed hours",
|
|
2298
|
+
"tooltip": "Total logged and approved timesheet hours within the selected period.",
|
|
2299
|
+
"description": "{value} billable"
|
|
2300
|
+
},
|
|
2301
|
+
"consumedHoursCost": {
|
|
2302
|
+
"title": "Consumed hours cost",
|
|
2303
|
+
"tooltip": "Actual cost of delivered hours: timesheet hours × collaborator hourly rate (monthly cost ÷ weekly capacity).",
|
|
2304
|
+
"description": "{value} of delivered hours"
|
|
2305
|
+
},
|
|
2306
|
+
"idlenessRate": {
|
|
2307
|
+
"title": "Idleness rate",
|
|
2308
|
+
"tooltip": "Percentage of idle time: gap between planned weekly allocation and hours actually submitted in timesheets, relative to total capacity.",
|
|
2309
|
+
"description": "{value} idle cost"
|
|
2310
|
+
},
|
|
2311
|
+
"idlenessCost": {
|
|
2312
|
+
"title": "Idleness cost",
|
|
2313
|
+
"tooltip": "Amount spent on idle time: allocated cost minus cost of hours effectively consumed in approved timesheets.",
|
|
2314
|
+
"description": "{value} idleness"
|
|
2315
|
+
}
|
|
2316
|
+
},
|
|
2317
|
+
"table": {
|
|
2318
|
+
"title": "Project breakdown",
|
|
2319
|
+
"description": "Budget, allocated cost, planned profit, consumed hours, idleness, and risk by project.",
|
|
2320
|
+
"billableHours": "{value} billable",
|
|
2321
|
+
"columns": {
|
|
2322
|
+
"project": "Project",
|
|
2323
|
+
"status": "Status",
|
|
2324
|
+
"budget": "Budget",
|
|
2325
|
+
"allocatedCost": "Allocated cost",
|
|
2326
|
+
"plannedProfit": "Planned profit",
|
|
2327
|
+
"hours": "Consumed hours",
|
|
2328
|
+
"consumedHoursCost": "Consumed hours cost",
|
|
2329
|
+
"idlenessRate": "Idleness rate",
|
|
2330
|
+
"idlenessCost": "Idleness cost",
|
|
2331
|
+
"risk": "Risk",
|
|
2332
|
+
"recommendation": "Recommendation"
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2128
2335
|
}
|
|
2129
2336
|
}
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
"manageDepartments": "Gerenciar departamentos",
|
|
23
23
|
"manageCollaboratorTypes": "Gerenciar tipos de colaborador",
|
|
24
24
|
"manageTemplates": "Gerenciar templates",
|
|
25
|
-
"useTemplate": "Usar template"
|
|
25
|
+
"useTemplate": "Usar template",
|
|
26
|
+
"showValues": "Exibir valores",
|
|
27
|
+
"hideValues": "Ocultar valores"
|
|
26
28
|
},
|
|
27
29
|
"filters": {
|
|
28
30
|
"allStatuses": "Todos os status",
|
|
@@ -108,11 +110,11 @@
|
|
|
108
110
|
"noTemplatesFound": "Nenhum template encontrado.",
|
|
109
111
|
"loading": "Carregando..."
|
|
110
112
|
},
|
|
111
|
-
"states": {
|
|
112
|
-
"loading": "Carregando...",
|
|
113
|
-
"emptyTitle": "Nenhum registro encontrado",
|
|
114
|
-
"emptyDescription": "Ajuste os filtros atuais ou crie um novo registro.",
|
|
115
|
-
"noAccessTitle": "Acesso necessário"
|
|
113
|
+
"states": {
|
|
114
|
+
"loading": "Carregando...",
|
|
115
|
+
"emptyTitle": "Nenhum registro encontrado",
|
|
116
|
+
"emptyDescription": "Ajuste os filtros atuais ou crie um novo registro.",
|
|
117
|
+
"noAccessTitle": "Acesso necessário"
|
|
116
118
|
}
|
|
117
119
|
},
|
|
118
120
|
"DashboardPage": {
|
|
@@ -617,6 +619,9 @@
|
|
|
617
619
|
"done": "Concluídas",
|
|
618
620
|
"doneDescription": "Tarefas finalizadas."
|
|
619
621
|
},
|
|
622
|
+
"labels": {
|
|
623
|
+
"progress": "Progresso"
|
|
624
|
+
},
|
|
620
625
|
"status": {
|
|
621
626
|
"todo": "A fazer",
|
|
622
627
|
"doing": "Em andamento",
|
|
@@ -965,7 +970,22 @@
|
|
|
965
970
|
"deleteTitle": "Excluir tarefa",
|
|
966
971
|
"deleteDescription": "Tem certeza que deseja excluir esta tarefa de forma permanente? Esta ação não pode ser desfeita."
|
|
967
972
|
},
|
|
968
|
-
"emptyArchivedDescription": "Nenhuma tarefa arquivada neste projeto."
|
|
973
|
+
"emptyArchivedDescription": "Nenhuma tarefa arquivada neste projeto.",
|
|
974
|
+
"commentsSection": {
|
|
975
|
+
"title": "Comentários",
|
|
976
|
+
"noComments": "Nenhum comentário ainda.",
|
|
977
|
+
"defaultUser": "Usuário desconhecido",
|
|
978
|
+
"ariaEditComment": "Editar comentário",
|
|
979
|
+
"ariaDeleteComment": "Excluir comentário",
|
|
980
|
+
"saveButton": "Salvar",
|
|
981
|
+
"cancelButton": "Cancelar",
|
|
982
|
+
"submitButton": "Adicionar comentário",
|
|
983
|
+
"errors": {
|
|
984
|
+
"addComment": "Não foi possível adicionar o comentário.",
|
|
985
|
+
"editComment": "Não foi possível atualizar o comentário.",
|
|
986
|
+
"deleteComment": "Não foi possível excluir o comentário."
|
|
987
|
+
}
|
|
988
|
+
}
|
|
969
989
|
},
|
|
970
990
|
"ContractsPage": {
|
|
971
991
|
"title": "Contratos",
|
|
@@ -1996,15 +2016,15 @@
|
|
|
1996
2016
|
"category": "Categoria",
|
|
1997
2017
|
"billable": "Faturável",
|
|
1998
2018
|
"reimbursable": "Reembolsável",
|
|
1999
|
-
"all": "Todos",
|
|
2000
|
-
"yes": "Sim",
|
|
2001
|
-
"no": "Não",
|
|
2002
|
-
"planned": "Planejado",
|
|
2003
|
-
"realized": "Realizado",
|
|
2004
|
-
"statuses": {
|
|
2005
|
-
"planned": "Planejado",
|
|
2006
|
-
"approved": "Aprovado",
|
|
2007
|
-
"realized": "Realizado",
|
|
2019
|
+
"all": "Todos",
|
|
2020
|
+
"yes": "Sim",
|
|
2021
|
+
"no": "Não",
|
|
2022
|
+
"planned": "Planejado",
|
|
2023
|
+
"realized": "Realizado",
|
|
2024
|
+
"statuses": {
|
|
2025
|
+
"planned": "Planejado",
|
|
2026
|
+
"approved": "Aprovado",
|
|
2027
|
+
"realized": "Realizado",
|
|
2008
2028
|
"cancelled": "Cancelado"
|
|
2009
2029
|
},
|
|
2010
2030
|
"colDate": "Data",
|
|
@@ -2132,5 +2152,192 @@
|
|
|
2132
2152
|
"statusBreakdown": "Planejado × Aprovado × Realizado",
|
|
2133
2153
|
"noData": "Sem dados suficientes"
|
|
2134
2154
|
}
|
|
2155
|
+
},
|
|
2156
|
+
"TaskFileAttachments": {
|
|
2157
|
+
"uploadError": "Erro no upload",
|
|
2158
|
+
"error": "Erro",
|
|
2159
|
+
"empty": "Nenhum arquivo anexado",
|
|
2160
|
+
"dropzone": {
|
|
2161
|
+
"ariaLabel": "Clique ou solte arquivos para anexar",
|
|
2162
|
+
"dragging": "Solte os arquivos aqui",
|
|
2163
|
+
"idle": "Clique ou arraste arquivos para anexar"
|
|
2164
|
+
},
|
|
2165
|
+
"actions": {
|
|
2166
|
+
"openInNewTab": "Abrir em nova aba",
|
|
2167
|
+
"removeFile": "Remover arquivo"
|
|
2168
|
+
}
|
|
2169
|
+
},
|
|
2170
|
+
"ReportsCollaboratorsPage": {
|
|
2171
|
+
"title": "Relatório de Colaboradores",
|
|
2172
|
+
"description": "Dashboard executivo com custo, lucro, capacidade atual e planejamento dos próximos 12 meses.",
|
|
2173
|
+
"breadcrumb": "Relatórios / Colaboradores",
|
|
2174
|
+
"actions": {
|
|
2175
|
+
"clear": "Limpar"
|
|
2176
|
+
},
|
|
2177
|
+
"filters": {
|
|
2178
|
+
"start": "Início",
|
|
2179
|
+
"end": "Fim",
|
|
2180
|
+
"department": "Departamento",
|
|
2181
|
+
"contract": "Vínculo",
|
|
2182
|
+
"scenario": "Cenário",
|
|
2183
|
+
"all": "Todos"
|
|
2184
|
+
},
|
|
2185
|
+
"scenario": {
|
|
2186
|
+
"base": "Base",
|
|
2187
|
+
"growth": "Crescimento",
|
|
2188
|
+
"conservative": "Conservador"
|
|
2189
|
+
},
|
|
2190
|
+
"allocationStatus": {
|
|
2191
|
+
"overload": "Sobrecarga",
|
|
2192
|
+
"idle": "Ocioso",
|
|
2193
|
+
"healthy": "Saudável"
|
|
2194
|
+
},
|
|
2195
|
+
"cards": {
|
|
2196
|
+
"headcount": {
|
|
2197
|
+
"title": "Headcount",
|
|
2198
|
+
"description": "Colaboradores no recorte"
|
|
2199
|
+
},
|
|
2200
|
+
"cost": {
|
|
2201
|
+
"title": "Custo total",
|
|
2202
|
+
"perAllocatedHour": "por hora alocada",
|
|
2203
|
+
"perCapacityHour": "por hora de capacidade"
|
|
2204
|
+
},
|
|
2205
|
+
"revenue": {
|
|
2206
|
+
"title": "Valor gerado",
|
|
2207
|
+
"description": "{hours} faturáveis"
|
|
2208
|
+
},
|
|
2209
|
+
"margin": {
|
|
2210
|
+
"title": "Margem"
|
|
2211
|
+
},
|
|
2212
|
+
"utilization": {
|
|
2213
|
+
"title": "Utilização",
|
|
2214
|
+
"description": "Horas faturáveis comprometidas sobre capacidade"
|
|
2215
|
+
},
|
|
2216
|
+
"freeCapacity": {
|
|
2217
|
+
"title": "Capacidade livre",
|
|
2218
|
+
"description": "{percent} disponível"
|
|
2219
|
+
},
|
|
2220
|
+
"overtime": {
|
|
2221
|
+
"title": "Horas extras",
|
|
2222
|
+
"description": "{count} pessoas em sobrecarga"
|
|
2223
|
+
},
|
|
2224
|
+
"scenario": {
|
|
2225
|
+
"title": "Cenário 12 meses",
|
|
2226
|
+
"description": "Projeção calculada no backend"
|
|
2227
|
+
}
|
|
2228
|
+
},
|
|
2229
|
+
"table": {
|
|
2230
|
+
"title": "Detalhamento por colaborador",
|
|
2231
|
+
"description": "Custo fixo do período, valor apontado, lucro, capacidade comprometida e recomendação executiva.",
|
|
2232
|
+
"hoursBillableOf": "{billable} fat. de {allocated}",
|
|
2233
|
+
"headers": {
|
|
2234
|
+
"collaborator": "Colaborador",
|
|
2235
|
+
"cost": "Custo",
|
|
2236
|
+
"generatedValue": "Valor gerado",
|
|
2237
|
+
"profit": "Lucro",
|
|
2238
|
+
"hours": "Horas",
|
|
2239
|
+
"allocation": "Alocação",
|
|
2240
|
+
"risk": "Risco",
|
|
2241
|
+
"recommendation": "Recomendação"
|
|
2242
|
+
}
|
|
2243
|
+
}
|
|
2244
|
+
},
|
|
2245
|
+
"ReportsProjectsPage": {
|
|
2246
|
+
"title": "Relatório de Projetos",
|
|
2247
|
+
"description": "Dashboard executivo com receita, custo, lucro, prazo, risco e planejamento dos próximos 12 meses.",
|
|
2248
|
+
"breadcrumb": "Relatórios / Projetos",
|
|
2249
|
+
"filters": {
|
|
2250
|
+
"start": "Início",
|
|
2251
|
+
"end": "Fim",
|
|
2252
|
+
"status": "Status",
|
|
2253
|
+
"client": "Cliente",
|
|
2254
|
+
"scenario": "Cenário",
|
|
2255
|
+
"all": "Todos"
|
|
2256
|
+
},
|
|
2257
|
+
"scenario": {
|
|
2258
|
+
"base": "Base",
|
|
2259
|
+
"growth": "Crescimento",
|
|
2260
|
+
"conservative": "Conservador"
|
|
2261
|
+
},
|
|
2262
|
+
"status": {
|
|
2263
|
+
"on_track": "No prazo",
|
|
2264
|
+
"attention": "Atenção",
|
|
2265
|
+
"late": "Atrasado",
|
|
2266
|
+
"paused": "Pausado"
|
|
2267
|
+
},
|
|
2268
|
+
"contractType": {
|
|
2269
|
+
"fixed_price": "Preço fechado",
|
|
2270
|
+
"time_materials": "Hora / Material",
|
|
2271
|
+
"retainer": "Recorrente"
|
|
2272
|
+
},
|
|
2273
|
+
"risk": {
|
|
2274
|
+
"baixo": "baixo",
|
|
2275
|
+
"médio": "médio",
|
|
2276
|
+
"alto": "alto"
|
|
2277
|
+
},
|
|
2278
|
+
"actions": {
|
|
2279
|
+
"clear": "Limpar",
|
|
2280
|
+
"viewDetails": "Ver detalhes"
|
|
2281
|
+
},
|
|
2282
|
+
"cards": {
|
|
2283
|
+
"projects": {
|
|
2284
|
+
"title": "Projetos",
|
|
2285
|
+
"tooltip": "Número total de projetos ativos no período filtrado, incluindo os que estão em risco operacional.",
|
|
2286
|
+
"description": "{count} em risco operacional"
|
|
2287
|
+
},
|
|
2288
|
+
"budget": {
|
|
2289
|
+
"title": "Orçamento",
|
|
2290
|
+
"tooltip": "Soma dos campos de orçamento (budget_amount) de todos os projetos no período filtrado.",
|
|
2291
|
+
"description": "{count} projetos no período"
|
|
2292
|
+
},
|
|
2293
|
+
"allocatedCost": {
|
|
2294
|
+
"title": "Custo alocado",
|
|
2295
|
+
"tooltip": "Custo calculado a partir das alocações: horas semanais planejadas × custo mensal do colaborador × meses do período ÷ capacidade semanal.",
|
|
2296
|
+
"description": "vs {value} consumido"
|
|
2297
|
+
},
|
|
2298
|
+
"plannedProfit": {
|
|
2299
|
+
"title": "Lucro planejado",
|
|
2300
|
+
"tooltip": "Diferença entre o orçamento total dos projetos e o custo alocado dos colaboradores no período.",
|
|
2301
|
+
"description": "{value} de margem"
|
|
2302
|
+
},
|
|
2303
|
+
"hours": {
|
|
2304
|
+
"title": "Horas consumidas",
|
|
2305
|
+
"tooltip": "Total de horas lançadas e aprovadas nos timesheets dentro do período selecionado.",
|
|
2306
|
+
"description": "{value} faturáveis"
|
|
2307
|
+
},
|
|
2308
|
+
"consumedHoursCost": {
|
|
2309
|
+
"title": "Custo das horas consumidas",
|
|
2310
|
+
"tooltip": "Custo real das horas entregues: horas do timesheet × taxa horária do colaborador (custo mensal ÷ capacidade semanal).",
|
|
2311
|
+
"description": "{value} de horas entregues"
|
|
2312
|
+
},
|
|
2313
|
+
"idlenessRate": {
|
|
2314
|
+
"title": "Taxa de ociosidade",
|
|
2315
|
+
"tooltip": "Percentual de tempo ocioso: diferença entre a carga horária semanal planejada (alocada) e as horas efetivamente submetidas via timesheet, em relação à capacidade total.",
|
|
2316
|
+
"description": "{value} de custo ocioso"
|
|
2317
|
+
},
|
|
2318
|
+
"idlenessCost": {
|
|
2319
|
+
"title": "Custo de ociosidade",
|
|
2320
|
+
"tooltip": "Quanto foi gasto com tempo ocioso: custo alocado menos o custo das horas efetivamente consumidas nos timesheets aprovados.",
|
|
2321
|
+
"description": "{value} de ociosidade"
|
|
2322
|
+
}
|
|
2323
|
+
},
|
|
2324
|
+
"table": {
|
|
2325
|
+
"title": "Detalhamento por projeto",
|
|
2326
|
+
"description": "Orçamento, custo alocado, lucro planejado, horas consumidas, ociosidade e risco por projeto.",
|
|
2327
|
+
"billableHours": "{value} faturáveis",
|
|
2328
|
+
"columns": {
|
|
2329
|
+
"project": "Projeto",
|
|
2330
|
+
"status": "Status",
|
|
2331
|
+
"budget": "Orçamento",
|
|
2332
|
+
"allocatedCost": "Custo alocado",
|
|
2333
|
+
"plannedProfit": "Lucro planejado",
|
|
2334
|
+
"hours": "Horas consumidas",
|
|
2335
|
+
"consumedHoursCost": "Custo das horas consumidas",
|
|
2336
|
+
"idlenessRate": "Taxa de ociosidade",
|
|
2337
|
+
"idlenessCost": "Custo de ociosidade",
|
|
2338
|
+
"risk": "Risco",
|
|
2339
|
+
"recommendation": "Recomendação"
|
|
2340
|
+
}
|
|
2341
|
+
}
|
|
2135
2342
|
}
|
|
2136
2343
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hed-hog/operations",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.330",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"dependencies": {
|
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
"@nestjs/core": "^11",
|
|
10
10
|
"@nestjs/jwt": "^11",
|
|
11
11
|
"@nestjs/mapped-types": "*",
|
|
12
|
+
"@hed-hog/api-locale": "0.0.14",
|
|
12
13
|
"@hed-hog/api": "0.0.8",
|
|
13
14
|
"@hed-hog/api-prisma": "0.0.6",
|
|
14
15
|
"@hed-hog/api-pagination": "0.0.7",
|
|
15
|
-
"@hed-hog/
|
|
16
|
-
"@hed-hog/core": "0.0.329",
|
|
16
|
+
"@hed-hog/contact": "0.0.330",
|
|
17
17
|
"@hed-hog/api-types": "0.0.1",
|
|
18
|
-
"@hed-hog/
|
|
18
|
+
"@hed-hog/core": "0.0.330"
|
|
19
19
|
},
|
|
20
20
|
"exports": {
|
|
21
21
|
".": {
|
|
@@ -200,7 +200,7 @@ describe('OperationsService quick-entry timesheets', () => {
|
|
|
200
200
|
|
|
201
201
|
jest.spyOn(service as any, 'getActorContext').mockResolvedValue({
|
|
202
202
|
userId: 15,
|
|
203
|
-
roleSlugs: ['
|
|
203
|
+
roleSlugs: ['operations-collaborator'],
|
|
204
204
|
collaboratorId: 7,
|
|
205
205
|
collaboratorName: 'Taylor Tester',
|
|
206
206
|
isDirector: false,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
} from '@nestjs/common';
|
|
21
21
|
import { OperationsAccessService } from './services/shared/operations-access.service';
|
|
22
22
|
|
|
23
|
-
const COLLABORATOR_ROLE = '
|
|
23
|
+
const COLLABORATOR_ROLE = 'operations-collaborator';
|
|
24
24
|
const SUPERVISOR_ROLE = 'admin-operations-supervisor';
|
|
25
25
|
const DIRECTOR_ROLE = 'admin-operations-director';
|
|
26
26
|
const CONTRACT_CATEGORY_VALUES = [
|
|
@@ -2774,7 +2774,13 @@ export class OperationsService {
|
|
|
2774
2774
|
p.code,
|
|
2775
2775
|
p.name,
|
|
2776
2776
|
p.client_name AS "clientName",
|
|
2777
|
-
|
|
2777
|
+
COALESCE(
|
|
2778
|
+
cp.avatar_id,
|
|
2779
|
+
(SELECT p2.avatar_id FROM person p2
|
|
2780
|
+
WHERE p.client_person_id IS NULL
|
|
2781
|
+
AND LOWER(TRIM(p2.name)) = LOWER(TRIM(p.client_name))
|
|
2782
|
+
LIMIT 1)
|
|
2783
|
+
) AS "clientAvatarId",
|
|
2778
2784
|
p.summary,
|
|
2779
2785
|
p.status,
|
|
2780
2786
|
p.progress_percent AS "progressPercent",
|
|
@@ -3254,7 +3260,7 @@ export class OperationsService {
|
|
|
3254
3260
|
return task;
|
|
3255
3261
|
}
|
|
3256
3262
|
|
|
3257
|
-
async updateTask(userId: number, taskId: number, data: TaskPayload) {
|
|
3263
|
+
async updateTask(userId: number, taskId: number, data: TaskPayload) {
|
|
3258
3264
|
const actor = await this.getActorContext(userId);
|
|
3259
3265
|
if (!actor.isCollaborator && !actor.isDirector && !actor.isSupervisor) {
|
|
3260
3266
|
throw new ForbiddenException(
|
|
@@ -7741,7 +7747,13 @@ export class OperationsService {
|
|
|
7741
7747
|
p.contract_id AS "contractId",
|
|
7742
7748
|
p.manager_collaborator_id AS "managerCollaboratorId",
|
|
7743
7749
|
p.client_person_id AS "clientPersonId",
|
|
7744
|
-
|
|
7750
|
+
COALESCE(
|
|
7751
|
+
client_person.avatar_id,
|
|
7752
|
+
(SELECT p2.avatar_id FROM person p2
|
|
7753
|
+
WHERE p.client_person_id IS NULL
|
|
7754
|
+
AND LOWER(TRIM(p2.name)) = LOWER(TRIM(p.client_name))
|
|
7755
|
+
LIMIT 1)
|
|
7756
|
+
) AS "clientAvatarId",
|
|
7745
7757
|
p.code,
|
|
7746
7758
|
p.name,
|
|
7747
7759
|
p.client_name AS "clientName",
|
|
@@ -11385,6 +11397,13 @@ export class OperationsService {
|
|
|
11385
11397
|
p.code,
|
|
11386
11398
|
p.name,
|
|
11387
11399
|
p.client_name AS "clientName",
|
|
11400
|
+
COALESCE(
|
|
11401
|
+
cp.avatar_id,
|
|
11402
|
+
(SELECT p2.avatar_id FROM person p2
|
|
11403
|
+
WHERE p.client_person_id IS NULL
|
|
11404
|
+
AND LOWER(TRIM(p2.name)) = LOWER(TRIM(p.client_name))
|
|
11405
|
+
LIMIT 1)
|
|
11406
|
+
) AS "clientAvatarId",
|
|
11388
11407
|
p.summary,
|
|
11389
11408
|
p.status,
|
|
11390
11409
|
p.progress_percent AS "progressPercent",
|
|
@@ -11397,12 +11416,13 @@ export class OperationsService {
|
|
|
11397
11416
|
FROM operations_project p
|
|
11398
11417
|
LEFT JOIN operations_contract c ON c.id = p.contract_id
|
|
11399
11418
|
LEFT JOIN operations_collaborator m ON m.id = p.manager_collaborator_id
|
|
11419
|
+
LEFT JOIN person cp ON cp.id = p.client_person_id
|
|
11400
11420
|
LEFT JOIN operations_project_assignment pa
|
|
11401
11421
|
ON pa.project_id = p.id
|
|
11402
11422
|
AND pa.deleted_at IS NULL
|
|
11403
11423
|
AND pa.status IN ('planned', 'active')
|
|
11404
11424
|
WHERE ${whereClause}
|
|
11405
|
-
GROUP BY p.id, c.id, m.id`;
|
|
11425
|
+
GROUP BY p.id, c.id, m.id, cp.id`;
|
|
11406
11426
|
|
|
11407
11427
|
if (!pagination) {
|
|
11408
11428
|
return this.queryRows(`${baseQuery} ORDER BY p.name ASC`, params);
|