diff --git a/docs/swagger/swagger-spec.json b/docs/swagger/swagger-spec.json index 73f1761..2d6d040 100644 --- a/docs/swagger/swagger-spec.json +++ b/docs/swagger/swagger-spec.json @@ -29,6 +29,782 @@ ] } }, + "/timesheets": { + "post": { + "operationId": "TimesheetsController_create", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTimesheetDto" + } + } + } + }, + "responses": { + "201": { + "description": "Timesheet created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TimesheetEntity" + } + } + } + }, + "400": { + "description": "Incomplete task or invalid data" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Create timesheet", + "tags": [ + "Timesheets" + ] + }, + "get": { + "operationId": "TimesheetsController_findAll", + "parameters": [], + "responses": { + "201": { + "description": "List of timesheet found", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TimesheetEntity" + } + } + } + } + }, + "400": { + "description": "List of timesheets not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Find all timesheets", + "tags": [ + "Timesheets" + ] + } + }, + "/timesheets/{id}": { + "get": { + "operationId": "TimesheetsController_findOne", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "201": { + "description": "Timesheet found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TimesheetEntity" + } + } + } + }, + "400": { + "description": "Timesheet not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Find timesheet", + "tags": [ + "Timesheets" + ] + }, + "patch": { + "operationId": "TimesheetsController_update", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateTimesheetDto" + } + } + } + }, + "responses": { + "201": { + "description": "Timesheet updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TimesheetEntity" + } + } + } + }, + "400": { + "description": "Timesheet not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Update timesheet", + "tags": [ + "Timesheets" + ] + }, + "delete": { + "operationId": "TimesheetsController_remove", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "201": { + "description": "Timesheet deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TimesheetEntity" + } + } + } + }, + "400": { + "description": "Timesheet not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Delete timesheet", + "tags": [ + "Timesheets" + ] + } + }, + "/Expenses": { + "post": { + "operationId": "ExpensesController_create", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateExpenseDto" + } + } + } + }, + "responses": { + "201": { + "description": "Expense created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExpenseEntity" + } + } + } + }, + "400": { + "description": "Incomplete task or invalid data" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Create expense", + "tags": [ + "Expenses" + ] + }, + "get": { + "operationId": "ExpensesController_findAll", + "parameters": [], + "responses": { + "201": { + "description": "List of expenses found", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ExpenseEntity" + } + } + } + } + }, + "400": { + "description": "List of expenses not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Find all expenses", + "tags": [ + "Expenses" + ] + } + }, + "/Expenses/{id}": { + "get": { + "operationId": "ExpensesController_findOne", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "201": { + "description": "Expense found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExpenseEntity" + } + } + } + }, + "400": { + "description": "Expense not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Find expense", + "tags": [ + "Expenses" + ] + }, + "patch": { + "operationId": "ExpensesController_update", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateExpenseDto" + } + } + } + }, + "responses": { + "201": { + "description": "Expense updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExpenseEntity" + } + } + } + }, + "400": { + "description": "Expense not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Expense shift", + "tags": [ + "Expenses" + ] + }, + "delete": { + "operationId": "ExpensesController_remove", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "201": { + "description": "Expense deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExpenseEntity" + } + } + } + }, + "400": { + "description": "Expense not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Delete expense", + "tags": [ + "Expenses" + ] + } + }, + "/shifts": { + "post": { + "operationId": "ShiftsController_create", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateShiftDto" + } + } + } + }, + "responses": { + "201": { + "description": "Shift created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ShiftEntity" + } + } + } + }, + "400": { + "description": "Incomplete task or invalid data" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Create shift", + "tags": [ + "Shifts" + ] + }, + "get": { + "operationId": "ShiftsController_findAll", + "parameters": [], + "responses": { + "201": { + "description": "List of shifts found", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ShiftEntity" + } + } + } + } + }, + "400": { + "description": "List of shifts not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Find all shifts", + "tags": [ + "Shifts" + ] + } + }, + "/shifts/{id}": { + "get": { + "operationId": "ShiftsController_findOne", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "201": { + "description": "Shift found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ShiftEntity" + } + } + } + }, + "400": { + "description": "Shift not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Find shift", + "tags": [ + "Shifts" + ] + }, + "patch": { + "operationId": "ShiftsController_update", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateShiftsDto" + } + } + } + }, + "responses": { + "201": { + "description": "Shift updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ShiftEntity" + } + } + } + }, + "400": { + "description": "Shift not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Update shift", + "tags": [ + "Shifts" + ] + }, + "delete": { + "operationId": "ShiftsController_remove", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "201": { + "description": "Shift deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ShiftEntity" + } + } + } + }, + "400": { + "description": "Shift not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Delete shift", + "tags": [ + "Shifts" + ] + } + }, + "/leave-requests": { + "post": { + "operationId": "LeaveRequestController_create", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateLeaveRequestsDto" + } + } + } + }, + "responses": { + "201": { + "description": "Leave request created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LeaveRequestEntity" + } + } + } + }, + "400": { + "description": "Incomplete task or invalid data" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Create leave request", + "tags": [ + "Leave Requests" + ] + }, + "get": { + "operationId": "LeaveRequestController_findAll", + "parameters": [], + "responses": { + "201": { + "description": "List of Leave requests found", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LeaveRequestEntity" + } + } + } + } + }, + "400": { + "description": "List of leave request not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Find all leave request", + "tags": [ + "Leave Requests" + ] + } + }, + "/leave-requests/{id}": { + "get": { + "operationId": "LeaveRequestController_findOne", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "201": { + "description": "Leave request found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LeaveRequestEntity" + } + } + } + }, + "400": { + "description": "Leave request not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Find leave request", + "tags": [ + "Leave Requests" + ] + }, + "patch": { + "operationId": "LeaveRequestController_update", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateLeaveRequestsDto" + } + } + } + }, + "responses": { + "201": { + "description": "Leave request updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LeaveRequestEntity" + } + } + } + }, + "400": { + "description": "Leave request not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Update leave request", + "tags": [ + "Leave Requests" + ] + }, + "delete": { + "operationId": "LeaveRequestController_remove", + "parameters": [ + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "201": { + "description": "Leave request deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LeaveRequestEntity" + } + } + } + }, + "400": { + "description": "Leave request not found" + } + }, + "security": [ + { + "access-token": [] + } + ], + "summary": "Delete leave request", + "tags": [ + "Leave Requests" + ] + } + }, "/oauth-access-tokens": { "post": { "operationId": "OauthAccessTokensController_create", @@ -527,14 +1303,14 @@ ] }, "patch": { - "operationId": "EmployeesController_update", + "operationId": "EmployeesController_updateOrArchiveOrRestore", "parameters": [ { "name": "id", "required": true, "in": "path", "schema": { - "type": "number" + "type": "string" } } ], @@ -549,18 +1325,8 @@ } }, "responses": { - "201": { - "description": "Employee updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/EmployeeEntity" - } - } - } - }, - "400": { - "description": "Employee not found" + "200": { + "description": "" } }, "security": [ @@ -568,7 +1334,6 @@ "access-token": [] } ], - "summary": "Update employee", "tags": [ "Employees" ] @@ -611,394 +1376,6 @@ ] } }, - "/leave-requests": { - "post": { - "operationId": "LeaveRequestController_create", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateLeaveRequestsDto" - } - } - } - }, - "responses": { - "201": { - "description": "Leave request created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LeaveRequestEntity" - } - } - } - }, - "400": { - "description": "Incomplete task or invalid data" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Create leave request", - "tags": [ - "Leave Requests" - ] - }, - "get": { - "operationId": "LeaveRequestController_findAll", - "parameters": [], - "responses": { - "201": { - "description": "List of Leave requests found", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/LeaveRequestEntity" - } - } - } - } - }, - "400": { - "description": "List of leave request not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Find all leave request", - "tags": [ - "Leave Requests" - ] - } - }, - "/leave-requests/{id}": { - "get": { - "operationId": "LeaveRequestController_findOne", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "responses": { - "201": { - "description": "Leave request found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LeaveRequestEntity" - } - } - } - }, - "400": { - "description": "Leave request not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Find leave request", - "tags": [ - "Leave Requests" - ] - }, - "patch": { - "operationId": "LeaveRequestController_update", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateLeaveRequestsDto" - } - } - } - }, - "responses": { - "201": { - "description": "Leave request updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LeaveRequestEntity" - } - } - } - }, - "400": { - "description": "Leave request not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Update leave request", - "tags": [ - "Leave Requests" - ] - }, - "delete": { - "operationId": "LeaveRequestController_remove", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "responses": { - "201": { - "description": "Leave request deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/LeaveRequestEntity" - } - } - } - }, - "400": { - "description": "Leave request not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Delete leave request", - "tags": [ - "Leave Requests" - ] - } - }, - "/Expenses": { - "post": { - "operationId": "ExpensesController_create", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateExpenseDto" - } - } - } - }, - "responses": { - "201": { - "description": "Expense created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExpenseEntity" - } - } - } - }, - "400": { - "description": "Incomplete task or invalid data" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Create expense", - "tags": [ - "Expenses" - ] - }, - "get": { - "operationId": "ExpensesController_findAll", - "parameters": [], - "responses": { - "201": { - "description": "List of expenses found", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ExpenseEntity" - } - } - } - } - }, - "400": { - "description": "List of expenses not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Find all expenses", - "tags": [ - "Expenses" - ] - } - }, - "/Expenses/{id}": { - "get": { - "operationId": "ExpensesController_findOne", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "responses": { - "201": { - "description": "Expense found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExpenseEntity" - } - } - } - }, - "400": { - "description": "Expense not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Find expense", - "tags": [ - "Expenses" - ] - }, - "patch": { - "operationId": "ExpensesController_update", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateExpenseDto" - } - } - } - }, - "responses": { - "201": { - "description": "Expense updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExpenseEntity" - } - } - } - }, - "400": { - "description": "Expense not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Expense shift", - "tags": [ - "Expenses" - ] - }, - "delete": { - "operationId": "ExpensesController_remove", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "responses": { - "201": { - "description": "Expense deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ExpenseEntity" - } - } - } - }, - "400": { - "description": "Expense not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Delete expense", - "tags": [ - "Expenses" - ] - } - }, "/expense-codes": { "post": { "operationId": "ExpenseCodesController_create", @@ -1387,394 +1764,6 @@ ] } }, - "/shifts": { - "post": { - "operationId": "ShiftsController_create", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateShiftDto" - } - } - } - }, - "responses": { - "201": { - "description": "Shift created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ShiftEntity" - } - } - } - }, - "400": { - "description": "Incomplete task or invalid data" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Create shift", - "tags": [ - "Shifts" - ] - }, - "get": { - "operationId": "ShiftsController_findAll", - "parameters": [], - "responses": { - "201": { - "description": "List of shifts found", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ShiftEntity" - } - } - } - } - }, - "400": { - "description": "List of shifts not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Find all shifts", - "tags": [ - "Shifts" - ] - } - }, - "/shifts/{id}": { - "get": { - "operationId": "ShiftsController_findOne", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "responses": { - "201": { - "description": "Shift found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ShiftEntity" - } - } - } - }, - "400": { - "description": "Shift not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Find shift", - "tags": [ - "Shifts" - ] - }, - "patch": { - "operationId": "ShiftsController_update", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateShiftsDto" - } - } - } - }, - "responses": { - "201": { - "description": "Shift updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ShiftEntity" - } - } - } - }, - "400": { - "description": "Shift not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Update shift", - "tags": [ - "Shifts" - ] - }, - "delete": { - "operationId": "ShiftsController_remove", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "responses": { - "201": { - "description": "Shift deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/ShiftEntity" - } - } - } - }, - "400": { - "description": "Shift not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Delete shift", - "tags": [ - "Shifts" - ] - } - }, - "/timesheets": { - "post": { - "operationId": "TimesheetsController_create", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateTimesheetDto" - } - } - } - }, - "responses": { - "201": { - "description": "Timesheet created", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TimesheetEntity" - } - } - } - }, - "400": { - "description": "Incomplete task or invalid data" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Create timesheet", - "tags": [ - "Timesheets" - ] - }, - "get": { - "operationId": "TimesheetsController_findAll", - "parameters": [], - "responses": { - "201": { - "description": "List of timesheet found", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "$ref": "#/components/schemas/TimesheetEntity" - } - } - } - } - }, - "400": { - "description": "List of timesheets not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Find all timesheets", - "tags": [ - "Timesheets" - ] - } - }, - "/timesheets/{id}": { - "get": { - "operationId": "TimesheetsController_findOne", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "responses": { - "201": { - "description": "Timesheet found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TimesheetEntity" - } - } - } - }, - "400": { - "description": "Timesheet not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Find timesheet", - "tags": [ - "Timesheets" - ] - }, - "patch": { - "operationId": "TimesheetsController_update", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpdateTimesheetDto" - } - } - } - }, - "responses": { - "201": { - "description": "Timesheet updated", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TimesheetEntity" - } - } - } - }, - "400": { - "description": "Timesheet not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Update timesheet", - "tags": [ - "Timesheets" - ] - }, - "delete": { - "operationId": "TimesheetsController_remove", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "responses": { - "201": { - "description": "Timesheet deleted", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TimesheetEntity" - } - } - } - }, - "400": { - "description": "Timesheet not found" - } - }, - "security": [ - { - "access-token": [] - } - ], - "summary": "Delete timesheet", - "tags": [ - "Timesheets" - ] - } - }, "/auth/login": { "get": { "operationId": "AuthController_login", @@ -1991,6 +1980,483 @@ } }, "schemas": { + "CreateTimesheetDto": { + "type": "object", + "properties": { + "employee_id": { + "type": "number", + "example": "426433", + "description": "employee`s ID number of linked timsheet" + }, + "is_approved": { + "type": "boolean", + "example": "True or False or Pending or Denied or Cancelled or Escalated", + "description": "Timesheet`s approval status" + } + }, + "required": [ + "employee_id", + "is_approved" + ] + }, + "TimesheetEntity": { + "type": "object", + "properties": { + "id": { + "type": "number", + "example": 1, + "description": "timesheet`s unique ID (auto-generated)" + }, + "employee_id": { + "type": "number", + "example": 426433, + "description": "employee`s ID number of linked timsheet" + }, + "is_approved": { + "type": "boolean", + "example": true, + "description": "Timesheet`s approval status" + } + }, + "required": [ + "id", + "employee_id", + "is_approved" + ] + }, + "UpdateTimesheetDto": { + "type": "object", + "properties": { + "employee_id": { + "type": "number", + "example": "426433", + "description": "employee`s ID number of linked timsheet" + }, + "is_approved": { + "type": "boolean", + "example": "True or False or Pending or Denied or Cancelled or Escalated", + "description": "Timesheet`s approval status" + } + } + }, + "CreateExpenseDto": { + "type": "object", + "properties": { + "timesheet_id": { + "type": "number", + "example": "Th3F3110w5h1pX2024", + "description": "ID number for a set timesheet" + }, + "expense_code_id": { + "type": "number", + "example": "0n3R1n962Ru13xX", + "description": "ID number of an expense code (link with shift-codes)" + }, + "date": { + "format": "date-time", + "type": "string", + "example": "20/10/3018", + "description": "Date where the expense was made" + }, + "amount": { + "type": "number", + "example": "280 000 000,00", + "description": "Amount of the expense" + }, + "description": { + "type": "string", + "example": "Spent for mileage between A and B", + "description": "explain`s why the expense was made" + }, + "is_approved": { + "type": "boolean", + "example": "True or False or Pending or Denied or Cancelled or Escalated", + "description": "Expense`s approval status" + }, + "supervisor_comment": { + "type": "string", + "example": "Asked X to go there as an emergency response", + "description": "Supervisro`s justification for the spending of an employee" + } + }, + "required": [ + "timesheet_id", + "expense_code_id", + "date", + "amount", + "description", + "is_approved", + "supervisor_comment" + ] + }, + "ExpenseEntity": { + "type": "object", + "properties": { + "id": { + "type": "number", + "example": 1, + "description": "Unique ID of the expense (auto-generated)" + }, + "timesheet_id": { + "type": "number", + "example": 101, + "description": "ID number for a set timesheet" + }, + "expense": { + "type": "number", + "example": 7, + "description": "ID number of an expense code (link with expense-codes)" + }, + "date": { + "format": "date-time", + "type": "string", + "example": "3018-10-20T00:00:00.000Z", + "description": "Date where the expense was made" + }, + "is_approuved": { + "type": "boolean", + "example": "DENIED, APPROUVED, PENDING, etc...", + "description": "validation status" + }, + "description": { + "type": "string", + "example": "Spent for mileage between A and B", + "description": "explain`s why the expense was made" + }, + "supervisor_comment": { + "type": "string", + "example": "Asked X to go there as an emergency response", + "description": "Supervisro`s justification for the spending of an employee" + } + }, + "required": [ + "id", + "timesheet_id", + "expense", + "date", + "is_approuved", + "description", + "supervisor_comment" + ] + }, + "UpdateExpenseDto": { + "type": "object", + "properties": { + "timesheet_id": { + "type": "number", + "example": "Th3F3110w5h1pX2024", + "description": "ID number for a set timesheet" + }, + "expense_code_id": { + "type": "number", + "example": "0n3R1n962Ru13xX", + "description": "ID number of an expense code (link with shift-codes)" + }, + "date": { + "format": "date-time", + "type": "string", + "example": "20/10/3018", + "description": "Date where the expense was made" + }, + "amount": { + "type": "number", + "example": "280 000 000,00", + "description": "Amount of the expense" + }, + "description": { + "type": "string", + "example": "Spent for mileage between A and B", + "description": "explain`s why the expense was made" + }, + "is_approved": { + "type": "boolean", + "example": "True or False or Pending or Denied or Cancelled or Escalated", + "description": "Expense`s approval status" + }, + "supervisor_comment": { + "type": "string", + "example": "Asked X to go there as an emergency response", + "description": "Supervisro`s justification for the spending of an employee" + } + } + }, + "CreateShiftDto": { + "type": "object", + "properties": { + "timesheet_id": { + "type": "number", + "example": "Th3F3110w5h1pX2024", + "description": "ID number for a set timesheet" + }, + "shift_code_id": { + "type": "number", + "example": "0n3R1n962Ru13xX", + "description": "ID number of a shift code (link with shift-codes)" + }, + "date": { + "format": "date-time", + "type": "string", + "example": "20/10/3018", + "description": "Date where the shift takes place" + }, + "start_time": { + "format": "date-time", + "type": "string", + "example": "08:00", + "description": "Start time of the said shift" + }, + "end_time": { + "format": "date-time", + "type": "string", + "example": "17:00", + "description": "End time of the said shift" + }, + "description": { + "type": "string", + "example": "Called for an emergency at X` place", + "description": "justify the purpose of the shift" + } + }, + "required": [ + "timesheet_id", + "shift_code_id", + "date", + "start_time", + "end_time", + "description" + ] + }, + "ShiftEntity": { + "type": "object", + "properties": { + "id": { + "type": "number", + "example": 1, + "description": "Unique ID of the shift (auto-generated)" + }, + "timesheet_id": { + "type": "number", + "example": 101, + "description": "ID number for a set timesheet" + }, + "shift_code_id": { + "type": "number", + "example": 7, + "description": "ID number of a shift code (link with shift-codes)" + }, + "date": { + "format": "date-time", + "type": "string", + "example": "3018-10-20T00:00:00.000Z", + "description": "Date where the shift takes place" + }, + "start_time": { + "format": "date-time", + "type": "string", + "example": "3018-10-20T08:00:00.000Z", + "description": "Start time of the said shift" + }, + "end_time": { + "format": "date-time", + "type": "string", + "example": "3018-10-20T17:00:00.000Z", + "description": "End time of the said shift" + } + }, + "required": [ + "id", + "timesheet_id", + "shift_code_id", + "date", + "start_time", + "end_time" + ] + }, + "UpdateShiftsDto": { + "type": "object", + "properties": { + "timesheet_id": { + "type": "number", + "example": "Th3F3110w5h1pX2024", + "description": "ID number for a set timesheet" + }, + "shift_code_id": { + "type": "number", + "example": "0n3R1n962Ru13xX", + "description": "ID number of a shift code (link with shift-codes)" + }, + "date": { + "format": "date-time", + "type": "string", + "example": "20/10/3018", + "description": "Date where the shift takes place" + }, + "start_time": { + "format": "date-time", + "type": "string", + "example": "08:00", + "description": "Start time of the said shift" + }, + "end_time": { + "format": "date-time", + "type": "string", + "example": "17:00", + "description": "End time of the said shift" + }, + "description": { + "type": "string", + "example": "Called for an emergency at X` place", + "description": "justify the purpose of the shift" + } + } + }, + "CreateLeaveRequestsDto": { + "type": "object", + "properties": { + "employee_id": { + "type": "number", + "example": "4655867", + "description": "Employee`s id" + }, + "leave_type": { + "type": "string", + "example": "Sick or Vacation or Unpaid or Bereavement or Parental or Legal", + "description": "type of leave request for an accounting perception" + }, + "start_date_time": { + "format": "date-time", + "type": "string", + "example": "22/06/2463", + "description": "Leave request`s start date" + }, + "end_date_time": { + "format": "date-time", + "type": "string", + "example": "25/03/3019", + "description": "Leave request`s end date" + }, + "comment": { + "type": "string", + "example": "My precious", + "description": "Leave request`s comment" + }, + "approval_status": { + "type": "string", + "example": "True or False or Pending or Denied or Cancelled or Escalated", + "description": "Leave request`s approval status" + } + }, + "required": [ + "employee_id", + "leave_type", + "start_date_time", + "end_date_time", + "comment", + "approval_status" + ] + }, + "LeaveRequestEntity": { + "type": "object", + "properties": { + "id": { + "type": "number", + "example": 1, + "description": "Leave request`s unique id(auto-incremented)" + }, + "employee_id": { + "type": "number", + "example": 42, + "description": "ID of concerned employee" + }, + "leave_type": { + "type": "string", + "example": "SICK", + "enum": [ + "SICK", + "VACATION", + "UNPAID", + "BEREAVEMENT", + "PARENTAL", + "LEGAL" + ], + "description": "type of leave request for an accounting perception" + }, + "start_date_time": { + "format": "date-time", + "type": "string", + "example": "22/06/2463", + "description": "Leave request`s start date" + }, + "end_date_time": { + "format": "date-time", + "type": "string", + "example": "25/03/3019", + "description": "Leave request`s end date (optionnal)" + }, + "comment": { + "type": "string", + "example": "My precious", + "description": "Leave request employee`s comment" + }, + "approval_status": { + "type": "string", + "example": "PENDING", + "enum": [ + "PENDING", + "APPROVED", + "DENIED", + "CANCELLED", + "ESCALATED" + ], + "description": "Leave request`s approval status" + } + }, + "required": [ + "id", + "employee_id", + "leave_type", + "start_date_time", + "comment", + "approval_status" + ] + }, + "UpdateLeaveRequestsDto": { + "type": "object", + "properties": { + "employee_id": { + "type": "number", + "example": "4655867", + "description": "Employee`s id" + }, + "leave_type": { + "type": "string", + "example": "Sick or Vacation or Unpaid or Bereavement or Parental or Legal", + "description": "type of leave request for an accounting perception" + }, + "start_date_time": { + "format": "date-time", + "type": "string", + "example": "22/06/2463", + "description": "Leave request`s start date" + }, + "end_date_time": { + "format": "date-time", + "type": "string", + "example": "25/03/3019", + "description": "Leave request`s end date" + }, + "comment": { + "type": "string", + "example": "My precious", + "description": "Leave request`s comment" + }, + "approval_status": { + "type": "string", + "example": "True or False or Pending or Denied or Cancelled or Escalated", + "description": "Leave request`s approval status" + } + } + }, "CreateOauthAccessTokenDto": { "type": "object", "properties": { @@ -2442,294 +2908,6 @@ } } }, - "CreateLeaveRequestsDto": { - "type": "object", - "properties": { - "employee_id": { - "type": "number", - "example": "4655867", - "description": "Employee`s id" - }, - "leave_type": { - "type": "string", - "example": "Sick or Vacation or Unpaid or Bereavement or Parental or Legal", - "description": "type of leave request for an accounting perception" - }, - "start_date_time": { - "format": "date-time", - "type": "string", - "example": "22/06/2463", - "description": "Leave request`s start date" - }, - "end_date_time": { - "format": "date-time", - "type": "string", - "example": "25/03/3019", - "description": "Leave request`s end date" - }, - "comment": { - "type": "string", - "example": "My precious", - "description": "Leave request`s comment" - }, - "approval_status": { - "type": "string", - "example": "True or False or Pending or Denied or Cancelled or Escalated", - "description": "Leave request`s approval status" - } - }, - "required": [ - "employee_id", - "leave_type", - "start_date_time", - "end_date_time", - "comment", - "approval_status" - ] - }, - "LeaveRequestEntity": { - "type": "object", - "properties": { - "id": { - "type": "number", - "example": 1, - "description": "Leave request`s unique id(auto-incremented)" - }, - "employee_id": { - "type": "number", - "example": 42, - "description": "ID of concerned employee" - }, - "leave_type": { - "type": "string", - "example": "SICK", - "enum": [ - "SICK", - "VACATION", - "UNPAID", - "BEREAVEMENT", - "PARENTAL", - "LEGAL" - ], - "description": "type of leave request for an accounting perception" - }, - "start_date_time": { - "format": "date-time", - "type": "string", - "example": "22/06/2463", - "description": "Leave request`s start date" - }, - "end_date_time": { - "format": "date-time", - "type": "string", - "example": "25/03/3019", - "description": "Leave request`s end date (optionnal)" - }, - "comment": { - "type": "string", - "example": "My precious", - "description": "Leave request employee`s comment" - }, - "approval_status": { - "type": "string", - "example": "PENDING", - "enum": [ - "PENDING", - "APPROVED", - "DENIED", - "CANCELLED", - "ESCALATED" - ], - "description": "Leave request`s approval status" - } - }, - "required": [ - "id", - "employee_id", - "leave_type", - "start_date_time", - "comment", - "approval_status" - ] - }, - "UpdateLeaveRequestsDto": { - "type": "object", - "properties": { - "employee_id": { - "type": "number", - "example": "4655867", - "description": "Employee`s id" - }, - "leave_type": { - "type": "string", - "example": "Sick or Vacation or Unpaid or Bereavement or Parental or Legal", - "description": "type of leave request for an accounting perception" - }, - "start_date_time": { - "format": "date-time", - "type": "string", - "example": "22/06/2463", - "description": "Leave request`s start date" - }, - "end_date_time": { - "format": "date-time", - "type": "string", - "example": "25/03/3019", - "description": "Leave request`s end date" - }, - "comment": { - "type": "string", - "example": "My precious", - "description": "Leave request`s comment" - }, - "approval_status": { - "type": "string", - "example": "True or False or Pending or Denied or Cancelled or Escalated", - "description": "Leave request`s approval status" - } - } - }, - "CreateExpenseDto": { - "type": "object", - "properties": { - "timesheet_id": { - "type": "number", - "example": "Th3F3110w5h1pX2024", - "description": "ID number for a set timesheet" - }, - "expense_code_id": { - "type": "number", - "example": "0n3R1n962Ru13xX", - "description": "ID number of an expense code (link with shift-codes)" - }, - "date": { - "format": "date-time", - "type": "string", - "example": "20/10/3018", - "description": "Date where the expense was made" - }, - "amount": { - "type": "number", - "example": "280 000 000,00", - "description": "Amount of the expense" - }, - "description": { - "type": "string", - "example": "Spent for mileage between A and B", - "description": "explain`s why the expense was made" - }, - "is_approved": { - "type": "boolean", - "example": "True or False or Pending or Denied or Cancelled or Escalated", - "description": "Expense`s approval status" - }, - "supervisor_comment": { - "type": "string", - "example": "Asked X to go there as an emergency response", - "description": "Supervisro`s justification for the spending of an employee" - } - }, - "required": [ - "timesheet_id", - "expense_code_id", - "date", - "amount", - "description", - "is_approved", - "supervisor_comment" - ] - }, - "ExpenseEntity": { - "type": "object", - "properties": { - "id": { - "type": "number", - "example": 1, - "description": "Unique ID of the expense (auto-generated)" - }, - "timesheet_id": { - "type": "number", - "example": 101, - "description": "ID number for a set timesheet" - }, - "expense": { - "type": "number", - "example": 7, - "description": "ID number of an expense code (link with expense-codes)" - }, - "date": { - "format": "date-time", - "type": "string", - "example": "3018-10-20T00:00:00.000Z", - "description": "Date where the expense was made" - }, - "is_approuved": { - "type": "boolean", - "example": "DENIED, APPROUVED, PENDING, etc...", - "description": "validation status" - }, - "description": { - "type": "string", - "example": "Spent for mileage between A and B", - "description": "explain`s why the expense was made" - }, - "supervisor_comment": { - "type": "string", - "example": "Asked X to go there as an emergency response", - "description": "Supervisro`s justification for the spending of an employee" - } - }, - "required": [ - "id", - "timesheet_id", - "expense", - "date", - "is_approuved", - "description", - "supervisor_comment" - ] - }, - "UpdateExpenseDto": { - "type": "object", - "properties": { - "timesheet_id": { - "type": "number", - "example": "Th3F3110w5h1pX2024", - "description": "ID number for a set timesheet" - }, - "expense_code_id": { - "type": "number", - "example": "0n3R1n962Ru13xX", - "description": "ID number of an expense code (link with shift-codes)" - }, - "date": { - "format": "date-time", - "type": "string", - "example": "20/10/3018", - "description": "Date where the expense was made" - }, - "amount": { - "type": "number", - "example": "280 000 000,00", - "description": "Amount of the expense" - }, - "description": { - "type": "string", - "example": "Spent for mileage between A and B", - "description": "explain`s why the expense was made" - }, - "is_approved": { - "type": "boolean", - "example": "True or False or Pending or Denied or Cancelled or Escalated", - "description": "Expense`s approval status" - }, - "supervisor_comment": { - "type": "string", - "example": "Asked X to go there as an emergency response", - "description": "Supervisro`s justification for the spending of an employee" - } - } - }, "CreateExpenseCodeDto": { "type": "object", "properties": { @@ -2848,195 +3026,6 @@ } } }, - "CreateShiftDto": { - "type": "object", - "properties": { - "timesheet_id": { - "type": "number", - "example": "Th3F3110w5h1pX2024", - "description": "ID number for a set timesheet" - }, - "shift_code_id": { - "type": "number", - "example": "0n3R1n962Ru13xX", - "description": "ID number of a shift code (link with shift-codes)" - }, - "date": { - "format": "date-time", - "type": "string", - "example": "20/10/3018", - "description": "Date where the shift takes place" - }, - "start_time": { - "format": "date-time", - "type": "string", - "example": "08:00", - "description": "Start time of the said shift" - }, - "end_time": { - "format": "date-time", - "type": "string", - "example": "17:00", - "description": "End time of the said shift" - }, - "description": { - "type": "string", - "example": "Called for an emergency at X` place", - "description": "justify the purpose of the shift" - } - }, - "required": [ - "timesheet_id", - "shift_code_id", - "date", - "start_time", - "end_time", - "description" - ] - }, - "ShiftEntity": { - "type": "object", - "properties": { - "id": { - "type": "number", - "example": 1, - "description": "Unique ID of the shift (auto-generated)" - }, - "timesheet_id": { - "type": "number", - "example": 101, - "description": "ID number for a set timesheet" - }, - "shift_code_id": { - "type": "number", - "example": 7, - "description": "ID number of a shift code (link with shift-codes)" - }, - "date": { - "format": "date-time", - "type": "string", - "example": "3018-10-20T00:00:00.000Z", - "description": "Date where the shift takes place" - }, - "start_time": { - "format": "date-time", - "type": "string", - "example": "3018-10-20T08:00:00.000Z", - "description": "Start time of the said shift" - }, - "end_time": { - "format": "date-time", - "type": "string", - "example": "3018-10-20T17:00:00.000Z", - "description": "End time of the said shift" - } - }, - "required": [ - "id", - "timesheet_id", - "shift_code_id", - "date", - "start_time", - "end_time" - ] - }, - "UpdateShiftsDto": { - "type": "object", - "properties": { - "timesheet_id": { - "type": "number", - "example": "Th3F3110w5h1pX2024", - "description": "ID number for a set timesheet" - }, - "shift_code_id": { - "type": "number", - "example": "0n3R1n962Ru13xX", - "description": "ID number of a shift code (link with shift-codes)" - }, - "date": { - "format": "date-time", - "type": "string", - "example": "20/10/3018", - "description": "Date where the shift takes place" - }, - "start_time": { - "format": "date-time", - "type": "string", - "example": "08:00", - "description": "Start time of the said shift" - }, - "end_time": { - "format": "date-time", - "type": "string", - "example": "17:00", - "description": "End time of the said shift" - }, - "description": { - "type": "string", - "example": "Called for an emergency at X` place", - "description": "justify the purpose of the shift" - } - } - }, - "CreateTimesheetDto": { - "type": "object", - "properties": { - "employee_id": { - "type": "number", - "example": "426433", - "description": "employee`s ID number of linked timsheet" - }, - "is_approved": { - "type": "boolean", - "example": "True or False or Pending or Denied or Cancelled or Escalated", - "description": "Timesheet`s approval status" - } - }, - "required": [ - "employee_id", - "is_approved" - ] - }, - "TimesheetEntity": { - "type": "object", - "properties": { - "id": { - "type": "number", - "example": 1, - "description": "timesheet`s unique ID (auto-generated)" - }, - "employee_id": { - "type": "number", - "example": 426433, - "description": "employee`s ID number of linked timsheet" - }, - "is_approved": { - "type": "boolean", - "example": true, - "description": "Timesheet`s approval status" - } - }, - "required": [ - "id", - "employee_id", - "is_approved" - ] - }, - "UpdateTimesheetDto": { - "type": "object", - "properties": { - "employee_id": { - "type": "number", - "example": "426433", - "description": "employee`s ID number of linked timsheet" - }, - "is_approved": { - "type": "boolean", - "example": "True or False or Pending or Denied or Cancelled or Escalated", - "description": "Timesheet`s approval status" - } - } - }, "PayPeriodEntity": { "type": "object", "properties": { diff --git a/prisma/migrations/20250729165951_fix_employees_crew_and_default_now_in_shifts_archive/migration.sql b/prisma/migrations/20250729165951_fix_employees_crew_and_default_now_in_shifts_archive/migration.sql new file mode 100644 index 0000000..1998c52 --- /dev/null +++ b/prisma/migrations/20250729165951_fix_employees_crew_and_default_now_in_shifts_archive/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "shifts_archive" ALTER COLUMN "archive_at" SET DEFAULT CURRENT_TIMESTAMP; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 8ce585d..8363ea0 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -43,7 +43,7 @@ model Employees { supervisor Employees? @relation("EmployeeSupervisor", fields: [supervisor_id], references: [id]) supervisor_id Int? - managed_employees Employees[] @relation("EmployeeSupervisor") //changer pour crew à la prochaine MaJ + crew Employees[] @relation("EmployeeSupervisor") archive EmployeesArchive[] @relation("EmployeeToArchive") timesheet Timesheets[] @relation("TimesheetEmployee") @@ -183,7 +183,7 @@ model ShiftsArchive { id Int @id @default(autoincrement()) shift Shifts @relation("ShiftsToArchive", fields: [shift_id], references: [id]) shift_id Int - archive_at DateTime + archive_at DateTime @default(now()) timesheet_id Int shift_code_id Int description String? diff --git a/src/app.module.ts b/src/app.module.ts index 34a59a8..e874e70 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -17,10 +17,12 @@ import { ExpensesModule } from './modules/expenses/expenses.module'; import { ExpenseCodesModule } from './modules/expense-codes/expense-codes.module'; import { PayperiodsModule } from './modules/pay-periods/pay-periods.module'; import { ScheduleModule } from '@nestjs/schedule'; +import { ArchivalModule } from './modules/archival/archival.module'; @Module({ imports: [ ScheduleModule.forRoot(), + ArchivalModule, PrismaModule, HealthModule, UsersModule, diff --git a/src/main.ts b/src/main.ts index 4c9552d..0bdbc78 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,9 @@ import 'reflect-metadata'; +//import and if case for @nestjs/schedule Cron jobs +import * as nodeCrypto from 'crypto'; +if(!(globalThis as any).crypto) { + (globalThis as any).crypto = nodeCrypto; +} import { ModuleRef, NestFactory, Reflector } from '@nestjs/core'; import { AppModule } from './app.module'; import { ValidationPipe } from '@nestjs/common'; diff --git a/src/modules/archival/archival.module.ts b/src/modules/archival/archival.module.ts new file mode 100644 index 0000000..926cf3f --- /dev/null +++ b/src/modules/archival/archival.module.ts @@ -0,0 +1,20 @@ +import { Module } from "@nestjs/common"; +import { ScheduleModule } from "@nestjs/schedule"; +import { TimesheetsModule } from "../timesheets/timesheets.module"; +import { ExpensesModule } from "../expenses/expenses.module"; +import { ShiftsModule } from "../shifts/shifts.module"; +import { LeaveRequestsModule } from "../leave-requests/leave-requests.module"; +import { ArchivalService } from "./services/archival.service"; + +@Module({ + imports: [ + ScheduleModule, + TimesheetsModule, + ExpensesModule, + ShiftsModule, + LeaveRequestsModule, + ], + providers: [ArchivalService], +}) + +export class ArchivalModule {} \ No newline at end of file diff --git a/src/modules/archival/services/archival.service.ts b/src/modules/archival/services/archival.service.ts new file mode 100644 index 0000000..989c6dd --- /dev/null +++ b/src/modules/archival/services/archival.service.ts @@ -0,0 +1,40 @@ +import { Injectable, Logger } from "@nestjs/common"; +import { Cron, Timeout } from "@nestjs/schedule"; +import { ExpensesService } from "src/modules/expenses/services/expenses.service"; +import { LeaveRequestsService } from "src/modules/leave-requests/services/leave-request.service"; +import { ShiftsService } from "src/modules/shifts/services/shifts.service"; +import { TimesheetsService } from "src/modules/timesheets/services/timesheets.service"; + +@Injectable() +export class ArchivalService { + private readonly logger = new Logger(ArchivalService.name); + + constructor( + private readonly timesheetsService: TimesheetsService, + private readonly expensesService: ExpensesService, + private readonly shiftsService: ShiftsService, + private readonly leaveRequestsService: LeaveRequestsService, + ) {} + + @Cron('0 0 3 * * 1', {timeZone:'America/Toronto'}) // chaque premier lundi du mois à 03h00 + async handleMonthlyArchival() { + const today = new Date(); + const dayOfMonth = today.getDate(); + + if (dayOfMonth > 7) { + this.logger.log('Archive {awaiting 1st monday of the month for archivation process}') + return; + } + + this.logger.log('monthly archivation in process'); + try { + await this.timesheetsService.archiveOld(); + await this.expensesService.archiveOld(); + await this.shiftsService.archiveOld(); + await this.leaveRequestsService.archiveExpired(); + this.logger.log('archivation process done'); + } catch (err) { + this.logger.log('an error occured during archivation ', err); + } + } +} \ No newline at end of file diff --git a/src/modules/employees/controllers/employees.controller.ts b/src/modules/employees/controllers/employees.controller.ts index c736182..2b30577 100644 --- a/src/modules/employees/controllers/employees.controller.ts +++ b/src/modules/employees/controllers/employees.controller.ts @@ -1,4 +1,4 @@ -import { Body,Controller,Delete,Get,Param,ParseIntPipe,Patch,Post,UseGuards } from '@nestjs/common'; +import { Body,Controller,Delete,Get,NotFoundException,Param,ParseIntPipe,Patch,Post,UseGuards } from '@nestjs/common'; import { Employees, Roles as RoleEnum } from '@prisma/client'; import { EmployeesService } from '../services/employees.service'; import { CreateEmployeeDto } from '../dtos/create-employee.dto'; @@ -62,4 +62,16 @@ export class EmployeesController { remove(@Param('id', ParseIntPipe) id: number): Promise { return this.employeesService.remove(id); } + + @Patch(':id') + async updateOrArchiveOrRestore( + @Param('id') id: string, + @Body() dto: UpdateEmployeeDto, + ) { + const result = await this.employeesService.patchEmployee(+id, dto); + if(!result) { + throw new NotFoundException(`Employee #${ id } not found in active or archive.`) + } + return result; + } } diff --git a/src/modules/employees/dtos/update-employee.dto.ts b/src/modules/employees/dtos/update-employee.dto.ts index f4096a1..c0558fb 100644 --- a/src/modules/employees/dtos/update-employee.dto.ts +++ b/src/modules/employees/dtos/update-employee.dto.ts @@ -1,4 +1,8 @@ import { PartialType } from '@nestjs/swagger'; import { CreateEmployeeDto } from './create-employee.dto'; -export class UpdateEmployeeDto extends PartialType(CreateEmployeeDto) {} +export class UpdateEmployeeDto extends PartialType(CreateEmployeeDto) { + first_work_day?: Date; + last_work_day?: Date; + supervisor_id?: number; +} diff --git a/src/modules/employees/services/employees.service.ts b/src/modules/employees/services/employees.service.ts index 5d945bd..9a16821 100644 --- a/src/modules/employees/services/employees.service.ts +++ b/src/modules/employees/services/employees.service.ts @@ -107,4 +107,86 @@ async update( await this.findOne(id); return this.prisma.employees.delete({ where: { id } }); } + + + //archivation function + async patchEmployee(id: number, dto: UpdateEmployeeDto): Promise { + //fetching existing employee + const existing = await this.prisma.employees.findUnique({ + where: { id }, + include: { user: true, archive: true }, + }); + if (existing) { + //verify last_work_day is not null => trigger archivation + if(dto.last_work_day != undefined && existing.last_work_day == null) { + return this.archiveOnTermination(existing, dto); + } + //if null => regular update + return this.prisma.employees.update({ + where: { id }, + data: dto, + }); + } + //if not found => fetch archives side for restoration + const archived = await this.prisma.employeesArchive.findFirst({ + where: { employee_id: id }, + include: { employee: true, user: true }, + }); + if (archived) { + //conditions for restoration + const restore = dto.last_work_day === null || dto.first_work_day != null; + if(restore) { + return this.restoreEmployee(archived, dto); + } + } + //if neither activated nor archivated => 404 + return null; + } + + //transfers the employee to archive and then delete from employees table + private async archiveOnTermination(existing: any, dto: UpdateEmployeeDto): Promise { + return this.prisma.$transaction(async transaction => { + //archive insertion + const archived = await transaction.employeesArchive.create({ + data: { + employee_id: existing.id, + user_id: existing.user_id, + first_name: existing.first_name, + last_name: existing.last_name, + external_payroll_id: existing.external_payroll_id, + company_code: existing.company_code, + first_Work_Day: existing.first_Work_Day, + last_work_day: existing.last_work_day, + supervisor_id: existing.supervisor_id ?? null, + }, + }); + //delete from employees table + await transaction.employees.delete({ where: { id: existing.id } }); + //return archived employee + return archived + }); + } + + //transfers the employee from archive to the employees table + private async restoreEmployee(archived: any, dto: UpdateEmployeeDto): Promise { + return this.prisma.$transaction(async transaction => { + //restores the archived employee into the employees table + const restored = await transaction.employees.create({ + data: { + id: archived.employee_id, + user_id: archived.user_id, + external_payroll_id: dto.external_payroll_id ?? archived.external_payroll_id, + company_code: dto.company_code ?? archived.company_code, + first_work_day: dto.first_work_day ?? archived.first_Work_Day, + last_work_day: null, + supervisor_id: dto.supervisor_id ?? archived.supervisor_id, + }, + }); + //deleting archived entry by id + await transaction.employeesArchive.delete({ where: { id: archived.id } }); + + //return restored employee + return restored; + }); + } } diff --git a/src/modules/expenses/expenses.module.ts b/src/modules/expenses/expenses.module.ts index 3432561..08cf449 100644 --- a/src/modules/expenses/expenses.module.ts +++ b/src/modules/expenses/expenses.module.ts @@ -5,7 +5,8 @@ import { ExpensesService } from "./services/expenses.service"; @Module({ controllers: [ExpensesController], - providers: [ExpensesService, PrismaService] + providers: [ExpensesService, PrismaService], + exports: [ ExpensesService ], }) export class ExpensesModule {} \ No newline at end of file diff --git a/src/modules/expenses/services/expenses.service.ts b/src/modules/expenses/services/expenses.service.ts index e92be77..2be085e 100644 --- a/src/modules/expenses/services/expenses.service.ts +++ b/src/modules/expenses/services/expenses.service.ts @@ -85,5 +85,51 @@ export class ExpensesService { async remove(id: number): Promise { await this.findOne(id); return this.prisma.expenses.delete({ where: { id } }); - } + } + + + //archivation function + async archiveOld(): Promise { + //fetches archived timesheet's Ids + const archivedTimesheets = await this.prisma.timesheetsArchive.findMany({ + select: { timesheet_id: true }, + }); + + const timesheetIds = archivedTimesheets.map(sheet => sheet.timesheet_id); + if(timesheetIds.length === 0) { + return; + } + + // copy/delete transaction + await this.prisma.$transaction(async transaction => { + //fetches expenses to move to archive + const expensesToArchive = await transaction.expenses.findMany({ + where: { timesheet_id: { in: timesheetIds } }, + }); + if(expensesToArchive.length === 0) { + return; + } + + //copies sent to archive table + await transaction.expensesArchive.createMany({ + data: expensesToArchive.map(exp => ({ + expense_id: exp.id, + timesheet_id: exp.timesheet_id, + expense_code_id: exp.expense_code_id, + date: exp.date, + amount: exp.amount, + attachement: exp.attachement, + description: exp.description, + is_approved: exp.is_approved, + supervisor_comment: exp.supervisor_comment, + })), + }); + + //delete from expenses table + await transaction.expenses.deleteMany({ + where: { id: { in: expensesToArchive.map(exp => exp.id) } }, + }) + + }) + } } \ No newline at end of file diff --git a/src/modules/leave-requests/leave-requests.module.ts b/src/modules/leave-requests/leave-requests.module.ts index 7ea2f65..1973165 100644 --- a/src/modules/leave-requests/leave-requests.module.ts +++ b/src/modules/leave-requests/leave-requests.module.ts @@ -6,6 +6,7 @@ import { Module } from "@nestjs/common"; @Module({ controllers: [LeaveRequestController], providers: [ LeaveRequestsService, PrismaService], + exports: [ LeaveRequestsService], }) export class LeaveRequestsModule {} \ No newline at end of file diff --git a/src/modules/leave-requests/services/leave-request.service.ts b/src/modules/leave-requests/services/leave-request.service.ts index 0974320..2d2bd84 100644 --- a/src/modules/leave-requests/services/leave-request.service.ts +++ b/src/modules/leave-requests/services/leave-request.service.ts @@ -106,4 +106,36 @@ export class LeaveRequestsService { where: { id }, }); } + + //archivation function + async archiveExpired(): Promise { + const now = new Date(); + + await this.prisma.$transaction(async transaction => { + //fetches expired leave requests + const expired = await transaction.leaveRequests.findMany({ + where: { end_date_time: { lt: now } }, + }); + if(expired.length === 0) { + return; + } + //copy unto archive table + await transaction.leaveRequestsArchive.createMany({ + data: expired.map(request => ({ + leave_request_id: request.id, + employee_id: request.employee_id, + leave_type: request.leave_type, + start_date_time: request.start_date_time, + end_date_time: request.end_date_time, + comment: request.comment, + approval_status: request.approval_status, + })), + }); + //delete from leave_requests table + await transaction.leaveRequests.deleteMany({ + where: { id: { in: expired.map(request => request.id ) } }, + }); + }); + + } } \ No newline at end of file diff --git a/src/modules/shifts/services/shifts.service.ts b/src/modules/shifts/services/shifts.service.ts index 38547d6..161e05c 100644 --- a/src/modules/shifts/services/shifts.service.ts +++ b/src/modules/shifts/services/shifts.service.ts @@ -86,4 +86,48 @@ export class ShiftsService { await this.findOne(id); return this.prisma.shifts.delete({ where: { id } }); } + + //archivation function + async archiveOld(): Promise { + //fetches archived timesheet's Ids + const archivedTimesheets = await this.prisma.timesheetsArchive.findMany({ + select: { timesheet_id: true }, + }); + + const timesheetIds = archivedTimesheets.map(sheet => sheet.timesheet_id); + if(timesheetIds.length === 0) { + return; + } + + // copy/delete transaction + await this.prisma.$transaction(async transaction => { + //fetches shifts to move to archive + const shiftsToArchive = await transaction.shifts.findMany({ + where: { timesheet_id: { in: timesheetIds } }, + }); + if(shiftsToArchive.length === 0) { + return; + } + + //copies sent to archive table + await transaction.shiftsArchive.createMany({ + data: shiftsToArchive.map(shift => ({ + shift_id: shift.id, + timesheet_id: shift.timesheet_id, + shift_code_id: shift.shift_code_id, + description: shift.description ?? undefined, + date: shift.date, + start_time: shift.start_time, + end_time: shift.end_time, + })), + }); + + //delete from shifts table + await transaction.shifts.deleteMany({ + where: { id: { in: shiftsToArchive.map(shift => shift.id) } }, + }) + + }) + } + } \ No newline at end of file diff --git a/src/modules/shifts/shifts.module.ts b/src/modules/shifts/shifts.module.ts index 6c05370..53924f0 100644 --- a/src/modules/shifts/shifts.module.ts +++ b/src/modules/shifts/shifts.module.ts @@ -5,6 +5,7 @@ import { PrismaService } from 'src/prisma/prisma.service'; @Module({ controllers: [ShiftsController], - providers: [ShiftsService, PrismaService] + providers: [ShiftsService, PrismaService], + exports: [ShiftsService], }) export class ShiftsModule {} diff --git a/src/modules/timesheets/services/timesheets.service.ts b/src/modules/timesheets/services/timesheets.service.ts index 31279b2..84db6e4 100644 --- a/src/modules/timesheets/services/timesheets.service.ts +++ b/src/modules/timesheets/services/timesheets.service.ts @@ -75,4 +75,44 @@ export class TimesheetsService { } + //Archivation function + async archiveOld(): Promise { + //calcul du cutoff pour archivation + const cutoff = new Date(); + cutoff.setMonth(cutoff.getMonth() - 6) + + await this.prisma.$transaction(async transaction => { + //fetches all timesheets to cutoff + const oldSheets = await transaction.timesheets.findMany({ + where: { shift: { every: { date: { lt: cutoff } }, + }, + }, + select: { + id: true, + employee_id: true, + is_approved: true, + }, + }); + if( oldSheets.length === 0) { + return; + } + + //preping data for archivation + const archiveDate = oldSheets.map(sheet => ({ + timesheet_id: sheet.id, + employee_id: sheet.employee_id, + is_approved: sheet.is_approved, + })); + + //copying data from timesheets table to archive table + await transaction.timesheetsArchive.createMany({ + data: archiveDate, + }); + + //removing data from timesheets table + await transaction.timesheets.deleteMany({ + where: { id: { in: oldSheets.map(s => s.id) } }, + }); + }); + } } diff --git a/src/modules/timesheets/timesheets.module.ts b/src/modules/timesheets/timesheets.module.ts index 6cfeb69..11da5c8 100644 --- a/src/modules/timesheets/timesheets.module.ts +++ b/src/modules/timesheets/timesheets.module.ts @@ -4,6 +4,7 @@ import { TimesheetsService } from './services/timesheets.service'; @Module({ controllers: [TimesheetsController], - providers: [TimesheetsService] + providers: [TimesheetsService], + exports: [TimesheetsService], }) export class TimesheetsModule {}