From 6aeaf169931b50e3ea53a93f1595c449a094c99a Mon Sep 17 00:00:00 2001 From: Matthieu Haineault Date: Tue, 21 Oct 2025 16:27:56 -0400 Subject: [PATCH] refactor(expenses): commented module expenses et leave-request. needs refactor to match new timesheets and shifts module. --- docs/swagger/swagger-spec.json | 1063 ++--------------- src/app.module.ts | 16 +- src/modules/archival/archival.module.ts | 64 +- .../controllers/expenses.controller.ts | 168 +-- src/modules/expenses/expenses.module.ts | 42 +- .../services/expenses-command.service.ts | 451 ++++--- .../services/expenses-query.service.ts | 305 +++-- .../controllers/leave-requests.controller.ts | 48 +- .../leave-requests/leave-requests.module.ts | 54 +- .../holiday-leave-requests.service.ts | 134 +-- .../services/leave-request.service.ts | 450 +++---- .../services/sick-leave-requests.service.ts | 174 +-- .../vacation-leave-requests.service.ts | 166 +-- .../utils/leave-request.util.ts | 185 ++- src/modules/pay-periods/pay-periods.module.ts | 56 +- .../services/pay-periods-command.service.ts | 4 +- .../services/timesheet-approval.service.ts | 38 + .../create-timesheet.dto.ts | 52 +- .../search-timesheet.dto.ts | 32 +- .../timesheet-period.dto.ts | 132 +- .../timesheet.helpers.ts | 104 +- .../timesheet.mappers.ts | 206 ++-- .../timesheet.selectors.ts | 82 +- .../~misc_deprecated-files/timesheet.types.ts | 136 +-- .../~misc_deprecated-files/timesheet.utils.ts | 290 ++--- .../timesheets-command.service.ts | 222 ++-- .../timesheets-query.service.ts | 88 +- .../timesheets.controller.ts | 92 +- 28 files changed, 2036 insertions(+), 2818 deletions(-) create mode 100644 src/modules/timesheets/services/timesheet-approval.service.ts diff --git a/docs/swagger/swagger-spec.json b/docs/swagger/swagger-spec.json index d478a65..25ae454 100644 --- a/docs/swagger/swagger-spec.json +++ b/docs/swagger/swagger-spec.json @@ -29,99 +29,31 @@ ] } }, - "/archives/employees": { + "/auth/v1/login": { "get": { - "operationId": "EmployeesArchiveController_findOneArchived", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], + "operationId": "AuthController_login", + "parameters": [], "responses": { "200": { - "description": "Archived employee found" + "description": "" } }, - "summary": "Fetch employee in archives with its Id", "tags": [ - "Employee Archives" + "Auth" ] } }, - "/archives/expenses": { + "/auth/callback": { "get": { - "operationId": "ExpensesArchiveController_findOneArchived", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], + "operationId": "AuthController_loginCallback", + "parameters": [], "responses": { "200": { - "description": "Archived expense found" + "description": "" } }, - "summary": "Fetch expense in archives with its Id", "tags": [ - "Expense Archives" - ] - } - }, - "/archives/shifts": { - "get": { - "operationId": "ShiftsArchiveController_findOneArchived", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "responses": { - "200": { - "description": "Archived shift found" - } - }, - "summary": "Fetch shift in archives with its Id", - "tags": [ - "Shift Archives" - ] - } - }, - "/archives/timesheets": { - "get": { - "operationId": "TimesheetsArchiveController_findOneArchived", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "responses": { - "200": { - "description": "Archived timesheet found" - } - }, - "summary": "Fetch timesheet in archives with its Id", - "tags": [ - "Timesheet Archives" + "Auth" ] } }, @@ -221,380 +153,6 @@ ] } }, - "/timesheets": { - "get": { - "operationId": "TimesheetsController_getPeriodByQuery", - "parameters": [ - { - "name": "year", - "required": true, - "in": "query", - "schema": { - "type": "number" - } - }, - { - "name": "period_no", - "required": true, - "in": "query", - "schema": { - "type": "number" - } - }, - { - "name": "email", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "access-token": [] - } - ], - "tags": [ - "Timesheets" - ] - } - }, - "/timesheets/{email}": { - "get": { - "operationId": "TimesheetsController_getByEmail", - "parameters": [ - { - "name": "email", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - }, - { - "name": "offset", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "access-token": [] - } - ], - "tags": [ - "Timesheets" - ] - } - }, - "/timesheets/shifts/{email}": { - "post": { - "operationId": "TimesheetsController_createTimesheetShifts", - "parameters": [ - { - "name": "email", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - }, - { - "name": "offset", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/CreateWeekShiftsDto" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "security": [ - { - "access-token": [] - } - ], - "tags": [ - "Timesheets" - ] - } - }, - "/Expenses/upsert/{email}/{date}": { - "put": { - "operationId": "ExpensesController_upsert_by_date", - "parameters": [ - { - "name": "email", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - }, - { - "name": "date", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpsertExpenseDto" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "access-token": [] - } - ], - "tags": [ - "Expenses" - ] - } - }, - "/Expenses/list/{email}/{year}/{period_no}": { - "get": { - "operationId": "ExpensesController_findExpenseListByPayPeriodAndEmail", - "parameters": [ - { - "name": "email", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - }, - { - "name": "year", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - }, - { - "name": "period_no", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "access-token": [] - } - ], - "tags": [ - "Expenses" - ] - } - }, - "/shifts/upsert/{email}": { - "put": { - "operationId": "ShiftsController_upsert_by_date", - "parameters": [ - { - "name": "email", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - }, - { - "name": "action", - "required": true, - "in": "query", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpsertShiftDto" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "access-token": [] - } - ], - "tags": [ - "Shifts" - ] - } - }, - "/shifts/delete/{email}/{date}": { - "delete": { - "operationId": "ShiftsController_remove", - "parameters": [ - { - "name": "email", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - }, - { - "name": "date", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpsertShiftDto" - } - } - } - }, - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "access-token": [] - } - ], - "tags": [ - "Shifts" - ] - } - }, - "/shifts/approval/{id}": { - "patch": { - "operationId": "ShiftsController_approve", - "parameters": [ - { - "name": "id", - "required": true, - "in": "path", - "schema": { - "type": "number" - } - } - ], - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "access-token": [] - } - ], - "tags": [ - "Shifts" - ] - } - }, - "/shifts/summary": { - "get": { - "operationId": "ShiftsController_getSummary", - "parameters": [], - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "access-token": [] - } - ], - "tags": [ - "Shifts" - ] - } - }, - "/shifts/export.csv": { - "get": { - "operationId": "ShiftsController_exportCsv", - "parameters": [], - "responses": { - "200": { - "description": "" - } - }, - "security": [ - { - "access-token": [] - } - ], - "tags": [ - "Shifts" - ] - } - }, "/notifications/summary": { "get": { "operationId": "NotificationsController_summary", @@ -623,63 +181,6 @@ ] } }, - "/leave-requests/upsert": { - "post": { - "operationId": "LeaveRequestController_upsertLeaveRequest", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/UpsertLeaveRequestDto" - } - } - } - }, - "responses": { - "201": { - "description": "" - } - }, - "security": [ - { - "access-token": [] - } - ], - "tags": [ - "Leave Requests" - ] - } - }, - "/auth/v1/login": { - "get": { - "operationId": "AuthController_login", - "parameters": [], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "Auth" - ] - } - }, - "/auth/callback": { - "get": { - "operationId": "AuthController_loginCallback", - "parameters": [], - "responses": { - "200": { - "description": "" - } - }, - "tags": [ - "Auth" - ] - } - }, "/oauth-sessions": { "post": { "operationId": "OauthSessionsController_create", @@ -874,251 +375,6 @@ ] } }, - "/pay-periods/current-and-all": { - "get": { - "operationId": "PayPeriodsController_getCurrentAndAll", - "parameters": [ - { - "name": "date", - "required": false, - "in": "query", - "description": "Override for resolving the current period", - "schema": { - "example": "2025-08-11", - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Find current and all pay periods", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PayPeriodBundleDto" - } - } - } - } - }, - "summary": "Return current pay period and the full list", - "tags": [ - "pay-periods" - ] - } - }, - "/pay-periods/date/{date}": { - "get": { - "operationId": "PayPeriodsController_findByDate", - "parameters": [ - { - "name": "date", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - } - ], - "responses": { - "200": { - "description": "Pay period found for the selected date", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PayPeriodDto" - } - } - } - }, - "404": { - "description": "Pay period not found for the selected date" - } - }, - "summary": "Resolve a period by a date within it", - "tags": [ - "pay-periods" - ] - } - }, - "/pay-periods/{year}/{periodNumber}": { - "get": { - "operationId": "PayPeriodsController_findOneByYear", - "parameters": [ - { - "name": "year", - "required": true, - "in": "path", - "schema": { - "example": 2024, - "type": "number" - } - }, - { - "name": "periodNumber", - "required": true, - "in": "path", - "description": "1..26", - "schema": { - "example": 1, - "type": "number" - } - } - ], - "responses": { - "200": { - "description": "Pay period found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PayPeriodDto" - } - } - } - }, - "404": { - "description": "Pay period not found" - } - }, - "summary": "Find pay period by year and period number", - "tags": [ - "pay-periods" - ] - } - }, - "/pay-periods/crew/bulk-approval": { - "patch": { - "operationId": "PayPeriodsController_bulkApproval", - "parameters": [], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/BulkCrewApprovalDto" - } - } - } - }, - "responses": { - "200": { - "description": "Pay period approved" - } - }, - "summary": "Approve all selected timesheets in the period", - "tags": [ - "pay-periods" - ] - } - }, - "/pay-periods/{year}/{periodNumber}/{email}": { - "get": { - "operationId": "PayPeriodsController_getCrewOverview", - "parameters": [ - { - "name": "year", - "required": true, - "in": "path", - "schema": { - "example": 2024, - "type": "number" - } - }, - { - "name": "periodNumber", - "required": true, - "in": "path", - "description": "1..26", - "schema": { - "example": 1, - "type": "number" - } - }, - { - "name": "email", - "required": true, - "in": "path", - "schema": { - "type": "string" - } - }, - { - "name": "includeSubtree", - "required": false, - "in": "query", - "description": "Include indirect reports", - "schema": { - "example": false, - "type": "boolean" - } - } - ], - "responses": { - "200": { - "description": "Crew overview", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PayPeriodOverviewDto" - } - } - } - }, - "404": { - "description": "Pay period not found" - } - }, - "summary": "Supervisor crew overview for a given pay period", - "tags": [ - "pay-periods" - ] - } - }, - "/pay-periods/overview/{year}/{periodNumber}": { - "get": { - "operationId": "PayPeriodsController_getOverviewByYear", - "parameters": [ - { - "name": "year", - "required": true, - "in": "path", - "schema": { - "example": 2024, - "type": "number" - } - }, - { - "name": "periodNumber", - "required": true, - "in": "path", - "description": "1..26", - "schema": { - "example": 1, - "type": "number" - } - } - ], - "responses": { - "200": { - "description": "Pay period overview found", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/PayPeriodOverviewDto" - } - } - } - }, - "404": { - "description": "Pay period not found" - } - }, - "summary": "Detailed view of a pay period by year + number", - "tags": [ - "pay-periods" - ] - } - }, "/preferences/{email}": { "patch": { "operationId": "PreferencesController_updatePreferences", @@ -1252,6 +508,123 @@ "SchedulePresets" ] } + }, + "/shift": { + "get": { + "operationId": "ShiftController_getShiftsByIds", + "parameters": [ + { + "name": "shift_ids", + "required": true, + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": [ + "Shift" + ] + }, + "patch": { + "operationId": "ShiftController_updateBatch", + "parameters": [], + "responses": { + "200": { + "description": "" + } + }, + "tags": [ + "Shift" + ] + } + }, + "/shift/{timesheet_id}": { + "post": { + "operationId": "ShiftController_createBatch", + "parameters": [ + { + "name": "timesheet_id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "responses": { + "201": { + "description": "" + } + }, + "tags": [ + "Shift" + ] + } + }, + "/shift/{shift_id}": { + "delete": { + "operationId": "ShiftController_remove", + "parameters": [ + { + "name": "shift_id", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": [ + "Shift" + ] + } + }, + "/timesheets": { + "get": { + "operationId": "TimesheetController_getTimesheetByIds", + "parameters": [ + { + "name": "timesheet_ids", + "required": true, + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": [ + "Timesheet" + ] + } } }, "info": { @@ -1463,22 +836,6 @@ "first_work_day" ] }, - "CreateWeekShiftsDto": { - "type": "object", - "properties": {} - }, - "UpsertExpenseDto": { - "type": "object", - "properties": {} - }, - "UpsertShiftDto": { - "type": "object", - "properties": {} - }, - "UpsertLeaveRequestDto": { - "type": "object", - "properties": {} - }, "CreateOauthSessionDto": { "type": "object", "properties": { @@ -1587,172 +944,6 @@ } } }, - "PayPeriodDto": { - "type": "object", - "properties": { - "pay_period_no": { - "type": "number", - "example": 1, - "description": "numéro cyclique de la période entre 1 et 26" - }, - "period_start": { - "type": "string", - "example": "2023-12-17", - "format": "date" - }, - "period_end": { - "type": "string", - "example": "2023-12-30", - "format": "date" - }, - "payday": { - "type": "string", - "example": "2023-01-04", - "format": "date" - }, - "pay_year": { - "type": "number", - "example": 2023 - }, - "label": { - "type": "string", - "example": "2023-12-17 → 2023-12-30" - } - }, - "required": [ - "pay_period_no", - "period_start", - "period_end", - "payday", - "pay_year", - "label" - ] - }, - "PayPeriodBundleDto": { - "type": "object", - "properties": { - "current": { - "description": "Current pay period (resolved from date)", - "allOf": [ - { - "$ref": "#/components/schemas/PayPeriodDto" - } - ] - }, - "periods": { - "description": "All pay periods", - "type": "array", - "items": { - "$ref": "#/components/schemas/PayPeriodDto" - } - } - }, - "required": [ - "current", - "periods" - ] - }, - "BulkCrewApprovalDto": { - "type": "object", - "properties": {} - }, - "EmployeePeriodOverviewDto": { - "type": "object", - "properties": { - "employee_name": { - "type": "string", - "example": "Alex Dupont", - "description": "Nom complet de lemployé" - }, - "regular_hours": { - "type": "number", - "example": 40, - "description": "pay-period`s regular hours" - }, - "other_hours": { - "type": "object", - "example": 0, - "description": "pay-period`s other hours" - }, - "expenses": { - "type": "number", - "example": 420.69, - "description": "pay-period`s total expenses ($)" - }, - "mileage": { - "type": "number", - "example": 40, - "description": "pay-period total mileages (km)" - }, - "is_approved": { - "type": "boolean", - "example": true, - "description": "Tous les timesheets de la période sont approuvés pour cet employé" - } - }, - "required": [ - "employee_name", - "regular_hours", - "other_hours", - "expenses", - "mileage", - "is_approved" - ] - }, - "PayPeriodOverviewDto": { - "type": "object", - "properties": { - "pay_period_no": { - "type": "number", - "example": 1, - "description": "Period number (1–26)" - }, - "pay_year": { - "type": "number", - "example": 2023, - "description": "Calendar year of the period" - }, - "period_start": { - "type": "string", - "example": "2023-12-17", - "format": "date", - "description": "Period start date (YYYY-MM-DD)" - }, - "period_end": { - "type": "string", - "example": "2023-12-30", - "format": "date", - "description": "Period end date (YYYY-MM-DD)" - }, - "payday": { - "type": "string", - "example": "2023-12-30", - "format": "date", - "description": "Period pay day(YYYY-MM-DD)" - }, - "label": { - "type": "string", - "example": "2023-12-17 → 2023-12-30", - "description": "Human-readable label" - }, - "employees_overview": { - "description": "Per-employee overview for the period", - "type": "array", - "items": { - "$ref": "#/components/schemas/EmployeePeriodOverviewDto" - } - } - }, - "required": [ - "pay_period_no", - "pay_year", - "period_start", - "period_end", - "payday", - "label", - "employees_overview" - ] - }, "PreferencesDto": { "type": "object", "properties": {} diff --git a/src/app.module.ts b/src/app.module.ts index daf8229..04f2348 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,21 +1,21 @@ import { BadRequestException, Module, ValidationPipe } from '@nestjs/common'; import { AppController } from './app.controller'; import { AppService } from './app.service'; -import { ArchivalModule } from './modules/archival/archival.module'; +// import { ArchivalModule } from './modules/archival/archival.module'; import { AuthenticationModule } from './modules/authentication/auth.module'; import { BankCodesModule } from './modules/bank-codes/bank-codes.module'; import { BusinessLogicsModule } from './modules/business-logics/business-logics.module'; // import { CsvExportModule } from './modules/exports/csv-exports.module'; import { CustomersModule } from './modules/customers/customers.module'; import { EmployeesModule } from './modules/employees/employees.module'; -import { ExpensesModule } from './modules/expenses/expenses.module'; +// import { ExpensesModule } from './modules/expenses/expenses.module'; import { HealthModule } from './health/health.module'; import { HealthController } from './health/health.controller'; -import { LeaveRequestsModule } from './modules/leave-requests/leave-requests.module'; +// import { LeaveRequestsModule } from './modules/leave-requests/leave-requests.module'; import { NotificationsModule } from './modules/notifications/notifications.module'; import { OauthSessionsModule } from './modules/oauth-sessions/oauth-sessions.module'; import { OvertimeService } from './modules/business-logics/services/overtime.service'; -import { PayperiodsModule } from './modules/pay-periods/pay-periods.module'; +// import { PayperiodsModule } from './modules/pay-periods/pay-periods.module'; import { PreferencesModule } from './modules/preferences/preferences.module'; import { PrismaModule } from './prisma/prisma.module'; import { ScheduleModule } from '@nestjs/schedule'; @@ -30,7 +30,7 @@ import { SchedulePresetsModule } from './modules/schedule-presets/schedule-prese @Module({ imports: [ - ArchivalModule, + // ArchivalModule, AuthenticationModule, BankCodesModule, BusinessLogicsModule, @@ -38,12 +38,12 @@ import { SchedulePresetsModule } from './modules/schedule-presets/schedule-prese // CsvExportModule, CustomersModule, EmployeesModule, - ExpensesModule, + // ExpensesModule, HealthModule, - LeaveRequestsModule, + // LeaveRequestsModule, NotificationsModule, OauthSessionsModule, - PayperiodsModule, + // PayperiodsModule, PreferencesModule, PrismaModule, ScheduleModule.forRoot(), //cronjobs diff --git a/src/modules/archival/archival.module.ts b/src/modules/archival/archival.module.ts index 03f1bf9..e48e908 100644 --- a/src/modules/archival/archival.module.ts +++ b/src/modules/archival/archival.module.ts @@ -1,34 +1,34 @@ -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"; -import { EmployeesArchiveController } from "./controllers/employees-archive.controller"; -import { ExpensesArchiveController } from "./controllers/expenses-archive.controller"; -import { LeaveRequestsArchiveController } from "./controllers/leave-requests-archive.controller"; -import { ShiftsArchiveController } from "./controllers/shifts-archive.controller"; -import { TimesheetsArchiveController } from "./controllers/timesheets-archive.controller"; -import { EmployeesModule } from "../employees/employees.module"; +// 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"; +// import { EmployeesArchiveController } from "./controllers/employees-archive.controller"; +// import { ExpensesArchiveController } from "./controllers/expenses-archive.controller"; +// import { LeaveRequestsArchiveController } from "./controllers/leave-requests-archive.controller"; +// import { ShiftsArchiveController } from "./controllers/shifts-archive.controller"; +// import { TimesheetsArchiveController } from "./controllers/timesheets-archive.controller"; +// import { EmployeesModule } from "../employees/employees.module"; -@Module({ - imports: [ - EmployeesModule, - ScheduleModule, - TimesheetsModule, - ExpensesModule, - ShiftsModule, - LeaveRequestsModule, - ], - providers: [ArchivalService], - controllers: [ - EmployeesArchiveController, - ExpensesArchiveController, - LeaveRequestsArchiveController, - ShiftsArchiveController, - TimesheetsArchiveController, - ], -}) +// @Module({ +// imports: [ +// EmployeesModule, +// ScheduleModule, +// TimesheetsModule, +// ExpensesModule, +// ShiftsModule, +// LeaveRequestsModule, +// ], +// providers: [ArchivalService], +// controllers: [ +// EmployeesArchiveController, +// ExpensesArchiveController, +// LeaveRequestsArchiveController, +// ShiftsArchiveController, +// TimesheetsArchiveController, +// ], +// }) -export class ArchivalModule {} \ No newline at end of file +// export class ArchivalModule {} \ No newline at end of file diff --git a/src/modules/expenses/controllers/expenses.controller.ts b/src/modules/expenses/controllers/expenses.controller.ts index cb3b1bb..aea3161 100644 --- a/src/modules/expenses/controllers/expenses.controller.ts +++ b/src/modules/expenses/controllers/expenses.controller.ts @@ -1,95 +1,95 @@ -import { Body, Controller, Get, Param, Put, } from "@nestjs/common"; -import { Roles as RoleEnum } from '.prisma/client'; -import { ApiBearerAuth, ApiTags } from "@nestjs/swagger"; -import { RolesAllowed } from "src/common/decorators/roles.decorators"; -import { ExpensesCommandService } from "../services/expenses-command.service"; -import { UpsertExpenseDto } from "../dtos/upsert-expense.dto"; -import { UpsertExpenseResult } from "../types and interfaces/expenses.types.interfaces"; -import { DayExpensesDto } from "src/modules/timesheets/~misc_deprecated-files/timesheet-period.dto"; -import { ExpensesQueryService } from "../services/expenses-query.service"; +// import { Body, Controller, Get, Param, Put, } from "@nestjs/common"; +// import { Roles as RoleEnum } from '.prisma/client'; +// import { ApiBearerAuth, ApiTags } from "@nestjs/swagger"; +// import { RolesAllowed } from "src/common/decorators/roles.decorators"; +// import { ExpensesCommandService } from "../services/expenses-command.service"; +// import { UpsertExpenseDto } from "../dtos/upsert-expense.dto"; +// import { UpsertExpenseResult } from "../types and interfaces/expenses.types.interfaces"; +// import { DayExpensesDto } from "src/modules/timesheets/~misc_deprecated-files/timesheet-period.dto"; +// import { ExpensesQueryService } from "../services/expenses-query.service"; -@ApiTags('Expenses') -@ApiBearerAuth('access-token') -// @UseGuards() -@Controller('Expenses') -export class ExpensesController { - constructor( - private readonly query: ExpensesQueryService, - private readonly command: ExpensesCommandService, - ) {} +// @ApiTags('Expenses') +// @ApiBearerAuth('access-token') +// // @UseGuards() +// @Controller('Expenses') +// export class ExpensesController { +// constructor( +// private readonly query: ExpensesQueryService, +// private readonly command: ExpensesCommandService, +// ) {} - @Put('upsert/:email/:date') - async upsert_by_date( - @Param('email') email: string, - @Param('date') date: string, - @Body() dto: UpsertExpenseDto, - ): Promise { - return this.command.upsertExpensesByDate(email, date, dto); - } +// @Put('upsert/:email/:date') +// async upsert_by_date( +// @Param('email') email: string, +// @Param('date') date: string, +// @Body() dto: UpsertExpenseDto, +// ): Promise { +// return this.command.upsertExpensesByDate(email, date, dto); +// } - @Get('list/:email/:year/:period_no') - async findExpenseListByPayPeriodAndEmail( - @Param('email') email:string, - @Param('year') year: number, - @Param('period_no') period_no: number, - ): Promise { - return this.query.findExpenseListByPayPeriodAndEmail(email, year, period_no); - } +// @Get('list/:email/:year/:period_no') +// async findExpenseListByPayPeriodAndEmail( +// @Param('email') email:string, +// @Param('year') year: number, +// @Param('period_no') period_no: number, +// ): Promise { +// return this.query.findExpenseListByPayPeriodAndEmail(email, year, period_no); +// } - //_____________________________________________________________________________________________ - // Deprecated or unused methods - //_____________________________________________________________________________________________ +// //_____________________________________________________________________________________________ +// // Deprecated or unused methods +// //_____________________________________________________________________________________________ - // @Post() - // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) - // @ApiOperation({ summary: 'Create expense' }) - // @ApiResponse({ status: 201, description: 'Expense created',type: CreateExpenseDto }) - // @ApiResponse({ status: 400, description: 'Incomplete task or invalid data' }) - // create(@Body() dto: CreateExpenseDto): Promise { - // return this.query.create(dto); - // } +// // @Post() +// // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) +// // @ApiOperation({ summary: 'Create expense' }) +// // @ApiResponse({ status: 201, description: 'Expense created',type: CreateExpenseDto }) +// // @ApiResponse({ status: 400, description: 'Incomplete task or invalid data' }) +// // create(@Body() dto: CreateExpenseDto): Promise { +// // return this.query.create(dto); +// // } - // @Get() - // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) - // @ApiOperation({ summary: 'Find all expenses' }) - // @ApiResponse({ status: 201, description: 'List of expenses found',type: CreateExpenseDto, isArray: true }) - // @ApiResponse({ status: 400, description: 'List of expenses not found' }) - // @UsePipes(new ValidationPipe({ transform: true, whitelist: true })) - // findAll(@Query() filters: SearchExpensesDto): Promise { - // return this.query.findAll(filters); - // } +// // @Get() +// // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) +// // @ApiOperation({ summary: 'Find all expenses' }) +// // @ApiResponse({ status: 201, description: 'List of expenses found',type: CreateExpenseDto, isArray: true }) +// // @ApiResponse({ status: 400, description: 'List of expenses not found' }) +// // @UsePipes(new ValidationPipe({ transform: true, whitelist: true })) +// // findAll(@Query() filters: SearchExpensesDto): Promise { +// // return this.query.findAll(filters); +// // } - // @Get(':id') - // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) - // @ApiOperation({ summary: 'Find expense' }) - // @ApiResponse({ status: 201, description: 'Expense found',type: CreateExpenseDto }) - // @ApiResponse({ status: 400, description: 'Expense not found' }) - // findOne(@Param('id', ParseIntPipe) id: number): Promise { - // return this.query.findOne(id); - // } +// // @Get(':id') +// // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) +// // @ApiOperation({ summary: 'Find expense' }) +// // @ApiResponse({ status: 201, description: 'Expense found',type: CreateExpenseDto }) +// // @ApiResponse({ status: 400, description: 'Expense not found' }) +// // findOne(@Param('id', ParseIntPipe) id: number): Promise { +// // return this.query.findOne(id); +// // } - // @Patch(':id') - // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) - // @ApiOperation({ summary: 'Expense shift' }) - // @ApiResponse({ status: 201, description: 'Expense updated',type: CreateExpenseDto }) - // @ApiResponse({ status: 400, description: 'Expense not found' }) - // update(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateExpenseDto) { - // return this.query.update(id,dto); - // } +// // @Patch(':id') +// // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) +// // @ApiOperation({ summary: 'Expense shift' }) +// // @ApiResponse({ status: 201, description: 'Expense updated',type: CreateExpenseDto }) +// // @ApiResponse({ status: 400, description: 'Expense not found' }) +// // update(@Param('id', ParseIntPipe) id: number, @Body() dto: UpdateExpenseDto) { +// // return this.query.update(id,dto); +// // } - // @Delete(':id') - // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) - // @ApiOperation({ summary: 'Delete expense' }) - // @ApiResponse({ status: 201, description: 'Expense deleted',type: CreateExpenseDto }) - // @ApiResponse({ status: 400, description: 'Expense not found' }) - // remove(@Param('id', ParseIntPipe) id: number): Promise { - // return this.query.remove(id); - // } +// // @Delete(':id') +// // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) +// // @ApiOperation({ summary: 'Delete expense' }) +// // @ApiResponse({ status: 201, description: 'Expense deleted',type: CreateExpenseDto }) +// // @ApiResponse({ status: 400, description: 'Expense not found' }) +// // remove(@Param('id', ParseIntPipe) id: number): Promise { +// // return this.query.remove(id); +// // } - // @Patch('approval/:id') - // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR) - // async approve(@Param('id', ParseIntPipe) id: number, @Body('is_approved', ParseBoolPipe) isApproved: boolean) { - // return this.command.updateApproval(id, isApproved); - // } +// // @Patch('approval/:id') +// // //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR) +// // async approve(@Param('id', ParseIntPipe) id: number, @Body('is_approved', ParseBoolPipe) isApproved: boolean) { +// // return this.command.updateApproval(id, isApproved); +// // } -} \ No newline at end of file +// } \ No newline at end of file diff --git a/src/modules/expenses/expenses.module.ts b/src/modules/expenses/expenses.module.ts index 6201b91..490ec9e 100644 --- a/src/modules/expenses/expenses.module.ts +++ b/src/modules/expenses/expenses.module.ts @@ -1,23 +1,23 @@ -import { ExpensesController } from "./controllers/expenses.controller"; -import { Module } from "@nestjs/common"; -import { ExpensesQueryService } from "./services/expenses-query.service"; -import { BusinessLogicsModule } from "src/modules/business-logics/business-logics.module"; -import { ExpensesCommandService } from "./services/expenses-command.service"; -import { ExpensesArchivalService } from "./services/expenses-archival.service"; -import { SharedModule } from "../shared/shared.module"; +// import { ExpensesController } from "./controllers/expenses.controller"; +// import { Module } from "@nestjs/common"; +// import { ExpensesQueryService } from "./services/expenses-query.service"; +// import { BusinessLogicsModule } from "src/modules/business-logics/business-logics.module"; +// import { ExpensesCommandService } from "./services/expenses-command.service"; +// import { ExpensesArchivalService } from "./services/expenses-archival.service"; +// import { SharedModule } from "../shared/shared.module"; -@Module({ - imports: [BusinessLogicsModule, SharedModule], - controllers: [ExpensesController], - providers: [ - ExpensesQueryService, - ExpensesArchivalService, - ExpensesCommandService, - ], - exports: [ - ExpensesQueryService, - ExpensesArchivalService, - ], -}) +// @Module({ +// imports: [BusinessLogicsModule, SharedModule], +// controllers: [ExpensesController], +// providers: [ +// ExpensesQueryService, +// ExpensesArchivalService, +// ExpensesCommandService, +// ], +// exports: [ +// ExpensesQueryService, +// ExpensesArchivalService, +// ], +// }) -export class ExpensesModule {} \ No newline at end of file +// export class ExpensesModule {} \ No newline at end of file diff --git a/src/modules/expenses/services/expenses-command.service.ts b/src/modules/expenses/services/expenses-command.service.ts index 1511eb0..723bb7a 100644 --- a/src/modules/expenses/services/expenses-command.service.ts +++ b/src/modules/expenses/services/expenses-command.service.ts @@ -1,250 +1,249 @@ -import { BaseApprovalService } from "src/common/shared/base-approval.service"; -import { Expenses, Prisma } from "@prisma/client"; -import { PrismaService } from "src/prisma/prisma.service"; -import { UpsertExpenseDto } from "../dtos/upsert-expense.dto"; -import { BankCodesResolver } from "src/modules/shared/utils/resolve-bank-type-id.utils"; -import { ExpenseResponse, UpsertAction } from "../types and interfaces/expenses.types.interfaces"; -import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; -import { EmployeeTimesheetResolver } from "src/modules/shared/utils/resolve-timesheet.utils"; -import { - BadRequestException, - Injectable, - NotFoundException -} from "@nestjs/common"; -import { - assertAndTrimComment, - computeAmountDecimal, - computeMileageAmount, - mapDbExpenseToDayResponse, - normalizeType, - parseAttachmentId -} from "../utils/expenses.utils"; -import { toDateOnly } from "src/modules/shifts/helpers/shifts-date-time-helpers"; +// import { BaseApprovalService } from "src/common/shared/base-approval.service"; +// import { Expenses, Prisma } from "@prisma/client"; +// import { PrismaService } from "src/prisma/prisma.service"; +// import { UpsertExpenseDto } from "../dtos/upsert-expense.dto"; +// import { BankCodesResolver } from "src/modules/shared/utils/resolve-bank-type-id.utils"; +// import { ExpenseResponse, UpsertAction } from "../types and interfaces/expenses.types.interfaces"; +// import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; +// import { EmployeeTimesheetResolver } from "src/modules/shared/utils/resolve-timesheet.utils"; +// import { +// BadRequestException, +// Injectable, +// NotFoundException +// } from "@nestjs/common"; +// import { +// assertAndTrimComment, +// computeAmountDecimal, +// computeMileageAmount, +// mapDbExpenseToDayResponse, +// normalizeType, +// parseAttachmentId +// } from "../utils/expenses.utils"; -@Injectable() -export class ExpensesCommandService extends BaseApprovalService { - constructor( - prisma: PrismaService, - private readonly bankCodesResolver: BankCodesResolver, - private readonly timesheetsResolver: EmployeeTimesheetResolver, - private readonly emailResolver: EmailToIdResolver, - ) { super(prisma); } +// @Injectable() +// export class ExpensesCommandService extends BaseApprovalService { +// constructor( +// prisma: PrismaService, +// private readonly bankCodesResolver: BankCodesResolver, +// private readonly timesheetsResolver: EmployeeTimesheetResolver, +// private readonly emailResolver: EmailToIdResolver, +// ) { super(prisma); } - //_____________________________________________________________________________________________ - // APPROVAL TX-DELEGATE METHODS - //_____________________________________________________________________________________________ +// //_____________________________________________________________________________________________ +// // APPROVAL TX-DELEGATE METHODS +// //_____________________________________________________________________________________________ - protected get delegate() { - return this.prisma.expenses; - } +// protected get delegate() { +// return this.prisma.expenses; +// } - protected delegateFor(transaction: Prisma.TransactionClient){ - return transaction.expenses; - } +// protected delegateFor(transaction: Prisma.TransactionClient){ +// return transaction.expenses; +// } - async updateApproval(id: number, isApproved: boolean): Promise { - return this.prisma.$transaction((transaction) => - this.updateApprovalWithTransaction(transaction, id, isApproved), - ); - } +// async updateApproval(id: number, isApproved: boolean): Promise { +// return this.prisma.$transaction((transaction) => +// this.updateApprovalWithTransaction(transaction, id, isApproved), +// ); +// } - //_____________________________________________________________________________________________ - // MASTER CRUD FUNCTION - //_____________________________________________________________________________________________ - readonly upsertExpensesByDate = async (email: string, date: string, dto: UpsertExpenseDto, - ): Promise<{ action:UpsertAction; day: ExpenseResponse[] }> => { +// //_____________________________________________________________________________________________ +// // MASTER CRUD FUNCTION +// //_____________________________________________________________________________________________ +// readonly upsertExpensesByDate = async (email: string, date: string, dto: UpsertExpenseDto, +// ): Promise<{ action:UpsertAction; day: ExpenseResponse[] }> => { - //validates if there is an existing expense, at least 1 old or new - const { old_expense, new_expense } = dto ?? {}; - if(!old_expense && !new_expense) throw new BadRequestException('At least one expense must be provided'); +// //validates if there is an existing expense, at least 1 old or new +// const { old_expense, new_expense } = dto ?? {}; +// if(!old_expense && !new_expense) throw new BadRequestException('At least one expense must be provided'); - //validate date format - const date_only = toDateOnly(date); - if(Number.isNaN(date_only.getTime())) throw new BadRequestException('Invalid date format (expected: YYYY-MM-DD)'); +// //validate date format +// const date_only = toDateOnly(date); +// if(Number.isNaN(date_only.getTime())) throw new BadRequestException('Invalid date format (expected: YYYY-MM-DD)'); - //resolve employee_id by email - const employee_id = await this.emailResolver.findIdByEmail(email); +// //resolve employee_id by email +// const employee_id = await this.emailResolver.findIdByEmail(email); - //make sure a timesheet existes - const timesheet_id = await this.timesheetsResolver.findTimesheetIdByEmail(email, date_only); - if(!timesheet_id) throw new NotFoundException(`no timesheet found for employee #${employee_id}`) - const {id} = timesheet_id; +// //make sure a timesheet existes +// const timesheet_id = await this.timesheetsResolver.findTimesheetIdByEmail(email, date_only); +// if(!timesheet_id) throw new NotFoundException(`no timesheet found for employee #${employee_id}`) +// const {id} = timesheet_id; - return this.prisma.$transaction(async (tx) => { - const loadDay = async (): Promise => { - const rows = await tx.expenses.findMany({ - where: { - timesheet_id: id, - date: date_only, - }, - include: { - bank_code: { - select: { - type: true, - }, - }, - }, - orderBy: [{ date: 'asc' }, { id: 'asc' }], - }); +// return this.prisma.$transaction(async (tx) => { +// const loadDay = async (): Promise => { +// const rows = await tx.expenses.findMany({ +// where: { +// timesheet_id: id, +// date: date_only, +// }, +// include: { +// bank_code: { +// select: { +// type: true, +// }, +// }, +// }, +// orderBy: [{ date: 'asc' }, { id: 'asc' }], +// }); - return rows.map((r) => - mapDbExpenseToDayResponse({ - date: r.date, - amount: r.amount ?? 0, - mileage: r.mileage ?? 0, - comment: r.comment, - is_approved: r.is_approved, - bank_code: r.bank_code, - })); - }; +// return rows.map((r) => +// mapDbExpenseToDayResponse({ +// date: r.date, +// amount: r.amount ?? 0, +// mileage: r.mileage ?? 0, +// comment: r.comment, +// is_approved: r.is_approved, +// bank_code: r.bank_code, +// })); +// }; - const normalizePayload = async (payload: { - type: string; - amount?: number; - mileage?: number; - comment: string; - attachment?: string | number; - }): Promise<{ - type: string; - bank_code_id: number; - amount: Prisma.Decimal; - mileage: number | null; - comment: string; - attachment: number | null; - }> => { - const type = normalizeType(payload.type); - const comment = assertAndTrimComment(payload.comment); - const attachment = parseAttachmentId(payload.attachment); +// const normalizePayload = async (payload: { +// type: string; +// amount?: number; +// mileage?: number; +// comment: string; +// attachment?: string | number; +// }): Promise<{ +// type: string; +// bank_code_id: number; +// amount: Prisma.Decimal; +// mileage: number | null; +// comment: string; +// attachment: number | null; +// }> => { +// const type = normalizeType(payload.type); +// const comment = assertAndTrimComment(payload.comment); +// const attachment = parseAttachmentId(payload.attachment); - const { id: bank_code_id, modifier } = await this.bankCodesResolver.findByType(type); - let amount = computeAmountDecimal(type, payload, modifier); - let mileage: number | null = null; +// const { id: bank_code_id, modifier } = await this.bankCodesResolver.findByType(type); +// let amount = computeAmountDecimal(type, payload, modifier); +// let mileage: number | null = null; - if (type === 'MILEAGE') { - mileage = Number(payload.mileage ?? 0); - if (!(mileage > 0)) { - throw new BadRequestException('Mileage required and must be > 0 for type MILEAGE'); - } +// if (type === 'MILEAGE') { +// mileage = Number(payload.mileage ?? 0); +// if (!(mileage > 0)) { +// throw new BadRequestException('Mileage required and must be > 0 for type MILEAGE'); +// } - const amountNumber = computeMileageAmount(mileage, modifier); - amount = new Prisma.Decimal(amountNumber); +// const amountNumber = computeMileageAmount(mileage, modifier); +// amount = new Prisma.Decimal(amountNumber); - } else { - if (!(typeof payload.amount === 'number' && payload.amount >= 0)) { - throw new BadRequestException('Amount required for non-MILEAGE expense'); - } - amount = new Prisma.Decimal(payload.amount); - } +// } else { +// if (!(typeof payload.amount === 'number' && payload.amount >= 0)) { +// throw new BadRequestException('Amount required for non-MILEAGE expense'); +// } +// amount = new Prisma.Decimal(payload.amount); +// } - if (attachment !== null) { - const attachment_row = await tx.attachments.findUnique({ - where: { id: attachment }, - select: { status: true }, - }); - if (!attachment_row || attachment_row.status !== 'ACTIVE') { - throw new BadRequestException('Attachment not found or inactive'); - } - } +// if (attachment !== null) { +// const attachment_row = await tx.attachments.findUnique({ +// where: { id: attachment }, +// select: { status: true }, +// }); +// if (!attachment_row || attachment_row.status !== 'ACTIVE') { +// throw new BadRequestException('Attachment not found or inactive'); +// } +// } - return { - type, - bank_code_id, - amount, - mileage, - comment, - attachment - }; - }; +// return { +// type, +// bank_code_id, +// amount, +// mileage, +// comment, +// attachment +// }; +// }; - const findExactOld = async (norm: { - bank_code_id: number; - amount: Prisma.Decimal; - mileage: number | null; - comment: string; - attachment: number | null; - }) => { - return tx.expenses.findFirst({ - where: { - timesheet_id: id, - date: date_only, - bank_code_id: norm.bank_code_id, - amount: norm.amount, - comment: norm.comment, - attachment: norm.attachment, - ...(norm.mileage !== null ? { mileage: norm.mileage } : { mileage: null }), - }, - select: { id: true }, - }); - }; +// const findExactOld = async (norm: { +// bank_code_id: number; +// amount: Prisma.Decimal; +// mileage: number | null; +// comment: string; +// attachment: number | null; +// }) => { +// return tx.expenses.findFirst({ +// where: { +// timesheet_id: id, +// date: date_only, +// bank_code_id: norm.bank_code_id, +// amount: norm.amount, +// comment: norm.comment, +// attachment: norm.attachment, +// ...(norm.mileage !== null ? { mileage: norm.mileage } : { mileage: null }), +// }, +// select: { id: true }, +// }); +// }; - let action : UpsertAction; - //_____________________________________________________________________________________________ - // DELETE - //_____________________________________________________________________________________________ - if(old_expense && !new_expense) { - const old_norm = await normalizePayload(old_expense); - const existing = await findExactOld(old_norm); - if(!existing) { - throw new NotFoundException({ - error_code: 'EXPENSE_STALE', - message: 'The expense was modified or deleted by someone else', - }); - } - await tx.expenses.delete({where: { id: existing.id } }); - action = 'delete'; - } - //_____________________________________________________________________________________________ - // CREATE - //_____________________________________________________________________________________________ - else if (!old_expense && new_expense) { - const new_exp = await normalizePayload(new_expense); - await tx.expenses.create({ - data: { - timesheet_id: id, - date: date_only, - bank_code_id: new_exp.bank_code_id, - amount: new_exp.amount, - mileage: new_exp.mileage, - comment: new_exp.comment, - attachment: new_exp.attachment, - is_approved: false, - }, - }); - action = 'create'; - } - //_____________________________________________________________________________________________ - // UPDATE - //_____________________________________________________________________________________________ - else if(old_expense && new_expense) { - const old_norm = await normalizePayload(old_expense); - const existing = await findExactOld(old_norm); - if(!existing) { - throw new NotFoundException({ - error_code: 'EXPENSE_STALE', - message: 'The expense was modified or deleted by someone else', - }); - } +// let action : UpsertAction; +// //_____________________________________________________________________________________________ +// // DELETE +// //_____________________________________________________________________________________________ +// if(old_expense && !new_expense) { +// const old_norm = await normalizePayload(old_expense); +// const existing = await findExactOld(old_norm); +// if(!existing) { +// throw new NotFoundException({ +// error_code: 'EXPENSE_STALE', +// message: 'The expense was modified or deleted by someone else', +// }); +// } +// await tx.expenses.delete({where: { id: existing.id } }); +// action = 'delete'; +// } +// //_____________________________________________________________________________________________ +// // CREATE +// //_____________________________________________________________________________________________ +// else if (!old_expense && new_expense) { +// const new_exp = await normalizePayload(new_expense); +// await tx.expenses.create({ +// data: { +// timesheet_id: id, +// date: date_only, +// bank_code_id: new_exp.bank_code_id, +// amount: new_exp.amount, +// mileage: new_exp.mileage, +// comment: new_exp.comment, +// attachment: new_exp.attachment, +// is_approved: false, +// }, +// }); +// action = 'create'; +// } +// //_____________________________________________________________________________________________ +// // UPDATE +// //_____________________________________________________________________________________________ +// else if(old_expense && new_expense) { +// const old_norm = await normalizePayload(old_expense); +// const existing = await findExactOld(old_norm); +// if(!existing) { +// throw new NotFoundException({ +// error_code: 'EXPENSE_STALE', +// message: 'The expense was modified or deleted by someone else', +// }); +// } - const new_exp = await normalizePayload(new_expense); - await tx.expenses.update({ - where: { id: existing.id }, - data: { - bank_code_id: new_exp.bank_code_id, - amount: new_exp.amount, - mileage: new_exp.mileage, - comment: new_exp.comment, - attachment: new_exp.attachment, - }, - }); - action = 'update'; - } - else { - throw new BadRequestException('Invalid upsert combination'); - } +// const new_exp = await normalizePayload(new_expense); +// await tx.expenses.update({ +// where: { id: existing.id }, +// data: { +// bank_code_id: new_exp.bank_code_id, +// amount: new_exp.amount, +// mileage: new_exp.mileage, +// comment: new_exp.comment, +// attachment: new_exp.attachment, +// }, +// }); +// action = 'update'; +// } +// else { +// throw new BadRequestException('Invalid upsert combination'); +// } - const day = await loadDay(); +// const day = await loadDay(); - return { action, day }; - }); - } -} \ No newline at end of file +// return { action, day }; +// }); +// } +// } \ No newline at end of file diff --git a/src/modules/expenses/services/expenses-query.service.ts b/src/modules/expenses/services/expenses-query.service.ts index 441b9d8..d95f1a7 100644 --- a/src/modules/expenses/services/expenses-query.service.ts +++ b/src/modules/expenses/services/expenses-query.service.ts @@ -1,174 +1,171 @@ -import { Injectable, NotFoundException } from "@nestjs/common"; -import { PrismaService } from "src/prisma/prisma.service"; -import { DayExpensesDto as ExpenseListResponseDto, ExpenseDto } from "src/modules/timesheets/~misc_deprecated-files/timesheet-period.dto"; -import { round2, toUTCDateOnly } from "src/modules/timesheets/~misc_deprecated-files/utils-helpers-others/timesheet.helpers"; -import { EXPENSE_TYPES } from "src/modules/timesheets/~misc_deprecated-files/utils-helpers-others/timesheet.types"; -import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; +// import { Injectable, NotFoundException } from "@nestjs/common"; +// import { PrismaService } from "src/prisma/prisma.service"; +// import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; -@Injectable() -export class ExpensesQueryService { - constructor( - private readonly prisma: PrismaService, - private readonly employeeRepo: EmailToIdResolver, - ) {} +// @Injectable() +// export class ExpensesQueryService { +// constructor( +// private readonly prisma: PrismaService, +// private readonly employeeRepo: EmailToIdResolver, +// ) {} - //fetchs all expenses for a selected employee using email, pay-period-year and number - async findExpenseListByPayPeriodAndEmail( - email: string, - year: number, - period_no: number - ): Promise { - //fetch employe_id using email - const employee_id = await this.employeeRepo.findIdByEmail(email); - if(!employee_id) throw new NotFoundException(`Employee with email: ${email} not found`); +// //fetchs all expenses for a selected employee using email, pay-period-year and number +// async findExpenseListByPayPeriodAndEmail( +// email: string, +// year: number, +// period_no: number +// ): Promise { +// //fetch employe_id using email +// const employee_id = await this.employeeRepo.findIdByEmail(email); +// if(!employee_id) throw new NotFoundException(`Employee with email: ${email} not found`); - //fetch pay-period using year and period_no - const pay_period = await this.prisma.payPeriods.findFirst({ - where: { - pay_year: year, - pay_period_no: period_no - }, - select: { period_start: true, period_end: true }, - }); - if(!pay_period) throw new NotFoundException(`Pay period ${year}- ${period_no} not found`); +// //fetch pay-period using year and period_no +// const pay_period = await this.prisma.payPeriods.findFirst({ +// where: { +// pay_year: year, +// pay_period_no: period_no +// }, +// select: { period_start: true, period_end: true }, +// }); +// if(!pay_period) throw new NotFoundException(`Pay period ${year}- ${period_no} not found`); - const start = toUTCDateOnly(pay_period.period_start); - const end = toUTCDateOnly(pay_period.period_end); +// const start = toUTCDateOnly(pay_period.period_start); +// const end = toUTCDateOnly(pay_period.period_end); - //sets rows data - const rows = await this.prisma.expenses.findMany({ - where: { - date: { gte: start, lte: end }, - timesheet: { is: { employee_id } }, - }, - orderBy: { date: 'asc'}, - select: { - amount: true, - mileage: true, - comment: true, - is_approved: true, - supervisor_comment: true, - bank_code: {select: { type: true } }, - }, - }); +// //sets rows data +// const rows = await this.prisma.expenses.findMany({ +// where: { +// date: { gte: start, lte: end }, +// timesheet: { is: { employee_id } }, +// }, +// orderBy: { date: 'asc'}, +// select: { +// amount: true, +// mileage: true, +// comment: true, +// is_approved: true, +// supervisor_comment: true, +// bank_code: {select: { type: true } }, +// }, +// }); - //declare return values - const expenses: ExpenseDto[] = []; - let total_amount = 0; - let total_mileage = 0; +// //declare return values +// const expenses: ExpenseDto[] = []; +// let total_amount = 0; +// let total_mileage = 0; - //set rows - for(const row of rows) { - const type = (row.bank_code?.type ?? '').toUpperCase(); - const amount = round2(Number(row.amount ?? 0)); - const mileage = round2(Number(row.mileage ?? 0)); +// //set rows +// for(const row of rows) { +// const type = (row.bank_code?.type ?? '').toUpperCase(); +// const amount = round2(Number(row.amount ?? 0)); +// const mileage = round2(Number(row.mileage ?? 0)); - if(type === EXPENSE_TYPES.MILEAGE) { - total_mileage += mileage; - } else { - total_amount += amount; - } +// if(type === EXPENSE_TYPES.MILEAGE) { +// total_mileage += mileage; +// } else { +// total_amount += amount; +// } - //fills rows array - expenses.push({ - type, - amount, - mileage, - comment: row.comment ?? '', - is_approved: row.is_approved ?? false, - supervisor_comment: row.supervisor_comment ?? '', - }); - } +// //fills rows array +// expenses.push({ +// type, +// amount, +// mileage, +// comment: row.comment ?? '', +// is_approved: row.is_approved ?? false, +// supervisor_comment: row.supervisor_comment ?? '', +// }); +// } - return { - expenses, - total_expense: round2(total_amount), - total_mileage: round2(total_mileage), - }; -} +// return { +// expenses, +// total_expense: round2(total_amount), +// total_mileage: round2(total_mileage), +// }; +// } - //_____________________________________________________________________________________________ - // Deprecated or unused methods - //_____________________________________________________________________________________________ +// //_____________________________________________________________________________________________ +// // Deprecated or unused methods +// //_____________________________________________________________________________________________ - // async create(dto: CreateExpenseDto): Promise { - // const { timesheet_id, bank_code_id, date, amount:rawAmount, - // comment, is_approved,supervisor_comment} = dto; - // //fetches type and modifier - // const bank_code = await this.prisma.bankCodes.findUnique({ - // where: { id: bank_code_id }, - // select: { type: true, modifier: true }, - // }); - // if(!bank_code) throw new NotFoundException(`bank_code #${bank_code_id} not found`); +// // async create(dto: CreateExpenseDto): Promise { +// // const { timesheet_id, bank_code_id, date, amount:rawAmount, +// // comment, is_approved,supervisor_comment} = dto; +// // //fetches type and modifier +// // const bank_code = await this.prisma.bankCodes.findUnique({ +// // where: { id: bank_code_id }, +// // select: { type: true, modifier: true }, +// // }); +// // if(!bank_code) throw new NotFoundException(`bank_code #${bank_code_id} not found`); - // //if mileage -> service, otherwise the ratio is amount:1 - // let final_amount: number; - // if(bank_code.type === 'mileage') { - // final_amount = await this.mileageService.calculateReimbursement(rawAmount, bank_code_id); - // }else { - // final_amount = parseFloat( (rawAmount * bank_code.modifier).toFixed(2)); - // } +// // //if mileage -> service, otherwise the ratio is amount:1 +// // let final_amount: number; +// // if(bank_code.type === 'mileage') { +// // final_amount = await this.mileageService.calculateReimbursement(rawAmount, bank_code_id); +// // }else { +// // final_amount = parseFloat( (rawAmount * bank_code.modifier).toFixed(2)); +// // } - // return this.prisma.expenses.create({ - // data: { - // timesheet_id, - // bank_code_id, - // date, - // amount: final_amount, - // comment, - // is_approved, - // supervisor_comment - // }, - // include: { timesheet: { include: { employee: { include: { user: true }}}}, - // bank_code: true, - // }, - // }) - // } +// // return this.prisma.expenses.create({ +// // data: { +// // timesheet_id, +// // bank_code_id, +// // date, +// // amount: final_amount, +// // comment, +// // is_approved, +// // supervisor_comment +// // }, +// // include: { timesheet: { include: { employee: { include: { user: true }}}}, +// // bank_code: true, +// // }, +// // }) +// // } - // async findAll(filters: SearchExpensesDto): Promise { - // const where = buildPrismaWhere(filters); - // const expenses = await this.prisma.expenses.findMany({ where }) - // return expenses; - // } +// // async findAll(filters: SearchExpensesDto): Promise { +// // const where = buildPrismaWhere(filters); +// // const expenses = await this.prisma.expenses.findMany({ where }) +// // return expenses; +// // } - // async findOne(id: number): Promise { - // const expense = await this.prisma.expenses.findUnique({ - // where: { id }, - // include: { timesheet: { include: { employee: { include: { user:true } } } }, - // bank_code: true, - // }, - // }); - // if (!expense) { - // throw new NotFoundException(`Expense #${id} not found`); - // } - // return expense; - // } +// // async findOne(id: number): Promise { +// // const expense = await this.prisma.expenses.findUnique({ +// // where: { id }, +// // include: { timesheet: { include: { employee: { include: { user:true } } } }, +// // bank_code: true, +// // }, +// // }); +// // if (!expense) { +// // throw new NotFoundException(`Expense #${id} not found`); +// // } +// // return expense; +// // } - // async update(id: number, dto: UpdateExpenseDto): Promise { - // await this.findOne(id); - // const { timesheet_id, bank_code_id, date, amount, - // comment, is_approved, supervisor_comment} = dto; - // return this.prisma.expenses.update({ - // where: { id }, - // data: { - // ...(timesheet_id !== undefined && { timesheet_id}), - // ...(bank_code_id !== undefined && { bank_code_id }), - // ...(date !== undefined && { date }), - // ...(amount !== undefined && { amount }), - // ...(comment !== undefined && { comment }), - // ...(is_approved !== undefined && { is_approved }), - // ...(supervisor_comment !== undefined && { supervisor_comment }), - // }, - // include: { timesheet: { include: { employee: { include: { user: true } } } }, - // bank_code: true, - // }, - // }); - // } +// // async update(id: number, dto: UpdateExpenseDto): Promise { +// // await this.findOne(id); +// // const { timesheet_id, bank_code_id, date, amount, +// // comment, is_approved, supervisor_comment} = dto; +// // return this.prisma.expenses.update({ +// // where: { id }, +// // data: { +// // ...(timesheet_id !== undefined && { timesheet_id}), +// // ...(bank_code_id !== undefined && { bank_code_id }), +// // ...(date !== undefined && { date }), +// // ...(amount !== undefined && { amount }), +// // ...(comment !== undefined && { comment }), +// // ...(is_approved !== undefined && { is_approved }), +// // ...(supervisor_comment !== undefined && { supervisor_comment }), +// // }, +// // include: { timesheet: { include: { employee: { include: { user: true } } } }, +// // bank_code: true, +// // }, +// // }); +// // } - // async remove(id: number): Promise { - // await this.findOne(id); - // return this.prisma.expenses.delete({ where: { id } }); - // } +// // async remove(id: number): Promise { +// // await this.findOne(id); +// // return this.prisma.expenses.delete({ where: { id } }); +// // } -} \ No newline at end of file +// } \ No newline at end of file diff --git a/src/modules/leave-requests/controllers/leave-requests.controller.ts b/src/modules/leave-requests/controllers/leave-requests.controller.ts index fc934ff..7ecce7e 100644 --- a/src/modules/leave-requests/controllers/leave-requests.controller.ts +++ b/src/modules/leave-requests/controllers/leave-requests.controller.ts @@ -1,30 +1,30 @@ -import { Body, Controller, Post } from "@nestjs/common"; -import { ApiBearerAuth, ApiTags } from "@nestjs/swagger"; -import { LeaveRequestsService } from "../services/leave-request.service"; -import { UpsertLeaveRequestDto } from "../dtos/upsert-leave-request.dto"; -import { LeaveTypes } from "@prisma/client"; +// import { Body, Controller, Post } from "@nestjs/common"; +// import { ApiBearerAuth, ApiTags } from "@nestjs/swagger"; +// import { LeaveRequestsService } from "../services/leave-request.service"; +// import { UpsertLeaveRequestDto } from "../dtos/upsert-leave-request.dto"; +// import { LeaveTypes } from "@prisma/client"; -@ApiTags('Leave Requests') -@ApiBearerAuth('access-token') -// @UseGuards() -@Controller('leave-requests') -export class LeaveRequestController { - constructor(private readonly leave_service: LeaveRequestsService){} +// @ApiTags('Leave Requests') +// @ApiBearerAuth('access-token') +// // @UseGuards() +// @Controller('leave-requests') +// export class LeaveRequestController { +// constructor(private readonly leave_service: LeaveRequestsService){} - @Post('upsert') - async upsertLeaveRequest(@Body() dto: UpsertLeaveRequestDto) { - const { action, leave_requests } = await this.leave_service.handle(dto); - return { action, leave_requests }; - }q +// @Post('upsert') +// async upsertLeaveRequest(@Body() dto: UpsertLeaveRequestDto) { +// const { action, leave_requests } = await this.leave_service.handle(dto); +// return { action, leave_requests }; +// }q - //TODO: - /* - @Get('archive') - findAllArchived(){...} +// //TODO: +// /* +// @Get('archive') +// findAllArchived(){...} - @Get('archive/:id') - findOneArchived(id){...} - */ +// @Get('archive/:id') +// findOneArchived(id){...} +// */ -} +// } diff --git a/src/modules/leave-requests/leave-requests.module.ts b/src/modules/leave-requests/leave-requests.module.ts index 714dad8..03ad546 100644 --- a/src/modules/leave-requests/leave-requests.module.ts +++ b/src/modules/leave-requests/leave-requests.module.ts @@ -1,29 +1,29 @@ -import { PrismaService } from "src/prisma/prisma.service"; -import { LeaveRequestController } from "./controllers/leave-requests.controller"; -import { HolidayLeaveRequestsService } from "./services/holiday-leave-requests.service"; -import { Module } from "@nestjs/common"; -import { BusinessLogicsModule } from "src/modules/business-logics/business-logics.module"; -import { VacationLeaveRequestsService } from "./services/vacation-leave-requests.service"; -import { SickLeaveRequestsService } from "./services/sick-leave-requests.service"; -import { LeaveRequestsService } from "./services/leave-request.service"; -import { ShiftsModule } from "../shifts/shifts.module"; -import { LeaveRequestsUtils } from "./utils/leave-request.util"; -import { SharedModule } from "../shared/shared.module"; +// import { PrismaService } from "src/prisma/prisma.service"; +// import { LeaveRequestController } from "./controllers/leave-requests.controller"; +// import { HolidayLeaveRequestsService } from "./services/holiday-leave-requests.service"; +// import { Module } from "@nestjs/common"; +// import { BusinessLogicsModule } from "src/modules/business-logics/business-logics.module"; +// import { VacationLeaveRequestsService } from "./services/vacation-leave-requests.service"; +// import { SickLeaveRequestsService } from "./services/sick-leave-requests.service"; +// import { LeaveRequestsService } from "./services/leave-request.service"; +// import { ShiftsModule } from "../shifts/shifts.module"; +// import { LeaveRequestsUtils } from "./utils/leave-request.util"; +// import { SharedModule } from "../shared/shared.module"; -@Module({ - imports: [BusinessLogicsModule, ShiftsModule, SharedModule], - controllers: [LeaveRequestController], - providers: [ - VacationLeaveRequestsService, - SickLeaveRequestsService, - HolidayLeaveRequestsService, - LeaveRequestsService, - PrismaService, - LeaveRequestsUtils, - ], - exports: [ - LeaveRequestsService, - ], -}) +// @Module({ +// imports: [BusinessLogicsModule, ShiftsModule, SharedModule], +// controllers: [LeaveRequestController], +// providers: [ +// VacationLeaveRequestsService, +// SickLeaveRequestsService, +// HolidayLeaveRequestsService, +// LeaveRequestsService, +// PrismaService, +// LeaveRequestsUtils, +// ], +// exports: [ +// LeaveRequestsService, +// ], +// }) -export class LeaveRequestsModule {} \ No newline at end of file +// export class LeaveRequestsModule {} \ No newline at end of file diff --git a/src/modules/leave-requests/services/holiday-leave-requests.service.ts b/src/modules/leave-requests/services/holiday-leave-requests.service.ts index 309bfbb..ecfa8cc 100644 --- a/src/modules/leave-requests/services/holiday-leave-requests.service.ts +++ b/src/modules/leave-requests/services/holiday-leave-requests.service.ts @@ -1,78 +1,78 @@ -import { UpsertLeaveRequestDto, UpsertResult } from '../dtos/upsert-leave-request.dto'; -import { LeaveRequestViewDto } from '../dtos/leave-request-view.dto'; -import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; -import { LeaveApprovalStatus, LeaveTypes } from '@prisma/client'; -import { HolidayService } from 'src/modules/business-logics/services/holiday.service'; -import { PrismaService } from 'src/prisma/prisma.service'; -import { mapRowToView } from '../mappers/leave-requests.mapper'; -import { leaveRequestsSelect } from '../utils/leave-requests.select'; -import { LeaveRequestsUtils} from '../utils/leave-request.util'; -import { normalizeDates, toDateOnly } from 'src/modules/shared/helpers/date-time.helpers'; -import { BankCodesResolver } from 'src/modules/shared/utils/resolve-bank-type-id.utils'; -import { EmailToIdResolver } from 'src/modules/shared/utils/resolve-email-id.utils'; +// import { UpsertLeaveRequestDto, UpsertResult } from '../dtos/upsert-leave-request.dto'; +// import { LeaveRequestViewDto } from '../dtos/leave-request-view.dto'; +// import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; +// import { LeaveApprovalStatus, LeaveTypes } from '@prisma/client'; +// import { HolidayService } from 'src/modules/business-logics/services/holiday.service'; +// import { PrismaService } from 'src/prisma/prisma.service'; +// import { mapRowToView } from '../mappers/leave-requests.mapper'; +// import { leaveRequestsSelect } from '../utils/leave-requests.select'; +// import { LeaveRequestsUtils} from '../utils/leave-request.util'; +// import { normalizeDates, toDateOnly } from 'src/modules/shared/helpers/date-time.helpers'; +// import { BankCodesResolver } from 'src/modules/shared/utils/resolve-bank-type-id.utils'; +// import { EmailToIdResolver } from 'src/modules/shared/utils/resolve-email-id.utils'; -@Injectable() -export class HolidayLeaveRequestsService { - constructor( - private readonly prisma: PrismaService, - private readonly holidayService: HolidayService, - private readonly leaveUtils: LeaveRequestsUtils, - private readonly emailResolver: EmailToIdResolver, - private readonly typeResolver: BankCodesResolver, - ) {} +// @Injectable() +// export class HolidayLeaveRequestsService { +// constructor( +// private readonly prisma: PrismaService, +// private readonly holidayService: HolidayService, +// private readonly leaveUtils: LeaveRequestsUtils, +// private readonly emailResolver: EmailToIdResolver, +// private readonly typeResolver: BankCodesResolver, +// ) {} - async create(dto: UpsertLeaveRequestDto): Promise { - const email = dto.email.trim(); - const employee_id = await this.emailResolver.findIdByEmail(email); - const bank_code = await this.typeResolver.findByType(LeaveTypes.HOLIDAY); - if(!bank_code) throw new NotFoundException(`bank_code not found`); - const dates = normalizeDates(dto.dates); - if (!dates.length) throw new BadRequestException('Dates array must not be empty'); +// async create(dto: UpsertLeaveRequestDto): Promise { +// const email = dto.email.trim(); +// const employee_id = await this.emailResolver.findIdByEmail(email); +// const bank_code = await this.typeResolver.findByType(LeaveTypes.HOLIDAY); +// if(!bank_code) throw new NotFoundException(`bank_code not found`); +// const dates = normalizeDates(dto.dates); +// if (!dates.length) throw new BadRequestException('Dates array must not be empty'); - const created: LeaveRequestViewDto[] = []; +// const created: LeaveRequestViewDto[] = []; - for (const iso_date of dates) { - const date = toDateOnly(iso_date); +// for (const iso_date of dates) { +// const date = toDateOnly(iso_date); - const existing = await this.prisma.leaveRequests.findUnique({ - where: { - leave_per_employee_date: { - employee_id: employee_id, - leave_type: LeaveTypes.HOLIDAY, - date, - }, - }, - select: { id: true }, - }); - if (existing) { - throw new BadRequestException(`Holiday request already exists for ${iso_date}`); - } +// const existing = await this.prisma.leaveRequests.findUnique({ +// where: { +// leave_per_employee_date: { +// employee_id: employee_id, +// leave_type: LeaveTypes.HOLIDAY, +// date, +// }, +// }, +// select: { id: true }, +// }); +// if (existing) { +// throw new BadRequestException(`Holiday request already exists for ${iso_date}`); +// } - const payable = await this.holidayService.calculateHolidayPay(email, date, bank_code.modifier); - const row = await this.prisma.leaveRequests.create({ - data: { - employee_id: employee_id, - bank_code_id: bank_code.id, - leave_type: LeaveTypes.HOLIDAY, - date, - comment: dto.comment ?? '', - requested_hours: dto.requested_hours ?? 8, - payable_hours: payable, - approval_status: dto.approval_status ?? LeaveApprovalStatus.PENDING, - }, - select: leaveRequestsSelect, - }); +// const payable = await this.holidayService.calculateHolidayPay(email, date, bank_code.modifier); +// const row = await this.prisma.leaveRequests.create({ +// data: { +// employee_id: employee_id, +// bank_code_id: bank_code.id, +// leave_type: LeaveTypes.HOLIDAY, +// date, +// comment: dto.comment ?? '', +// requested_hours: dto.requested_hours ?? 8, +// payable_hours: payable, +// approval_status: dto.approval_status ?? LeaveApprovalStatus.PENDING, +// }, +// select: leaveRequestsSelect, +// }); - const hours = Number(row.payable_hours ?? row.requested_hours ?? 0); - if (row.approval_status === LeaveApprovalStatus.APPROVED) { - await this.leaveUtils.syncShift(email, employee_id, iso_date, hours,LeaveTypes.HOLIDAY, row.comment); - } +// const hours = Number(row.payable_hours ?? row.requested_hours ?? 0); +// if (row.approval_status === LeaveApprovalStatus.APPROVED) { +// await this.leaveUtils.syncShift(email, employee_id, iso_date, hours,LeaveTypes.HOLIDAY, row.comment); +// } - created.push({ ...mapRowToView(row), action: 'create' }); - } +// created.push({ ...mapRowToView(row), action: 'create' }); +// } - return { action: 'create', leave_requests: created }; - } -} +// return { action: 'create', leave_requests: created }; +// } +// } diff --git a/src/modules/leave-requests/services/leave-request.service.ts b/src/modules/leave-requests/services/leave-request.service.ts index d5e3eb7..7b0c82e 100644 --- a/src/modules/leave-requests/services/leave-request.service.ts +++ b/src/modules/leave-requests/services/leave-request.service.ts @@ -1,248 +1,248 @@ -import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; -import { LeaveApprovalStatus, LeaveTypes } from "@prisma/client"; -import { roundToQuarterHour } from "src/common/utils/date-utils"; -import { UpsertLeaveRequestDto, UpsertResult } from "../dtos/upsert-leave-request.dto"; -import { LeaveRequestViewDto } from "../dtos/leave-request-view.dto"; -import { mapRowToView } from "../mappers/leave-requests.mapper"; -import { leaveRequestsSelect } from "../utils/leave-requests.select"; -import { HolidayLeaveRequestsService } from "./holiday-leave-requests.service"; -import { SickLeaveRequestsService } from "./sick-leave-requests.service"; -import { VacationLeaveRequestsService } from "./vacation-leave-requests.service"; -import { HolidayService } from "src/modules/business-logics/services/holiday.service"; -import { SickLeaveService } from "src/modules/business-logics/services/sick-leave.service"; -import { VacationService } from "src/modules/business-logics/services/vacation.service"; -import { PrismaService } from "src/prisma/prisma.service"; -import { LeaveRequestsUtils } from "../utils/leave-request.util"; -import { normalizeDates, toDateOnly, toISODateKey } from "src/modules/shared/helpers/date-time.helpers"; -import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; -import { BankCodesResolver } from "src/modules/shared/utils/resolve-bank-type-id.utils"; +// import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; +// import { LeaveApprovalStatus, LeaveTypes } from "@prisma/client"; +// import { roundToQuarterHour } from "src/common/utils/date-utils"; +// import { UpsertLeaveRequestDto, UpsertResult } from "../dtos/upsert-leave-request.dto"; +// import { LeaveRequestViewDto } from "../dtos/leave-request-view.dto"; +// import { mapRowToView } from "../mappers/leave-requests.mapper"; +// import { leaveRequestsSelect } from "../utils/leave-requests.select"; +// import { HolidayLeaveRequestsService } from "./holiday-leave-requests.service"; +// import { SickLeaveRequestsService } from "./sick-leave-requests.service"; +// import { VacationLeaveRequestsService } from "./vacation-leave-requests.service"; +// import { HolidayService } from "src/modules/business-logics/services/holiday.service"; +// import { SickLeaveService } from "src/modules/business-logics/services/sick-leave.service"; +// import { VacationService } from "src/modules/business-logics/services/vacation.service"; +// import { PrismaService } from "src/prisma/prisma.service"; +// import { LeaveRequestsUtils } from "../utils/leave-request.util"; +// import { normalizeDates, toDateOnly, toISODateKey } from "src/modules/shared/helpers/date-time.helpers"; +// import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; +// import { BankCodesResolver } from "src/modules/shared/utils/resolve-bank-type-id.utils"; -@Injectable() -export class LeaveRequestsService { - constructor( - private readonly prisma: PrismaService, - private readonly holidayLeaveService: HolidayLeaveRequestsService, - private readonly holidayService: HolidayService, - private readonly sickLogic: SickLeaveService, - private readonly sickLeaveService: SickLeaveRequestsService, - private readonly vacationLeaveService: VacationLeaveRequestsService, - private readonly vacationLogic: VacationService, - private readonly leaveUtils: LeaveRequestsUtils, - private readonly emailResolver: EmailToIdResolver, - private readonly typeResolver: BankCodesResolver, - ) {} +// @Injectable() +// export class LeaveRequestsService { +// constructor( +// private readonly prisma: PrismaService, +// private readonly holidayLeaveService: HolidayLeaveRequestsService, +// private readonly holidayService: HolidayService, +// private readonly sickLogic: SickLeaveService, +// private readonly sickLeaveService: SickLeaveRequestsService, +// private readonly vacationLeaveService: VacationLeaveRequestsService, +// private readonly vacationLogic: VacationService, +// private readonly leaveUtils: LeaveRequestsUtils, +// private readonly emailResolver: EmailToIdResolver, +// private readonly typeResolver: BankCodesResolver, +// ) {} - //handle distribution to the right service according to the selected type and action - async handle(dto: UpsertLeaveRequestDto): Promise { - switch (dto.type) { - case LeaveTypes.HOLIDAY: - if( dto.action === 'create'){ - return this.holidayLeaveService.create(dto); - } else if (dto.action === 'update') { - return this.update(dto, LeaveTypes.HOLIDAY); - } else if (dto.action === 'delete'){ - return this.delete(dto, LeaveTypes.HOLIDAY); - } - case LeaveTypes.VACATION: - if( dto.action === 'create'){ - return this.vacationLeaveService.create(dto); - } else if (dto.action === 'update') { - return this.update(dto, LeaveTypes.VACATION); - } else if (dto.action === 'delete'){ - return this.delete(dto, LeaveTypes.VACATION); - } - case LeaveTypes.SICK: - if( dto.action === 'create'){ - return this.sickLeaveService.create(dto); - } else if (dto.action === 'update') { - return this.update(dto, LeaveTypes.SICK); - } else if (dto.action === 'delete'){ - return this.delete(dto, LeaveTypes.SICK); - } - default: - throw new BadRequestException(`Unsupported leave type: ${dto.type} or action: ${dto.action}`); - } - } +// //handle distribution to the right service according to the selected type and action +// async handle(dto: UpsertLeaveRequestDto): Promise { +// switch (dto.type) { +// case LeaveTypes.HOLIDAY: +// if( dto.action === 'create'){ +// return this.holidayLeaveService.create(dto); +// } else if (dto.action === 'update') { +// return this.update(dto, LeaveTypes.HOLIDAY); +// } else if (dto.action === 'delete'){ +// return this.delete(dto, LeaveTypes.HOLIDAY); +// } +// case LeaveTypes.VACATION: +// if( dto.action === 'create'){ +// return this.vacationLeaveService.create(dto); +// } else if (dto.action === 'update') { +// return this.update(dto, LeaveTypes.VACATION); +// } else if (dto.action === 'delete'){ +// return this.delete(dto, LeaveTypes.VACATION); +// } +// case LeaveTypes.SICK: +// if( dto.action === 'create'){ +// return this.sickLeaveService.create(dto); +// } else if (dto.action === 'update') { +// return this.update(dto, LeaveTypes.SICK); +// } else if (dto.action === 'delete'){ +// return this.delete(dto, LeaveTypes.SICK); +// } +// default: +// throw new BadRequestException(`Unsupported leave type: ${dto.type} or action: ${dto.action}`); +// } +// } - async delete(dto: UpsertLeaveRequestDto, type: LeaveTypes): Promise { - const email = dto.email.trim(); - const dates = normalizeDates(dto.dates); - const employee_id = await this.emailResolver.findIdByEmail(email); - if (!dates.length) throw new BadRequestException("Dates array must not be empty"); +// async delete(dto: UpsertLeaveRequestDto, type: LeaveTypes): Promise { +// const email = dto.email.trim(); +// const dates = normalizeDates(dto.dates); +// const employee_id = await this.emailResolver.findIdByEmail(email); +// if (!dates.length) throw new BadRequestException("Dates array must not be empty"); - const rows = await this.prisma.leaveRequests.findMany({ - where: { - employee_id: employee_id, - leave_type: type, - date: { in: dates.map((d) => toDateOnly(d)) }, - }, - select: leaveRequestsSelect, - }); +// const rows = await this.prisma.leaveRequests.findMany({ +// where: { +// employee_id: employee_id, +// leave_type: type, +// date: { in: dates.map((d) => toDateOnly(d)) }, +// }, +// select: leaveRequestsSelect, +// }); - if (rows.length !== dates.length) { - const missing = dates.filter((isoDate) => !rows.some((row) => toISODateKey(row.date) === isoDate)); - throw new NotFoundException(`No Leave request found for: ${missing.join(", ")}`); - } +// if (rows.length !== dates.length) { +// const missing = dates.filter((isoDate) => !rows.some((row) => toISODateKey(row.date) === isoDate)); +// throw new NotFoundException(`No Leave request found for: ${missing.join(", ")}`); +// } - for (const row of rows) { - if (row.approval_status === LeaveApprovalStatus.APPROVED) { - const iso = toISODateKey(row.date); - await this.leaveUtils.removeShift(email, employee_id, iso, type); - } - } +// for (const row of rows) { +// if (row.approval_status === LeaveApprovalStatus.APPROVED) { +// const iso = toISODateKey(row.date); +// await this.leaveUtils.removeShift(email, employee_id, iso, type); +// } +// } - await this.prisma.leaveRequests.deleteMany({ - where: { id: { in: rows.map((row) => row.id) } }, - }); +// await this.prisma.leaveRequests.deleteMany({ +// where: { id: { in: rows.map((row) => row.id) } }, +// }); - const deleted = rows.map((row) => ({ ...mapRowToView(row), action: "delete" as const })); - return { action: "delete", leave_requests: deleted }; - } +// const deleted = rows.map((row) => ({ ...mapRowToView(row), action: "delete" as const })); +// return { action: "delete", leave_requests: deleted }; +// } - async update(dto: UpsertLeaveRequestDto, type: LeaveTypes): Promise { - const email = dto.email.trim(); - const employee_id = await this.emailResolver.findIdByEmail(email); - const bank_code = await this.typeResolver.findByType(type); - if(!bank_code) throw new NotFoundException(`bank_code not found`); - const modifier = Number(bank_code.modifier ?? 1); - const dates = normalizeDates(dto.dates); - if (!dates.length) { - throw new BadRequestException("Dates array must not be empty"); - } +// async update(dto: UpsertLeaveRequestDto, type: LeaveTypes): Promise { +// const email = dto.email.trim(); +// const employee_id = await this.emailResolver.findIdByEmail(email); +// const bank_code = await this.typeResolver.findByType(type); +// if(!bank_code) throw new NotFoundException(`bank_code not found`); +// const modifier = Number(bank_code.modifier ?? 1); +// const dates = normalizeDates(dto.dates); +// if (!dates.length) { +// throw new BadRequestException("Dates array must not be empty"); +// } - const entries = await Promise.all( - dates.map(async (iso_date) => { - const date = toDateOnly(iso_date); - const existing = await this.prisma.leaveRequests.findUnique({ - where: { - leave_per_employee_date: { - employee_id: employee_id, - leave_type: type, - date, - }, - }, - select: leaveRequestsSelect, - }); - if (!existing) throw new NotFoundException(`No Leave request found for ${iso_date}`); - return { iso_date, date, existing }; - }), - ); +// const entries = await Promise.all( +// dates.map(async (iso_date) => { +// const date = toDateOnly(iso_date); +// const existing = await this.prisma.leaveRequests.findUnique({ +// where: { +// leave_per_employee_date: { +// employee_id: employee_id, +// leave_type: type, +// date, +// }, +// }, +// select: leaveRequestsSelect, +// }); +// if (!existing) throw new NotFoundException(`No Leave request found for ${iso_date}`); +// return { iso_date, date, existing }; +// }), +// ); - const updated: LeaveRequestViewDto[] = []; +// const updated: LeaveRequestViewDto[] = []; - if (type === LeaveTypes.SICK) { - const firstExisting = entries[0].existing; - const fallbackRequested = - firstExisting.requested_hours !== null && firstExisting.requested_hours !== undefined - ? Number(firstExisting.requested_hours) - : 8; - const requested_hours_per_day = dto.requested_hours ?? fallbackRequested; - const reference_date = entries.reduce( - (latest, entry) => (entry.date > latest ? entry.date : latest), - entries[0].date, - ); - const total_payable_hours = await this.sickLogic.calculateSickLeavePay( - employee_id, - reference_date, - entries.length, - requested_hours_per_day, - modifier, - ); - let remaining_payable_hours = roundToQuarterHour(Math.max(0, total_payable_hours)); - const daily_payable_cap = roundToQuarterHour(requested_hours_per_day * modifier); +// if (type === LeaveTypes.SICK) { +// const firstExisting = entries[0].existing; +// const fallbackRequested = +// firstExisting.requested_hours !== null && firstExisting.requested_hours !== undefined +// ? Number(firstExisting.requested_hours) +// : 8; +// const requested_hours_per_day = dto.requested_hours ?? fallbackRequested; +// const reference_date = entries.reduce( +// (latest, entry) => (entry.date > latest ? entry.date : latest), +// entries[0].date, +// ); +// const total_payable_hours = await this.sickLogic.calculateSickLeavePay( +// employee_id, +// reference_date, +// entries.length, +// requested_hours_per_day, +// modifier, +// ); +// let remaining_payable_hours = roundToQuarterHour(Math.max(0, total_payable_hours)); +// const daily_payable_cap = roundToQuarterHour(requested_hours_per_day * modifier); - for (const { iso_date, existing } of entries) { - const previous_status = existing.approval_status; - const payable = Math.min(remaining_payable_hours, daily_payable_cap); - const payable_rounded = roundToQuarterHour(Math.max(0, payable)); - remaining_payable_hours = roundToQuarterHour( - Math.max(0, remaining_payable_hours - payable_rounded), - ); +// for (const { iso_date, existing } of entries) { +// const previous_status = existing.approval_status; +// const payable = Math.min(remaining_payable_hours, daily_payable_cap); +// const payable_rounded = roundToQuarterHour(Math.max(0, payable)); +// remaining_payable_hours = roundToQuarterHour( +// Math.max(0, remaining_payable_hours - payable_rounded), +// ); - const row = await this.prisma.leaveRequests.update({ - where: { id: existing.id }, - data: { - comment: dto.comment ?? existing.comment, - requested_hours: requested_hours_per_day, - payable_hours: payable_rounded, - bank_code_id: bank_code.id, - approval_status: dto.approval_status ?? existing.approval_status, - }, - select: leaveRequestsSelect, - }); +// const row = await this.prisma.leaveRequests.update({ +// where: { id: existing.id }, +// data: { +// comment: dto.comment ?? existing.comment, +// requested_hours: requested_hours_per_day, +// payable_hours: payable_rounded, +// bank_code_id: bank_code.id, +// approval_status: dto.approval_status ?? existing.approval_status, +// }, +// select: leaveRequestsSelect, +// }); - const was_approved = previous_status === LeaveApprovalStatus.APPROVED; - const is_approved = row.approval_status === LeaveApprovalStatus.APPROVED; - const hours = Number(row.payable_hours ?? row.requested_hours ?? 0); +// const was_approved = previous_status === LeaveApprovalStatus.APPROVED; +// const is_approved = row.approval_status === LeaveApprovalStatus.APPROVED; +// const hours = Number(row.payable_hours ?? row.requested_hours ?? 0); - if (!was_approved && is_approved) { - await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment); - } else if (was_approved && !is_approved) { - await this.leaveUtils.removeShift(email, employee_id, iso_date, type); - } else if (was_approved && is_approved) { - await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment); - } - updated.push({ ...mapRowToView(row), action: "update" }); - } - return { action: "update", leave_requests: updated }; - } +// if (!was_approved && is_approved) { +// await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment); +// } else if (was_approved && !is_approved) { +// await this.leaveUtils.removeShift(email, employee_id, iso_date, type); +// } else if (was_approved && is_approved) { +// await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment); +// } +// updated.push({ ...mapRowToView(row), action: "update" }); +// } +// return { action: "update", leave_requests: updated }; +// } - for (const { iso_date, date, existing } of entries) { - const previous_status = existing.approval_status; - const fallbackRequested = - existing.requested_hours !== null && existing.requested_hours !== undefined - ? Number(existing.requested_hours) - : 8; - const requested_hours = dto.requested_hours ?? fallbackRequested; +// for (const { iso_date, date, existing } of entries) { +// const previous_status = existing.approval_status; +// const fallbackRequested = +// existing.requested_hours !== null && existing.requested_hours !== undefined +// ? Number(existing.requested_hours) +// : 8; +// const requested_hours = dto.requested_hours ?? fallbackRequested; - let payable: number; - switch (type) { - case LeaveTypes.HOLIDAY: - payable = await this.holidayService.calculateHolidayPay(email, date, modifier); - break; - case LeaveTypes.VACATION: { - const days_requested = requested_hours / 8; - payable = await this.vacationLogic.calculateVacationPay( - employee_id, - date, - Math.max(0, days_requested), - modifier, - ); - break; - } - default: - payable = existing.payable_hours !== null && existing.payable_hours !== undefined - ? Number(existing.payable_hours) - : requested_hours; - } +// let payable: number; +// switch (type) { +// case LeaveTypes.HOLIDAY: +// payable = await this.holidayService.calculateHolidayPay(email, date, modifier); +// break; +// case LeaveTypes.VACATION: { +// const days_requested = requested_hours / 8; +// payable = await this.vacationLogic.calculateVacationPay( +// employee_id, +// date, +// Math.max(0, days_requested), +// modifier, +// ); +// break; +// } +// default: +// payable = existing.payable_hours !== null && existing.payable_hours !== undefined +// ? Number(existing.payable_hours) +// : requested_hours; +// } - const row = await this.prisma.leaveRequests.update({ - where: { id: existing.id }, - data: { - requested_hours, - comment: dto.comment ?? existing.comment, - payable_hours: payable, - bank_code_id: bank_code.id, - approval_status: dto.approval_status ?? existing.approval_status, - }, - select: leaveRequestsSelect, - }); +// const row = await this.prisma.leaveRequests.update({ +// where: { id: existing.id }, +// data: { +// requested_hours, +// comment: dto.comment ?? existing.comment, +// payable_hours: payable, +// bank_code_id: bank_code.id, +// approval_status: dto.approval_status ?? existing.approval_status, +// }, +// select: leaveRequestsSelect, +// }); - const was_approved = previous_status === LeaveApprovalStatus.APPROVED; - const is_approved = row.approval_status === LeaveApprovalStatus.APPROVED; - const hours = Number(row.payable_hours ?? row.requested_hours ?? 0); +// const was_approved = previous_status === LeaveApprovalStatus.APPROVED; +// const is_approved = row.approval_status === LeaveApprovalStatus.APPROVED; +// const hours = Number(row.payable_hours ?? row.requested_hours ?? 0); - if (!was_approved && is_approved) { - await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment); - } else if (was_approved && !is_approved) { - await this.leaveUtils.removeShift(email, employee_id, iso_date, type); - } else if (was_approved && is_approved) { - await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment); - } - updated.push({ ...mapRowToView(row), action: "update" }); - } - return { action: "update", leave_requests: updated }; - } -} +// if (!was_approved && is_approved) { +// await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment); +// } else if (was_approved && !is_approved) { +// await this.leaveUtils.removeShift(email, employee_id, iso_date, type); +// } else if (was_approved && is_approved) { +// await this.leaveUtils.syncShift(email, employee_id, iso_date, hours, type, row.comment); +// } +// updated.push({ ...mapRowToView(row), action: "update" }); +// } +// return { action: "update", leave_requests: updated }; +// } +// } diff --git a/src/modules/leave-requests/services/sick-leave-requests.service.ts b/src/modules/leave-requests/services/sick-leave-requests.service.ts index dc513fa..a4554b1 100644 --- a/src/modules/leave-requests/services/sick-leave-requests.service.ts +++ b/src/modules/leave-requests/services/sick-leave-requests.service.ts @@ -1,98 +1,98 @@ -import { UpsertLeaveRequestDto, UpsertResult } from "../dtos/upsert-leave-request.dto"; -import { LeaveRequestViewDto } from "../dtos/leave-request-view.dto"; -import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; -import { LeaveApprovalStatus, LeaveTypes } from "@prisma/client"; -import { leaveRequestsSelect } from "../utils/leave-requests.select"; -import { mapRowToView } from "../mappers/leave-requests.mapper"; -import { PrismaService } from "src/prisma/prisma.service"; -import { SickLeaveService } from "src/modules/business-logics/services/sick-leave.service"; -import { roundToQuarterHour } from "src/common/utils/date-utils"; -import { LeaveRequestsUtils } from "../utils/leave-request.util"; -import { normalizeDates, toDateOnly } from "src/modules/shared/helpers/date-time.helpers"; -import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; -import { BankCodesResolver } from "src/modules/shared/utils/resolve-bank-type-id.utils"; +// import { UpsertLeaveRequestDto, UpsertResult } from "../dtos/upsert-leave-request.dto"; +// import { LeaveRequestViewDto } from "../dtos/leave-request-view.dto"; +// import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; +// import { LeaveApprovalStatus, LeaveTypes } from "@prisma/client"; +// import { leaveRequestsSelect } from "../utils/leave-requests.select"; +// import { mapRowToView } from "../mappers/leave-requests.mapper"; +// import { PrismaService } from "src/prisma/prisma.service"; +// import { SickLeaveService } from "src/modules/business-logics/services/sick-leave.service"; +// import { roundToQuarterHour } from "src/common/utils/date-utils"; +// import { LeaveRequestsUtils } from "../utils/leave-request.util"; +// import { normalizeDates, toDateOnly } from "src/modules/shared/helpers/date-time.helpers"; +// import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; +// import { BankCodesResolver } from "src/modules/shared/utils/resolve-bank-type-id.utils"; -@Injectable() -export class SickLeaveRequestsService { - constructor( - private readonly prisma: PrismaService, - private readonly sickService: SickLeaveService, - private readonly leaveUtils: LeaveRequestsUtils, - private readonly emailResolver: EmailToIdResolver, - private readonly typeResolver: BankCodesResolver, - ) {} +// @Injectable() +// export class SickLeaveRequestsService { +// constructor( +// private readonly prisma: PrismaService, +// private readonly sickService: SickLeaveService, +// private readonly leaveUtils: LeaveRequestsUtils, +// private readonly emailResolver: EmailToIdResolver, +// private readonly typeResolver: BankCodesResolver, +// ) {} - async create(dto: UpsertLeaveRequestDto): Promise { - const email = dto.email.trim(); - const employee_id = await this.emailResolver.findIdByEmail(email); - const bank_code = await this.typeResolver.findByType(LeaveTypes.SICK); - if(!bank_code) throw new NotFoundException(`bank_code not found`); +// async create(dto: UpsertLeaveRequestDto): Promise { +// const email = dto.email.trim(); +// const employee_id = await this.emailResolver.findIdByEmail(email); +// const bank_code = await this.typeResolver.findByType(LeaveTypes.SICK); +// if(!bank_code) throw new NotFoundException(`bank_code not found`); - const modifier = bank_code.modifier ?? 1; - const dates = normalizeDates(dto.dates); - if (!dates.length) throw new BadRequestException("Dates array must not be empty"); - const requested_hours_per_day = dto.requested_hours ?? 8; +// const modifier = bank_code.modifier ?? 1; +// const dates = normalizeDates(dto.dates); +// if (!dates.length) throw new BadRequestException("Dates array must not be empty"); +// const requested_hours_per_day = dto.requested_hours ?? 8; - const entries = dates.map((iso) => ({ iso, date: toDateOnly(iso) })); - const reference_date = entries.reduce( - (latest, entry) => (entry.date > latest ? entry.date : latest), - entries[0].date, - ); - const total_payable_hours = await this.sickService.calculateSickLeavePay( - employee_id, - reference_date, - entries.length, - requested_hours_per_day, - modifier, - ); - let remaining_payable_hours = roundToQuarterHour(Math.max(0, total_payable_hours)); - const daily_payable_cap = roundToQuarterHour(requested_hours_per_day * modifier); +// const entries = dates.map((iso) => ({ iso, date: toDateOnly(iso) })); +// const reference_date = entries.reduce( +// (latest, entry) => (entry.date > latest ? entry.date : latest), +// entries[0].date, +// ); +// const total_payable_hours = await this.sickService.calculateSickLeavePay( +// employee_id, +// reference_date, +// entries.length, +// requested_hours_per_day, +// modifier, +// ); +// let remaining_payable_hours = roundToQuarterHour(Math.max(0, total_payable_hours)); +// const daily_payable_cap = roundToQuarterHour(requested_hours_per_day * modifier); - const created: LeaveRequestViewDto[] = []; +// const created: LeaveRequestViewDto[] = []; - for (const { iso, date } of entries) { - const existing = await this.prisma.leaveRequests.findUnique({ - where: { - leave_per_employee_date: { - employee_id: employee_id, - leave_type: LeaveTypes.SICK, - date, - }, - }, - select: { id: true }, - }); - if (existing) { - throw new BadRequestException(`Sick request already exists for ${iso}`); - } +// for (const { iso, date } of entries) { +// const existing = await this.prisma.leaveRequests.findUnique({ +// where: { +// leave_per_employee_date: { +// employee_id: employee_id, +// leave_type: LeaveTypes.SICK, +// date, +// }, +// }, +// select: { id: true }, +// }); +// if (existing) { +// throw new BadRequestException(`Sick request already exists for ${iso}`); +// } - const payable = Math.min(remaining_payable_hours, daily_payable_cap); - const payable_rounded = roundToQuarterHour(Math.max(0, payable)); - remaining_payable_hours = roundToQuarterHour( - Math.max(0, remaining_payable_hours - payable_rounded), - ); +// const payable = Math.min(remaining_payable_hours, daily_payable_cap); +// const payable_rounded = roundToQuarterHour(Math.max(0, payable)); +// remaining_payable_hours = roundToQuarterHour( +// Math.max(0, remaining_payable_hours - payable_rounded), +// ); - const row = await this.prisma.leaveRequests.create({ - data: { - employee_id: employee_id, - bank_code_id: bank_code.id, - leave_type: LeaveTypes.SICK, - comment: dto.comment ?? "", - requested_hours: requested_hours_per_day, - payable_hours: payable_rounded, - approval_status: dto.approval_status ?? LeaveApprovalStatus.PENDING, - date, - }, - select: leaveRequestsSelect, - }); +// const row = await this.prisma.leaveRequests.create({ +// data: { +// employee_id: employee_id, +// bank_code_id: bank_code.id, +// leave_type: LeaveTypes.SICK, +// comment: dto.comment ?? "", +// requested_hours: requested_hours_per_day, +// payable_hours: payable_rounded, +// approval_status: dto.approval_status ?? LeaveApprovalStatus.PENDING, +// date, +// }, +// select: leaveRequestsSelect, +// }); - const hours = Number(row.payable_hours ?? row.requested_hours ?? 0); - if (row.approval_status === LeaveApprovalStatus.APPROVED) { - await this.leaveUtils.syncShift(email, employee_id, iso, hours,LeaveTypes.SICK, row.comment); - } +// const hours = Number(row.payable_hours ?? row.requested_hours ?? 0); +// if (row.approval_status === LeaveApprovalStatus.APPROVED) { +// await this.leaveUtils.syncShift(email, employee_id, iso, hours,LeaveTypes.SICK, row.comment); +// } - created.push({ ...mapRowToView(row), action: "create" }); - } +// created.push({ ...mapRowToView(row), action: "create" }); +// } - return { action: "create", leave_requests: created }; - } -} +// return { action: "create", leave_requests: created }; +// } +// } diff --git a/src/modules/leave-requests/services/vacation-leave-requests.service.ts b/src/modules/leave-requests/services/vacation-leave-requests.service.ts index 8d90b6f..34223f5 100644 --- a/src/modules/leave-requests/services/vacation-leave-requests.service.ts +++ b/src/modules/leave-requests/services/vacation-leave-requests.service.ts @@ -1,93 +1,93 @@  -import { UpsertLeaveRequestDto, UpsertResult } from "../dtos/upsert-leave-request.dto"; -import { LeaveRequestViewDto } from "../dtos/leave-request-view.dto"; -import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; -import { LeaveApprovalStatus, LeaveTypes } from "@prisma/client"; -import { VacationService } from "src/modules/business-logics/services/vacation.service"; -import { PrismaService } from "src/prisma/prisma.service"; -import { mapRowToView } from "../mappers/leave-requests.mapper"; -import { leaveRequestsSelect } from "../utils/leave-requests.select"; -import { roundToQuarterHour } from "src/common/utils/date-utils"; -import { LeaveRequestsUtils } from "../utils/leave-request.util"; -import { normalizeDates, toDateOnly } from "src/modules/shared/helpers/date-time.helpers"; -import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; -import { BankCodesResolver } from "src/modules/shared/utils/resolve-bank-type-id.utils"; +// import { UpsertLeaveRequestDto, UpsertResult } from "../dtos/upsert-leave-request.dto"; +// import { LeaveRequestViewDto } from "../dtos/leave-request-view.dto"; +// import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; +// import { LeaveApprovalStatus, LeaveTypes } from "@prisma/client"; +// import { VacationService } from "src/modules/business-logics/services/vacation.service"; +// import { PrismaService } from "src/prisma/prisma.service"; +// import { mapRowToView } from "../mappers/leave-requests.mapper"; +// import { leaveRequestsSelect } from "../utils/leave-requests.select"; +// import { roundToQuarterHour } from "src/common/utils/date-utils"; +// import { LeaveRequestsUtils } from "../utils/leave-request.util"; +// import { normalizeDates, toDateOnly } from "src/modules/shared/helpers/date-time.helpers"; +// import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; +// import { BankCodesResolver } from "src/modules/shared/utils/resolve-bank-type-id.utils"; -@Injectable() -export class VacationLeaveRequestsService { - constructor( - private readonly prisma: PrismaService, - private readonly vacationService: VacationService, - private readonly leaveUtils: LeaveRequestsUtils, - private readonly emailResolver: EmailToIdResolver, - private readonly typeResolver: BankCodesResolver, - ) {} +// @Injectable() +// export class VacationLeaveRequestsService { +// constructor( +// private readonly prisma: PrismaService, +// private readonly vacationService: VacationService, +// private readonly leaveUtils: LeaveRequestsUtils, +// private readonly emailResolver: EmailToIdResolver, +// private readonly typeResolver: BankCodesResolver, +// ) {} - async create(dto: UpsertLeaveRequestDto): Promise { - const email = dto.email.trim(); - const employee_id = await this.emailResolver.findIdByEmail(email); - const bank_code = await this.typeResolver.findByType(LeaveTypes.VACATION); - if(!bank_code) throw new NotFoundException(`bank_code not found`); +// async create(dto: UpsertLeaveRequestDto): Promise { +// const email = dto.email.trim(); +// const employee_id = await this.emailResolver.findIdByEmail(email); +// const bank_code = await this.typeResolver.findByType(LeaveTypes.VACATION); +// if(!bank_code) throw new NotFoundException(`bank_code not found`); - const modifier = bank_code.modifier ?? 1; - const dates = normalizeDates(dto.dates); - const requested_hours_per_day = dto.requested_hours ?? 8; - if (!dates.length) throw new BadRequestException("Dates array must not be empty"); +// const modifier = bank_code.modifier ?? 1; +// const dates = normalizeDates(dto.dates); +// const requested_hours_per_day = dto.requested_hours ?? 8; +// if (!dates.length) throw new BadRequestException("Dates array must not be empty"); - const entries = dates - .map((iso) => ({ iso, date: toDateOnly(iso) })) - .sort((a, b) => a.date.getTime() - b.date.getTime()); - const start_date = entries[0].date; - const total_payable_hours = await this.vacationService.calculateVacationPay( - employee_id, - start_date, - entries.length, - modifier, - ); - let remaining_payable_hours = roundToQuarterHour(Math.max(0, total_payable_hours)); - const daily_payable_cap = roundToQuarterHour(requested_hours_per_day * modifier); +// const entries = dates +// .map((iso) => ({ iso, date: toDateOnly(iso) })) +// .sort((a, b) => a.date.getTime() - b.date.getTime()); +// const start_date = entries[0].date; +// const total_payable_hours = await this.vacationService.calculateVacationPay( +// employee_id, +// start_date, +// entries.length, +// modifier, +// ); +// let remaining_payable_hours = roundToQuarterHour(Math.max(0, total_payable_hours)); +// const daily_payable_cap = roundToQuarterHour(requested_hours_per_day * modifier); - const created: LeaveRequestViewDto[] = []; +// const created: LeaveRequestViewDto[] = []; - for (const { iso, date } of entries) { - const existing = await this.prisma.leaveRequests.findUnique({ - where: { - leave_per_employee_date: { - employee_id: employee_id, - leave_type: LeaveTypes.VACATION, - date, - }, - }, - select: { id: true }, - }); - if (existing) throw new BadRequestException(`Vacation request already exists for ${iso}`); +// for (const { iso, date } of entries) { +// const existing = await this.prisma.leaveRequests.findUnique({ +// where: { +// leave_per_employee_date: { +// employee_id: employee_id, +// leave_type: LeaveTypes.VACATION, +// date, +// }, +// }, +// select: { id: true }, +// }); +// if (existing) throw new BadRequestException(`Vacation request already exists for ${iso}`); - const payable = Math.min(remaining_payable_hours, daily_payable_cap); - const payable_rounded = roundToQuarterHour(Math.max(0, payable)); - remaining_payable_hours = roundToQuarterHour( - Math.max(0, remaining_payable_hours - payable_rounded), - ); +// const payable = Math.min(remaining_payable_hours, daily_payable_cap); +// const payable_rounded = roundToQuarterHour(Math.max(0, payable)); +// remaining_payable_hours = roundToQuarterHour( +// Math.max(0, remaining_payable_hours - payable_rounded), +// ); - const row = await this.prisma.leaveRequests.create({ - data: { - employee_id: employee_id, - bank_code_id: bank_code.id, - payable_hours: payable_rounded, - requested_hours: requested_hours_per_day, - leave_type: LeaveTypes.VACATION, - comment: dto.comment ?? "", - approval_status: dto.approval_status ?? LeaveApprovalStatus.PENDING, - date, - }, - select: leaveRequestsSelect, - }); +// const row = await this.prisma.leaveRequests.create({ +// data: { +// employee_id: employee_id, +// bank_code_id: bank_code.id, +// payable_hours: payable_rounded, +// requested_hours: requested_hours_per_day, +// leave_type: LeaveTypes.VACATION, +// comment: dto.comment ?? "", +// approval_status: dto.approval_status ?? LeaveApprovalStatus.PENDING, +// date, +// }, +// select: leaveRequestsSelect, +// }); - const hours = Number(row.payable_hours ?? row.requested_hours ?? 0); - if (row.approval_status === LeaveApprovalStatus.APPROVED) { - await this.leaveUtils.syncShift(email, employee_id, iso, hours, LeaveTypes.VACATION, row.comment); - } - created.push({ ...mapRowToView(row), action: "create" }); - } - return { action: "create", leave_requests: created }; - } -} +// const hours = Number(row.payable_hours ?? row.requested_hours ?? 0); +// if (row.approval_status === LeaveApprovalStatus.APPROVED) { +// await this.leaveUtils.syncShift(email, employee_id, iso, hours, LeaveTypes.VACATION, row.comment); +// } +// created.push({ ...mapRowToView(row), action: "create" }); +// } +// return { action: "create", leave_requests: created }; +// } +// } diff --git a/src/modules/leave-requests/utils/leave-request.util.ts b/src/modules/leave-requests/utils/leave-request.util.ts index 129742f..d01ccf2 100644 --- a/src/modules/leave-requests/utils/leave-request.util.ts +++ b/src/modules/leave-requests/utils/leave-request.util.ts @@ -1,105 +1,104 @@ -import { hhmmFromLocal, toDateOnly, toStringFromDate } from "src/modules/shared/helpers/date-time.helpers"; -import { BadRequestException, Injectable } from "@nestjs/common"; -import { ShiftsCommandService } from "src/modules/shifts/_deprecated-files/shifts-command.service"; -import { PrismaService } from "src/prisma/prisma.service"; -import { LeaveTypes } from "@prisma/client"; -import { UpsertAction } from "src/modules/shared/types/upsert-actions.types"; +// import { hhmmFromLocal, toDateOnly, toStringFromDate } from "src/modules/shared/helpers/date-time.helpers"; +// import { BadRequestException, Injectable } from "@nestjs/common"; +// import { PrismaService } from "src/prisma/prisma.service"; +// import { LeaveTypes } from "@prisma/client"; +// import { UpsertAction } from "src/modules/shared/types/upsert-actions.types"; -@Injectable() -export class LeaveRequestsUtils { - constructor( - private readonly prisma: PrismaService, - private readonly shiftsCommand: ShiftsCommandService, - ){} +// @Injectable() +// export class LeaveRequestsUtils { +// constructor( +// private readonly prisma: PrismaService, +// private readonly shiftsCommand: ShiftsCommandService, +// ){} - async syncShift( - email: string, - employee_id: number, - date: string, - hours: number, - type: LeaveTypes, - comment?: string, - ) { - if (hours <= 0) return; +// async syncShift( +// email: string, +// employee_id: number, +// date: string, +// hours: number, +// type: LeaveTypes, +// comment?: string, +// ) { +// if (hours <= 0) return; - const duration_minutes = Math.round(hours * 60); - if (duration_minutes > 8 * 60) { - throw new BadRequestException("Amount of hours cannot exceed 8 hours per day."); - } - const date_only = toDateOnly(date); - const yyyy_mm_dd = toStringFromDate(date_only); +// const duration_minutes = Math.round(hours * 60); +// if (duration_minutes > 8 * 60) { +// throw new BadRequestException("Amount of hours cannot exceed 8 hours per day."); +// } +// const date_only = toDateOnly(date); +// const yyyy_mm_dd = toStringFromDate(date_only); - const start_minutes = 8 * 60; - const end_minutes = start_minutes + duration_minutes; - const toHHmm = (total: number) => - `${String(Math.floor(total / 60)).padStart(2, "0")}:${String(total % 60).padStart(2, "0")}`; +// const start_minutes = 8 * 60; +// const end_minutes = start_minutes + duration_minutes; +// const toHHmm = (total: number) => +// `${String(Math.floor(total / 60)).padStart(2, "0")}:${String(total % 60).padStart(2, "0")}`; - const existing = await this.prisma.shifts.findFirst({ - where: { - date: date_only, - bank_code: { type }, - timesheet: { employee_id: employee_id }, - }, - include: { bank_code: true }, - }); +// const existing = await this.prisma.shifts.findFirst({ +// where: { +// date: date_only, +// bank_code: { type }, +// timesheet: { employee_id: employee_id }, +// }, +// include: { bank_code: true }, +// }); - const action: UpsertAction = existing ? 'update' : 'create'; +// const action: UpsertAction = existing ? 'update' : 'create'; - await this.shiftsCommand.upsertShifts(email, action, { - old_shift: existing - ? { - date: yyyy_mm_dd, - start_time: existing.start_time.toISOString().slice(11, 16), - end_time: existing.end_time.toISOString().slice(11, 16), - type: existing.bank_code?.type ?? type, - is_remote: existing.is_remote, - is_approved:existing.is_approved, - comment: existing.comment ?? undefined, - } - : undefined, - new_shift: { - date: yyyy_mm_dd, - start_time: toHHmm(start_minutes), - end_time: toHHmm(end_minutes), - is_remote: existing?.is_remote ?? false, - is_approved:existing?.is_approved ?? false, - comment: comment ?? existing?.comment ?? "", - type: type, - }, - }); - } +// await this.shiftsCommand.upsertShifts(email, action, { +// old_shift: existing +// ? { +// date: yyyy_mm_dd, +// start_time: existing.start_time.toISOString().slice(11, 16), +// end_time: existing.end_time.toISOString().slice(11, 16), +// type: existing.bank_code?.type ?? type, +// is_remote: existing.is_remote, +// is_approved:existing.is_approved, +// comment: existing.comment ?? undefined, +// } +// : undefined, +// new_shift: { +// date: yyyy_mm_dd, +// start_time: toHHmm(start_minutes), +// end_time: toHHmm(end_minutes), +// is_remote: existing?.is_remote ?? false, +// is_approved:existing?.is_approved ?? false, +// comment: comment ?? existing?.comment ?? "", +// type: type, +// }, +// }); +// } - async removeShift( - email: string, - employee_id: number, - iso_date: string, - type: LeaveTypes, - ) { - const date_only = toDateOnly(iso_date); - const yyyy_mm_dd = toStringFromDate(date_only); - const existing = await this.prisma.shifts.findFirst({ - where: { - date: date_only, - bank_code: { type }, - timesheet: { employee_id: employee_id }, - }, - include: { bank_code: true }, - }); - if (!existing) return; +// async removeShift( +// email: string, +// employee_id: number, +// iso_date: string, +// type: LeaveTypes, +// ) { +// const date_only = toDateOnly(iso_date); +// const yyyy_mm_dd = toStringFromDate(date_only); +// const existing = await this.prisma.shifts.findFirst({ +// where: { +// date: date_only, +// bank_code: { type }, +// timesheet: { employee_id: employee_id }, +// }, +// include: { bank_code: true }, +// }); +// if (!existing) return; - await this.shiftsCommand.upsertShifts(email, 'delete', { - old_shift: { - date: yyyy_mm_dd, - start_time: hhmmFromLocal(existing.start_time), - end_time: hhmmFromLocal(existing.end_time), - type: existing.bank_code?.type ?? type, - is_remote: existing.is_remote, - is_approved:existing.is_approved, - comment: existing.comment ?? undefined, - }, - }); - } +// await this.shiftsCommand.upsertShifts(email, 'delete', { +// old_shift: { +// date: yyyy_mm_dd, +// start_time: hhmmFromLocal(existing.start_time), +// end_time: hhmmFromLocal(existing.end_time), +// type: existing.bank_code?.type ?? type, +// is_remote: existing.is_remote, +// is_approved:existing.is_approved, +// comment: existing.comment ?? undefined, +// }, +// }); +// } -} +// } diff --git a/src/modules/pay-periods/pay-periods.module.ts b/src/modules/pay-periods/pay-periods.module.ts index 401b53f..5f73d93 100644 --- a/src/modules/pay-periods/pay-periods.module.ts +++ b/src/modules/pay-periods/pay-periods.module.ts @@ -1,33 +1,27 @@ -import { PrismaModule } from "src/prisma/prisma.module"; -import { PayPeriodsController } from "./controllers/pay-periods.controller"; -import { Module } from "@nestjs/common"; -import { PayPeriodsCommandService } from "./services/pay-periods-command.service"; -import { PayPeriodsQueryService } from "./services/pay-periods-query.service"; -import { TimesheetsModule } from "../timesheets/timesheets.module"; -import { TimesheetsCommandService } from "../timesheets/~misc_deprecated-files/timesheets-command.service"; -import { ExpensesCommandService } from "../expenses/services/expenses-command.service"; -import { ShiftsCommandService } from "../shifts/_deprecated-files/shifts-command.service"; -import { SharedModule } from "../shared/shared.module"; -import { PrismaService } from "src/prisma/prisma.service"; -import { BusinessLogicsModule } from "../business-logics/business-logics.module"; -import { ShiftsHelpersService } from "../shifts/_deprecated-files/shifts.helpers"; +// import { PrismaModule } from "src/prisma/prisma.module"; +// import { PayPeriodsController } from "./controllers/pay-periods.controller"; +// import { Module } from "@nestjs/common"; +// import { PayPeriodsCommandService } from "./services/pay-periods-command.service"; +// import { PayPeriodsQueryService } from "./services/pay-periods-query.service"; +// import { TimesheetsModule } from "../timesheets/timesheets.module"; +// import { ExpensesCommandService } from "../expenses/services/expenses-command.service"; +// import { SharedModule } from "../shared/shared.module"; +// import { PrismaService } from "src/prisma/prisma.service"; +// import { BusinessLogicsModule } from "../business-logics/business-logics.module"; -@Module({ - imports: [PrismaModule, TimesheetsModule, SharedModule, BusinessLogicsModule], - providers: [ - PayPeriodsQueryService, - PayPeriodsCommandService, - TimesheetsCommandService, - ExpensesCommandService, - ShiftsCommandService, - PrismaService, - ShiftsHelpersService, - ], - controllers: [PayPeriodsController], - exports: [ - PayPeriodsQueryService, - PayPeriodsCommandService, - ] -}) +// @Module({ +// imports: [PrismaModule, TimesheetsModule, SharedModule, BusinessLogicsModule], +// providers: [ +// PayPeriodsQueryService, +// PayPeriodsCommandService, +// ExpensesCommandService, +// PrismaService, +// ], +// controllers: [PayPeriodsController], +// exports: [ +// PayPeriodsQueryService, +// PayPeriodsCommandService, +// ] +// }) -export class PayperiodsModule {} \ No newline at end of file +// export class PayperiodsModule {} \ No newline at end of file diff --git a/src/modules/pay-periods/services/pay-periods-command.service.ts b/src/modules/pay-periods/services/pay-periods-command.service.ts index 9fc2caa..a1a4b5a 100644 --- a/src/modules/pay-periods/services/pay-periods-command.service.ts +++ b/src/modules/pay-periods/services/pay-periods-command.service.ts @@ -1,14 +1,14 @@ import { BadRequestException, ForbiddenException, Injectable, NotFoundException } from "@nestjs/common"; -import { TimesheetsCommandService } from "src/modules/timesheets/~misc_deprecated-files/timesheets-command.service"; import { PrismaService } from "src/prisma/prisma.service"; import { BulkCrewApprovalDto } from "../dtos/bulk-crew-approval.dto"; import { PayPeriodsQueryService } from "./pay-periods-query.service"; +import { TimesheetApprovalService } from "src/modules/timesheets/services/timesheet-approval.service"; @Injectable() export class PayPeriodsCommandService { constructor( private readonly prisma: PrismaService, - private readonly timesheets_approval: TimesheetsCommandService, + private readonly timesheets_approval: TimesheetApprovalService, private readonly query: PayPeriodsQueryService, ) {} diff --git a/src/modules/timesheets/services/timesheet-approval.service.ts b/src/modules/timesheets/services/timesheet-approval.service.ts new file mode 100644 index 0000000..c22d0dc --- /dev/null +++ b/src/modules/timesheets/services/timesheet-approval.service.ts @@ -0,0 +1,38 @@ +import { Injectable } from "@nestjs/common"; +import { Prisma, Timesheets } from "@prisma/client"; +import { BaseApprovalService } from "src/common/shared/base-approval.service"; +import { PrismaService } from "src/prisma/prisma.service"; + + @Injectable() + export class TimesheetApprovalService extends BaseApprovalService{ + constructor(prisma: PrismaService){super(prisma)} + //_____________________________________________________________________________________________ + // APPROVAL AND DELEGATE METHODS + //_____________________________________________________________________________________________ + protected get delegate() { + return this.prisma.timesheets; + } + + protected delegateFor(transaction: Prisma.TransactionClient) { + return transaction.timesheets; + } + + async updateApproval(id: number, isApproved: boolean): Promise { + return this.prisma.$transaction((transaction) => + this.updateApprovalWithTransaction(transaction, id, isApproved), + ); + } + + async cascadeApprovalWithtx(transaction: Prisma.TransactionClient, timesheetId: number, isApproved: boolean): Promise { + const timesheet = await this.updateApprovalWithTransaction(transaction, timesheetId, isApproved); + await transaction.shifts.updateMany({ + where: { timesheet_id: timesheetId }, + data: { is_approved: isApproved }, + }); + await transaction.expenses.updateManyAndReturn({ + where: { timesheet_id: timesheetId }, + data: { is_approved: isApproved }, + }); + return timesheet; + } + } \ No newline at end of file diff --git a/src/modules/timesheets/~misc_deprecated-files/create-timesheet.dto.ts b/src/modules/timesheets/~misc_deprecated-files/create-timesheet.dto.ts index a6fd0b2..ceb3807 100644 --- a/src/modules/timesheets/~misc_deprecated-files/create-timesheet.dto.ts +++ b/src/modules/timesheets/~misc_deprecated-files/create-timesheet.dto.ts @@ -1,33 +1,33 @@ -import { Type } from "class-transformer"; -import { IsArray, IsOptional, IsString, Length, Matches, ValidateNested } from "class-validator"; +// import { Type } from "class-transformer"; +// import { IsArray, IsOptional, IsString, Length, Matches, ValidateNested } from "class-validator"; -export class CreateTimesheetDto { +// export class CreateTimesheetDto { - @IsString() - @Matches(/^\d{4}-\d{2}-\d{2}$/) - date!: string; +// @IsString() +// @Matches(/^\d{4}-\d{2}-\d{2}$/) +// date!: string; - @IsString() - @Length(1,64) - type!: string; +// @IsString() +// @Length(1,64) +// type!: string; - @IsString() - @Matches(/^\d{2}:\d{2}$/) - start_time!: string; +// @IsString() +// @Matches(/^\d{2}:\d{2}$/) +// start_time!: string; - @IsString() - @Matches(/^\d{2}:\d{2}$/) - end_time!: string; +// @IsString() +// @Matches(/^\d{2}:\d{2}$/) +// end_time!: string; - @IsOptional() - @IsString() - @Length(0,512) - comment?: string; -} +// @IsOptional() +// @IsString() +// @Length(0,512) +// comment?: string; +// } -export class CreateWeekShiftsDto { - @IsArray() - @ValidateNested({each:true}) - @Type(()=> CreateTimesheetDto) - shifts!: CreateTimesheetDto[]; -} +// export class CreateWeekShiftsDto { +// @IsArray() +// @ValidateNested({each:true}) +// @Type(()=> CreateTimesheetDto) +// shifts!: CreateTimesheetDto[]; +// } diff --git a/src/modules/timesheets/~misc_deprecated-files/search-timesheet.dto.ts b/src/modules/timesheets/~misc_deprecated-files/search-timesheet.dto.ts index a4bf613..6e1ba12 100644 --- a/src/modules/timesheets/~misc_deprecated-files/search-timesheet.dto.ts +++ b/src/modules/timesheets/~misc_deprecated-files/search-timesheet.dto.ts @@ -1,20 +1,20 @@ -import { Type } from "class-transformer"; -import { IsBoolean, IsInt, IsOptional } from "class-validator"; +// import { Type } from "class-transformer"; +// import { IsBoolean, IsInt, IsOptional } from "class-validator"; -export class SearchTimesheetDto { - @IsOptional() - @Type(() => Number) - @IsInt() - timesheet_id?: number; +// export class SearchTimesheetDto { +// @IsOptional() +// @Type(() => Number) +// @IsInt() +// timesheet_id?: number; - @IsOptional() - @Type(()=> Number) - @IsInt() - employee_id?: number; +// @IsOptional() +// @Type(()=> Number) +// @IsInt() +// employee_id?: number; - @IsOptional() - @Type(()=> Boolean) - @IsBoolean() - is_approved?: boolean; -} \ No newline at end of file +// @IsOptional() +// @Type(()=> Boolean) +// @IsBoolean() +// is_approved?: boolean; +// } \ No newline at end of file diff --git a/src/modules/timesheets/~misc_deprecated-files/timesheet-period.dto.ts b/src/modules/timesheets/~misc_deprecated-files/timesheet-period.dto.ts index 333716b..004026e 100644 --- a/src/modules/timesheets/~misc_deprecated-files/timesheet-period.dto.ts +++ b/src/modules/timesheets/~misc_deprecated-files/timesheet-period.dto.ts @@ -1,75 +1,75 @@ -export class TimesheetDto { - start_day: string; - end_day: string; - label: string; - shifts: ShiftDto[]; - expenses: ExpenseDto[] - is_approved: boolean; -} +// export class TimesheetDto { +// start_day: string; +// end_day: string; +// label: string; +// shifts: ShiftDto[]; +// expenses: ExpenseDto[] +// is_approved: boolean; +// } -export class ShiftDto { - date: string; - type: string; - start_time: string; - end_time : string; - comment: string; - is_approved: boolean; - is_remote: boolean; -} +// export class ShiftDto { +// date: string; +// type: string; +// start_time: string; +// end_time : string; +// comment: string; +// is_approved: boolean; +// is_remote: boolean; +// } -export class ExpenseDto { - type: string; - amount: number; - mileage: number; - comment: string; - is_approved: boolean; - supervisor_comment: string; -} +// export class ExpenseDto { +// type: string; +// amount: number; +// mileage: number; +// comment: string; +// is_approved: boolean; +// supervisor_comment: string; +// } -export type DayShiftsDto = ShiftDto[]; +// export type DayShiftsDto = ShiftDto[]; -export class DetailedShifts { - shifts: DayShiftsDto; - regular_hours: number; - evening_hours: number; - overtime_hours: number; - emergency_hours: number; - comment: string; - short_date: string; - break_durations?: number; -} +// export class DetailedShifts { +// shifts: DayShiftsDto; +// regular_hours: number; +// evening_hours: number; +// overtime_hours: number; +// emergency_hours: number; +// comment: string; +// short_date: string; +// break_durations?: number; +// } -export class DayExpensesDto { - expenses: ExpenseDto[] = []; - total_mileage: number; - total_expense: number; -} +// export class DayExpensesDto { +// expenses: ExpenseDto[] = []; +// total_mileage: number; +// total_expense: number; +// } -export class WeekDto { - is_approved: boolean; - shifts: { - sun: DetailedShifts; - mon: DetailedShifts; - tue: DetailedShifts; - wed: DetailedShifts; - thu: DetailedShifts; - fri: DetailedShifts; - sat: DetailedShifts; - } - expenses: { - sun: DayExpensesDto; - mon: DayExpensesDto; - tue: DayExpensesDto; - wed: DayExpensesDto; - thu: DayExpensesDto; - fri: DayExpensesDto; - sat: DayExpensesDto; - } -} +// export class WeekDto { +// is_approved: boolean; +// shifts: { +// sun: DetailedShifts; +// mon: DetailedShifts; +// tue: DetailedShifts; +// wed: DetailedShifts; +// thu: DetailedShifts; +// fri: DetailedShifts; +// sat: DetailedShifts; +// } +// expenses: { +// sun: DayExpensesDto; +// mon: DayExpensesDto; +// tue: DayExpensesDto; +// wed: DayExpensesDto; +// thu: DayExpensesDto; +// fri: DayExpensesDto; +// sat: DayExpensesDto; +// } +// } -export class TimesheetPeriodDto { - weeks: WeekDto[]; - employee_full_name: string; -} +// export class TimesheetPeriodDto { +// weeks: WeekDto[]; +// employee_full_name: string; +// } diff --git a/src/modules/timesheets/~misc_deprecated-files/timesheet.helpers.ts b/src/modules/timesheets/~misc_deprecated-files/timesheet.helpers.ts index b05a520..930a277 100644 --- a/src/modules/timesheets/~misc_deprecated-files/timesheet.helpers.ts +++ b/src/modules/timesheets/~misc_deprecated-files/timesheet.helpers.ts @@ -1,67 +1,67 @@ -import { MS_PER_DAY } from "src/modules/shared/constants/date-time.constant"; -import { DAY_KEYS, DayKey } from "./timesheet.types"; +// import { MS_PER_DAY } from "src/modules/shared/constants/date-time.constant"; +// import { DAY_KEYS, DayKey } from "./timesheet.types"; -export function toUTCDateOnly(date: Date | string): Date { - const d = new Date(date); - return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate())); -} +// export function toUTCDateOnly(date: Date | string): Date { +// const d = new Date(date); +// return new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate())); +// } -export function addDays(date:Date, days: number): Date { - return new Date(date.getTime() + days * MS_PER_DAY); -} +// export function addDays(date:Date, days: number): Date { +// return new Date(date.getTime() + days * MS_PER_DAY); +// } -export function endOfDayUTC(date: Date | string): Date { - const d = toUTCDateOnly(date); - return new Date(d.getTime() + MS_PER_DAY - 1); -} +// export function endOfDayUTC(date: Date | string): Date { +// const d = toUTCDateOnly(date); +// return new Date(d.getTime() + MS_PER_DAY - 1); +// } -export function isBetweenUTC(date: Date, start: Date, end_inclusive: Date): boolean { - const time = date.getTime(); - return time >= start.getTime() && time <= end_inclusive.getTime(); -} +// export function isBetweenUTC(date: Date, start: Date, end_inclusive: Date): boolean { +// const time = date.getTime(); +// return time >= start.getTime() && time <= end_inclusive.getTime(); +// } -export function toTimeString(date: Date): string { - const hours = String(date.getUTCHours()).padStart(2,'0'); - const minutes = String(date.getUTCMinutes()).padStart(2,'0'); - return `${hours}:${minutes}`; -} +// export function toTimeString(date: Date): string { +// const hours = String(date.getUTCHours()).padStart(2,'0'); +// const minutes = String(date.getUTCMinutes()).padStart(2,'0'); +// return `${hours}:${minutes}`; +// } -export function round2(num: number) { - return Math.round(num * 100) / 100; -} +// export function round2(num: number) { +// return Math.round(num * 100) / 100; +// } -export function shortDate(date:Date): string { - const mm = String(date.getUTCMonth()+1).padStart(2,'0'); - const dd = String(date.getUTCDate()).padStart(2,'0'); - return `${mm}/${dd}`; -} +// export function shortDate(date:Date): string { +// const mm = String(date.getUTCMonth()+1).padStart(2,'0'); +// const dd = String(date.getUTCDate()).padStart(2,'0'); +// return `${mm}/${dd}`; +// } -export function dayKeyFromDate(date: Date, useUTC = true): DayKey { - const index = useUTC ? date.getUTCDay() : date.getDay(); // 0=Sunday..6=Saturday - return DAY_KEYS[index]; -} +// export function dayKeyFromDate(date: Date, useUTC = true): DayKey { +// const index = useUTC ? date.getUTCDay() : date.getDay(); // 0=Sunday..6=Saturday +// return DAY_KEYS[index]; +// } -export const toHHmm = (date: Date) => date.toISOString().slice(11, 16); +// export const toHHmm = (date: Date) => date.toISOString().slice(11, 16); -export function parseISODate(iso: string): Date { - const [ y, m, d ] = iso.split('-').map(Number); - return new Date(y, (m ?? 1) - 1, d ?? 1); -} +// export function parseISODate(iso: string): Date { +// const [ y, m, d ] = iso.split('-').map(Number); +// return new Date(y, (m ?? 1) - 1, d ?? 1); +// } -export function parseHHmm(t: string): Date { - const [ hh, mm ] = t.split(':').map(Number); - return new Date(1970, 0, 1, hh || 0, mm || 0, 0, 0); -} +// export function parseHHmm(t: string): Date { +// const [ hh, mm ] = t.split(':').map(Number); +// return new Date(1970, 0, 1, hh || 0, mm || 0, 0, 0); +// } -export const toNum = (value: any) => - value && typeof value.toNumber === 'function' ? value.toNumber() : - typeof value === 'number' ? value : - value ? Number(value) : 0; +// export const toNum = (value: any) => +// value && typeof value.toNumber === 'function' ? value.toNumber() : +// typeof value === 'number' ? value : +// value ? Number(value) : 0; -export const upper = (s?: string | null) => String(s ?? '').toUpperCase(); +// export const upper = (s?: string | null) => String(s ?? '').toUpperCase(); -export const toRangeFromPeriod = (period: { period_start: Date; period_end: Date }) => ({ - from: toUTCDateOnly(period.period_start), - to: endOfDayUTC(period.period_end), -}); \ No newline at end of file +// export const toRangeFromPeriod = (period: { period_start: Date; period_end: Date }) => ({ +// from: toUTCDateOnly(period.period_start), +// to: endOfDayUTC(period.period_end), +// }); \ No newline at end of file diff --git a/src/modules/timesheets/~misc_deprecated-files/timesheet.mappers.ts b/src/modules/timesheets/~misc_deprecated-files/timesheet.mappers.ts index 6a0b928..64a21f8 100644 --- a/src/modules/timesheets/~misc_deprecated-files/timesheet.mappers.ts +++ b/src/modules/timesheets/~misc_deprecated-files/timesheet.mappers.ts @@ -1,111 +1,111 @@ -import { DayExpensesDto, WeekDto, DetailedShifts, TimesheetPeriodDto } from "../dtos/timesheet-period.dto"; -import { ShiftRow, ExpenseRow, ExpensesAmount, TimesheetMap } from "./timesheet.types"; -import { addDays, shortDate, toNum, upper } from "./timesheet.helpers"; -import { Prisma } from "@prisma/client"; +// import { DayExpensesDto, WeekDto, DetailedShifts, TimesheetPeriodDto } from "../dtos/timesheet-period.dto"; +// import { ShiftRow, ExpenseRow, ExpensesAmount, TimesheetMap } from "./timesheet.types"; +// import { addDays, shortDate, toNum, upper } from "./timesheet.helpers"; +// import { Prisma } from "@prisma/client"; -//mappers -export const mapShiftRow = (shift: { - date: Date; - start_time: Date; - end_time: Date; - comment?: string | null; - is_approved: boolean; - is_remote: boolean; - bank_code: { type: string }; -}): ShiftRow => ({ - date: shift.date, - start_time: shift.start_time, - end_time: shift.end_time, - comment: shift.comment ?? '', - is_approved: shift.is_approved, - is_remote: shift.is_remote, - type: upper(shift.bank_code.type), -}); +// //mappers +// export const mapShiftRow = (shift: { +// date: Date; +// start_time: Date; +// end_time: Date; +// comment?: string | null; +// is_approved: boolean; +// is_remote: boolean; +// bank_code: { type: string }; +// }): ShiftRow => ({ +// date: shift.date, +// start_time: shift.start_time, +// end_time: shift.end_time, +// comment: shift.comment ?? '', +// is_approved: shift.is_approved, +// is_remote: shift.is_remote, +// type: upper(shift.bank_code.type), +// }); -export const mapExpenseRow = (expense: { - date: Date; - amount: Prisma.Decimal | number | null; - mileage: Prisma.Decimal | number | null; - comment?: string | null; - is_approved: boolean; - supervisor_comment?: string|null; - bank_code: { type: string }, -}): ExpenseRow => ({ - date: expense.date, - amount: toNum(expense.amount), - mileage: toNum(expense.mileage), - comment: expense.comment ?? '', - is_approved: expense.is_approved, - supervisor_comment: expense.supervisor_comment ?? '', - type: upper(expense.bank_code.type), -}); +// export const mapExpenseRow = (expense: { +// date: Date; +// amount: Prisma.Decimal | number | null; +// mileage: Prisma.Decimal | number | null; +// comment?: string | null; +// is_approved: boolean; +// supervisor_comment?: string|null; +// bank_code: { type: string }, +// }): ExpenseRow => ({ +// date: expense.date, +// amount: toNum(expense.amount), +// mileage: toNum(expense.mileage), +// comment: expense.comment ?? '', +// is_approved: expense.is_approved, +// supervisor_comment: expense.supervisor_comment ?? '', +// type: upper(expense.bank_code.type), +// }); -// Factories -export function makeEmptyDayExpenses(): DayExpensesDto { - return { - expenses: [], - total_expense: -1, - total_mileage: -1, - }; -} +// // Factories +// export function makeEmptyDayExpenses(): DayExpensesDto { +// return { +// expenses: [], +// total_expense: -1, +// total_mileage: -1, +// }; +// } -export function makeEmptyWeek(week_start: Date): WeekDto { - const make_empty_shifts = (offset: number): DetailedShifts => ({ - shifts: [], - regular_hours: 0, - evening_hours: 0, - emergency_hours: 0, - overtime_hours: 0, - comment: '', - short_date: shortDate(addDays(week_start, offset)), - break_durations: 0, - }); - return { - is_approved: true, - shifts: { - sun: make_empty_shifts(0), - mon: make_empty_shifts(1), - tue: make_empty_shifts(2), - wed: make_empty_shifts(3), - thu: make_empty_shifts(4), - fri: make_empty_shifts(5), - sat: make_empty_shifts(6), - }, - expenses: { - sun: makeEmptyDayExpenses(), - mon: makeEmptyDayExpenses(), - tue: makeEmptyDayExpenses(), - wed: makeEmptyDayExpenses(), - thu: makeEmptyDayExpenses(), - fri: makeEmptyDayExpenses(), - sat: makeEmptyDayExpenses(), - }, - }; -} +// export function makeEmptyWeek(week_start: Date): WeekDto { +// const make_empty_shifts = (offset: number): DetailedShifts => ({ +// shifts: [], +// regular_hours: 0, +// evening_hours: 0, +// emergency_hours: 0, +// overtime_hours: 0, +// comment: '', +// short_date: shortDate(addDays(week_start, offset)), +// break_durations: 0, +// }); +// return { +// is_approved: true, +// shifts: { +// sun: make_empty_shifts(0), +// mon: make_empty_shifts(1), +// tue: make_empty_shifts(2), +// wed: make_empty_shifts(3), +// thu: make_empty_shifts(4), +// fri: make_empty_shifts(5), +// sat: make_empty_shifts(6), +// }, +// expenses: { +// sun: makeEmptyDayExpenses(), +// mon: makeEmptyDayExpenses(), +// tue: makeEmptyDayExpenses(), +// wed: makeEmptyDayExpenses(), +// thu: makeEmptyDayExpenses(), +// fri: makeEmptyDayExpenses(), +// sat: makeEmptyDayExpenses(), +// }, +// }; +// } -export function makeEmptyPeriod(): TimesheetPeriodDto { - return { weeks: [makeEmptyWeek(new Date()), makeEmptyWeek(new Date())], employee_full_name: '' }; -} +// export function makeEmptyPeriod(): TimesheetPeriodDto { +// return { weeks: [makeEmptyWeek(new Date()), makeEmptyWeek(new Date())], employee_full_name: '' }; +// } -export const makeAmounts = (): ExpensesAmount => ({ - expense: 0, - mileage: 0, -}); +// export const makeAmounts = (): ExpensesAmount => ({ +// expense: 0, +// mileage: 0, +// }); -export function makeEmptyTimesheet(params: { - start_day: string; - end_day: string; - label: string; - is_approved?: boolean; -}): TimesheetMap { - const { start_day, end_day, label, is_approved = false } = params; - return { - start_day, - end_day, - label, - shifts: [], - expenses: [], - is_approved, - }; -} \ No newline at end of file +// export function makeEmptyTimesheet(params: { +// start_day: string; +// end_day: string; +// label: string; +// is_approved?: boolean; +// }): TimesheetMap { +// const { start_day, end_day, label, is_approved = false } = params; +// return { +// start_day, +// end_day, +// label, +// shifts: [], +// expenses: [], +// is_approved, +// }; +// } \ No newline at end of file diff --git a/src/modules/timesheets/~misc_deprecated-files/timesheet.selectors.ts b/src/modules/timesheets/~misc_deprecated-files/timesheet.selectors.ts index 42aeff1..698f5a7 100644 --- a/src/modules/timesheets/~misc_deprecated-files/timesheet.selectors.ts +++ b/src/modules/timesheets/~misc_deprecated-files/timesheet.selectors.ts @@ -1,46 +1,46 @@ -import { EXPENSE_ASC_ORDER, EXPENSE_SELECT } from "../../../shared/selects/expenses.select"; -import { Injectable, NotFoundException } from "@nestjs/common"; -import { SHIFT_ASC_ORDER, SHIFT_SELECT } from "../../../shared/selects/shifts.select"; -import { PAY_PERIOD_SELECT } from "../../../shared/selects/pay-periods.select"; -import { PrismaService } from "src/prisma/prisma.service"; +// import { EXPENSE_ASC_ORDER, EXPENSE_SELECT } from "../../../shared/selects/expenses.select"; +// import { Injectable, NotFoundException } from "@nestjs/common"; +// import { SHIFT_ASC_ORDER, SHIFT_SELECT } from "../../../shared/selects/shifts.select"; +// import { PAY_PERIOD_SELECT } from "../../../shared/selects/pay-periods.select"; +// import { PrismaService } from "src/prisma/prisma.service"; -@Injectable() -export class TimesheetSelectorsService { - constructor(readonly prisma: PrismaService){} +// @Injectable() +// export class TimesheetSelectorsService { +// constructor(readonly prisma: PrismaService){} - async getPayPeriod(pay_year: number, pay_period_no: number) { - const period = await this.prisma.payPeriods.findFirst({ - where: { pay_year, pay_period_no }, - select: PAY_PERIOD_SELECT , - }); - if(!period) throw new NotFoundException(`period ${pay_year}-${pay_period_no} not found`); - return period; - } +// async getPayPeriod(pay_year: number, pay_period_no: number) { +// const period = await this.prisma.payPeriods.findFirst({ +// where: { pay_year, pay_period_no }, +// select: PAY_PERIOD_SELECT , +// }); +// if(!period) throw new NotFoundException(`period ${pay_year}-${pay_period_no} not found`); +// return period; +// } - async getShifts(employee_id: number, from: Date, to: Date) { - return this.prisma.shifts.findMany({ - where: {timesheet: { is: { employee_id } }, date: { gte: from, lte: to } }, - select: SHIFT_SELECT, - orderBy: SHIFT_ASC_ORDER, - }); - } +// async getShifts(employee_id: number, from: Date, to: Date) { +// return this.prisma.shifts.findMany({ +// where: {timesheet: { is: { employee_id } }, date: { gte: from, lte: to } }, +// select: SHIFT_SELECT, +// orderBy: SHIFT_ASC_ORDER, +// }); +// } - async getExpenses(employee_id: number, from: Date, to: Date) { - return this.prisma.expenses.findMany({ - where: { timesheet: {is: { employee_id } }, date: { gte: from, lte: to } }, - select: EXPENSE_SELECT, - orderBy: EXPENSE_ASC_ORDER, - }); - } +// async getExpenses(employee_id: number, from: Date, to: Date) { +// return this.prisma.expenses.findMany({ +// where: { timesheet: {is: { employee_id } }, date: { gte: from, lte: to } }, +// select: EXPENSE_SELECT, +// orderBy: EXPENSE_ASC_ORDER, +// }); +// } - async getTimesheetWithShiftsAndExpenses(employee_id: number, start_date_week: Date) { - return this.prisma.timesheets.findUnique({ - where: { employee_id_start_date: { employee_id, start_date: start_date_week } }, - select: { - is_approved: true, - shift: { select: SHIFT_SELECT, orderBy: SHIFT_ASC_ORDER }, - expense: { select: EXPENSE_SELECT, orderBy: EXPENSE_ASC_ORDER }, - }, - }); - } -} \ No newline at end of file +// async getTimesheetWithShiftsAndExpenses(employee_id: number, start_date_week: Date) { +// return this.prisma.timesheets.findUnique({ +// where: { employee_id_start_date: { employee_id, start_date: start_date_week } }, +// select: { +// is_approved: true, +// shift: { select: SHIFT_SELECT, orderBy: SHIFT_ASC_ORDER }, +// expense: { select: EXPENSE_SELECT, orderBy: EXPENSE_ASC_ORDER }, +// }, +// }); +// } +// } \ No newline at end of file diff --git a/src/modules/timesheets/~misc_deprecated-files/timesheet.types.ts b/src/modules/timesheets/~misc_deprecated-files/timesheet.types.ts index 6fcc951..1d1d0be 100644 --- a/src/modules/timesheets/~misc_deprecated-files/timesheet.types.ts +++ b/src/modules/timesheets/~misc_deprecated-files/timesheet.types.ts @@ -1,74 +1,74 @@ -export type ShiftRow = { - date: Date; - start_time: Date; - end_time: Date; - comment: string; - is_approved?: boolean; - is_remote: boolean; - type: string -}; -export type ExpenseRow = { - date: Date; - amount: number; - mileage?: number | null; - comment: string; - type: string; - is_approved?: boolean; - supervisor_comment: string; -}; +// export type ShiftRow = { +// date: Date; +// start_time: Date; +// end_time: Date; +// comment: string; +// is_approved?: boolean; +// is_remote: boolean; +// type: string +// }; +// export type ExpenseRow = { +// date: Date; +// amount: number; +// mileage?: number | null; +// comment: string; +// type: string; +// is_approved?: boolean; +// supervisor_comment: string; +// }; -export type TimesheetMap = { - start_day: string; - end_day: string; - label: string; - shifts: ShiftRow[]; - expenses: ExpenseRow[] - is_approved: boolean; -} +// export type TimesheetMap = { +// start_day: string; +// end_day: string; +// label: string; +// shifts: ShiftRow[]; +// expenses: ExpenseRow[] +// is_approved: boolean; +// } -// Types -export const SHIFT_TYPES = { - REGULAR: 'REGULAR', - EVENING: 'EVENING', - OVERTIME: 'OVERTIME', - EMERGENCY: 'EMERGENCY', - HOLIDAY: 'HOLIDAY', - VACATION: 'VACATION', - SICK: 'SICK', -} as const; +// // Types +// export const SHIFT_TYPES = { +// REGULAR: 'REGULAR', +// EVENING: 'EVENING', +// OVERTIME: 'OVERTIME', +// EMERGENCY: 'EMERGENCY', +// HOLIDAY: 'HOLIDAY', +// VACATION: 'VACATION', +// SICK: 'SICK', +// } as const; -export const EXPENSE_TYPES = { - MILEAGE: 'MILEAGE', - EXPENSE: 'EXPENSES', - PER_DIEM: 'PER_DIEM', - ON_CALL: 'ON_CALL', -} as const; +// export const EXPENSE_TYPES = { +// MILEAGE: 'MILEAGE', +// EXPENSE: 'EXPENSES', +// PER_DIEM: 'PER_DIEM', +// ON_CALL: 'ON_CALL', +// } as const; -//makes the strings indexes for arrays -export const DAY_KEYS = ['sun','mon','tue','wed','thu','fri','sat'] as const; -export type DayKey = typeof DAY_KEYS[number]; +// //makes the strings indexes for arrays +// export const DAY_KEYS = ['sun','mon','tue','wed','thu','fri','sat'] as const; +// export type DayKey = typeof DAY_KEYS[number]; -//shifts's hour by type -export type ShiftsHours = { - regular: number; - evening: number; - overtime: number; - emergency: number; - sick: number; - vacation: number; - holiday: number; -}; -export const make_hours = (): ShiftsHours => ({ - regular: 0, - evening: 0, - overtime: 0, - emergency: 0, - sick: 0, - vacation: 0, - holiday: 0, -}); +// //shifts's hour by type +// export type ShiftsHours = { +// regular: number; +// evening: number; +// overtime: number; +// emergency: number; +// sick: number; +// vacation: number; +// holiday: number; +// }; +// export const make_hours = (): ShiftsHours => ({ +// regular: 0, +// evening: 0, +// overtime: 0, +// emergency: 0, +// sick: 0, +// vacation: 0, +// holiday: 0, +// }); -export type ExpensesAmount = { - expense: number; - mileage: number; -}; \ No newline at end of file +// export type ExpensesAmount = { +// expense: number; +// mileage: number; +// }; \ No newline at end of file diff --git a/src/modules/timesheets/~misc_deprecated-files/timesheet.utils.ts b/src/modules/timesheets/~misc_deprecated-files/timesheet.utils.ts index d6e691f..b1ca369 100644 --- a/src/modules/timesheets/~misc_deprecated-files/timesheet.utils.ts +++ b/src/modules/timesheets/~misc_deprecated-files/timesheet.utils.ts @@ -1,171 +1,171 @@ -import { - DayKey, DAY_KEYS, EXPENSE_TYPES, ExpenseRow, - SHIFT_TYPES, ShiftRow, make_hours, ShiftsHours, ExpensesAmount -} from "./timesheet.types"; -import { - isBetweenUTC, dayKeyFromDate, toTimeString, round2, - toUTCDateOnly, endOfDayUTC, addDays -} from "./timesheet.helpers"; -import { WeekDto, ShiftDto, TimesheetPeriodDto, DayExpensesDto, ExpenseDto } from "../dtos/timesheet-period.dto"; -import { getWeekStart, getWeekEnd, formatDateISO } from "src/common/utils/date-utils"; -import { makeAmounts, makeEmptyWeek } from "./timesheet.mappers"; -import { toDateString } from "src/modules/pay-periods/utils/pay-year.util"; -import { MS_PER_HOUR } from "src/modules/shared/constants/date-time.constant"; +// import { +// DayKey, DAY_KEYS, EXPENSE_TYPES, ExpenseRow, +// SHIFT_TYPES, ShiftRow, make_hours, ShiftsHours, ExpensesAmount +// } from "./timesheet.types"; +// import { +// isBetweenUTC, dayKeyFromDate, toTimeString, round2, +// toUTCDateOnly, endOfDayUTC, addDays +// } from "./timesheet.helpers"; +// import { WeekDto, ShiftDto, TimesheetPeriodDto, DayExpensesDto, ExpenseDto } from "../dtos/timesheet-period.dto"; +// import { getWeekStart, getWeekEnd, formatDateISO } from "src/common/utils/date-utils"; +// import { makeAmounts, makeEmptyWeek } from "./timesheet.mappers"; +// import { toDateString } from "src/modules/pay-periods/utils/pay-year.util"; +// import { MS_PER_HOUR } from "src/modules/shared/constants/date-time.constant"; - export function computeWeekRange(week_offset = 0){ - //sets current week Sunday -> Saturday - const base = new Date(); - const offset = new Date(base); - offset.setDate(offset.getDate() + (week_offset * 7)); +// export function computeWeekRange(week_offset = 0){ +// //sets current week Sunday -> Saturday +// const base = new Date(); +// const offset = new Date(base); +// offset.setDate(offset.getDate() + (week_offset * 7)); - const start = getWeekStart(offset, 0); - const end = getWeekEnd(start); - const start_day = formatDateISO(start); - const end_day = formatDateISO(end); - const label = `${(start_day)}.${(end_day)}`; +// const start = getWeekStart(offset, 0); +// const end = getWeekEnd(start); +// const start_day = formatDateISO(start); +// const end_day = formatDateISO(end); +// const label = `${(start_day)}.${(end_day)}`; - return { start, end, start_day, end_day, label } - }; +// return { start, end, start_day, end_day, label } +// }; -export function buildWeek( - week_start: Date, - week_end: Date, - shifts: ShiftRow[], - expenses: ExpenseRow[], - ): WeekDto { - const week = makeEmptyWeek(week_start); - let all_approved = true; +// export function buildWeek( +// week_start: Date, +// week_end: Date, +// shifts: ShiftRow[], +// expenses: ExpenseRow[], +// ): WeekDto { +// const week = makeEmptyWeek(week_start); +// let all_approved = true; - const day_times: Record> = DAY_KEYS.reduce((acc, key) => { - acc[key] = []; return acc; - }, {} as Record>); +// const day_times: Record> = DAY_KEYS.reduce((acc, key) => { +// acc[key] = []; return acc; +// }, {} as Record>); - const day_hours: Record = DAY_KEYS.reduce((acc, key) => { - acc[key] = make_hours(); return acc; - }, {} as Record); +// const day_hours: Record = DAY_KEYS.reduce((acc, key) => { +// acc[key] = make_hours(); return acc; +// }, {} as Record); - const day_amounts: Record = DAY_KEYS.reduce((acc, key) => { - acc[key] = makeAmounts(); return acc; - }, {} as Record); +// const day_amounts: Record = DAY_KEYS.reduce((acc, key) => { +// acc[key] = makeAmounts(); return acc; +// }, {} as Record); - const day_expense_rows: Record = DAY_KEYS.reduce((acc, key) => { - acc[key] = { - expenses: [{ - type: '', - amount: -1, - mileage: -1, - comment: '', - is_approved: false, - supervisor_comment: '', - }], - total_expense: -1, - total_mileage: -1, - }; - return acc; - }, {} as Record); +// const day_expense_rows: Record = DAY_KEYS.reduce((acc, key) => { +// acc[key] = { +// expenses: [{ +// type: '', +// amount: -1, +// mileage: -1, +// comment: '', +// is_approved: false, +// supervisor_comment: '', +// }], +// total_expense: -1, +// total_mileage: -1, +// }; +// return acc; +// }, {} as Record); - //regroup hours per type of shifts - const week_shifts = shifts.filter(shift => isBetweenUTC(shift.date, week_start, week_end)); - for (const shift of week_shifts) { - const key = dayKeyFromDate(shift.date, true); - week.shifts[key].shifts.push({ - date: toDateString(shift.date), - type: shift.type, - start_time: toTimeString(shift.start_time), - end_time: toTimeString(shift.end_time), - comment: shift.comment, - is_approved: shift.is_approved ?? true, - is_remote: shift.is_remote, - } as ShiftDto); +// //regroup hours per type of shifts +// const week_shifts = shifts.filter(shift => isBetweenUTC(shift.date, week_start, week_end)); +// for (const shift of week_shifts) { +// const key = dayKeyFromDate(shift.date, true); +// week.shifts[key].shifts.push({ +// date: toDateString(shift.date), +// type: shift.type, +// start_time: toTimeString(shift.start_time), +// end_time: toTimeString(shift.end_time), +// comment: shift.comment, +// is_approved: shift.is_approved ?? true, +// is_remote: shift.is_remote, +// } as ShiftDto); - day_times[key].push({ start: shift.start_time, end: shift.end_time}); +// day_times[key].push({ start: shift.start_time, end: shift.end_time}); - const duration = Math.max(0, (shift.end_time.getTime() - shift.start_time.getTime())/ MS_PER_HOUR); - const type = (shift.type || '').toUpperCase(); +// const duration = Math.max(0, (shift.end_time.getTime() - shift.start_time.getTime())/ MS_PER_HOUR); +// const type = (shift.type || '').toUpperCase(); - if ( type === SHIFT_TYPES.REGULAR) day_hours[key].regular += duration; - else if( type === SHIFT_TYPES.EVENING) day_hours[key].evening += duration; - else if( type === SHIFT_TYPES.EMERGENCY) day_hours[key].emergency += duration; - else if( type === SHIFT_TYPES.OVERTIME) day_hours[key].overtime += duration; - else if( type === SHIFT_TYPES.SICK) day_hours[key].sick += duration; - else if( type === SHIFT_TYPES.VACATION) day_hours[key].vacation += duration; - else if( type === SHIFT_TYPES.HOLIDAY) day_hours[key].holiday += duration; +// if ( type === SHIFT_TYPES.REGULAR) day_hours[key].regular += duration; +// else if( type === SHIFT_TYPES.EVENING) day_hours[key].evening += duration; +// else if( type === SHIFT_TYPES.EMERGENCY) day_hours[key].emergency += duration; +// else if( type === SHIFT_TYPES.OVERTIME) day_hours[key].overtime += duration; +// else if( type === SHIFT_TYPES.SICK) day_hours[key].sick += duration; +// else if( type === SHIFT_TYPES.VACATION) day_hours[key].vacation += duration; +// else if( type === SHIFT_TYPES.HOLIDAY) day_hours[key].holiday += duration; - all_approved = all_approved && (shift.is_approved ?? true ); - } +// all_approved = all_approved && (shift.is_approved ?? true ); +// } - //regroupe amounts to type of expenses - const week_expenses = expenses.filter(expense => isBetweenUTC(expense.date, week_start, week_end)); - for (const expense of week_expenses) { - const key = dayKeyFromDate(expense.date, true); - const type = (expense.type || '').toUpperCase(); +// //regroupe amounts to type of expenses +// const week_expenses = expenses.filter(expense => isBetweenUTC(expense.date, week_start, week_end)); +// for (const expense of week_expenses) { +// const key = dayKeyFromDate(expense.date, true); +// const type = (expense.type || '').toUpperCase(); - const row: ExpenseDto = { - type, - amount: round2(expense.amount ?? 0), - mileage: round2(expense.mileage ?? 0), - comment: expense.comment ?? '', - is_approved: expense.is_approved ?? true, - supervisor_comment: expense.supervisor_comment ?? '', - }; +// const row: ExpenseDto = { +// type, +// amount: round2(expense.amount ?? 0), +// mileage: round2(expense.mileage ?? 0), +// comment: expense.comment ?? '', +// is_approved: expense.is_approved ?? true, +// supervisor_comment: expense.supervisor_comment ?? '', +// }; - day_expense_rows[key].expenses.push(row); +// day_expense_rows[key].expenses.push(row); - if(type === EXPENSE_TYPES.MILEAGE) { - day_amounts[key].mileage += row.mileage ?? 0; - } else { - day_amounts[key].expense += row.amount; - } +// if(type === EXPENSE_TYPES.MILEAGE) { +// day_amounts[key].mileage += row.mileage ?? 0; +// } else { +// day_amounts[key].expense += row.amount; +// } - all_approved = all_approved && row.is_approved; - } +// all_approved = all_approved && row.is_approved; +// } - for (const key of DAY_KEYS) { - //return exposed dto data - week.shifts[key].regular_hours = round2(day_hours[key].regular); - week.shifts[key].evening_hours = round2(day_hours[key].evening); - week.shifts[key].overtime_hours = round2(day_hours[key].overtime); - week.shifts[key].emergency_hours = round2(day_hours[key].emergency); +// for (const key of DAY_KEYS) { +// //return exposed dto data +// week.shifts[key].regular_hours = round2(day_hours[key].regular); +// week.shifts[key].evening_hours = round2(day_hours[key].evening); +// week.shifts[key].overtime_hours = round2(day_hours[key].overtime); +// week.shifts[key].emergency_hours = round2(day_hours[key].emergency); - //calculate gaps between shifts - const times = day_times[key].sort((a,b) => a.start.getTime() - b.start.getTime()); - let gaps = 0; - for (let i = 1; i < times.length; i++) { - const gap = (times[i].start.getTime() - times[i - 1].end.getTime()) / MS_PER_HOUR; - if(gap > 0) gaps += gap; - } - week.shifts[key].break_durations = round2(gaps); +// //calculate gaps between shifts +// const times = day_times[key].sort((a,b) => a.start.getTime() - b.start.getTime()); +// let gaps = 0; +// for (let i = 1; i < times.length; i++) { +// const gap = (times[i].start.getTime() - times[i - 1].end.getTime()) / MS_PER_HOUR; +// if(gap > 0) gaps += gap; +// } +// week.shifts[key].break_durations = round2(gaps); - //daily totals - const totals = day_amounts[key]; +// //daily totals +// const totals = day_amounts[key]; - day_expense_rows[key].total_mileage = round2(totals.mileage); - day_expense_rows[key].total_expense = round2(totals.expense); - } +// day_expense_rows[key].total_mileage = round2(totals.mileage); +// day_expense_rows[key].total_expense = round2(totals.expense); +// } - week.is_approved = all_approved; - return week; -} +// week.is_approved = all_approved; +// return week; +// } -export function buildPeriod( - period_start: Date, - period_end: Date, - shifts: ShiftRow[], - expenses: ExpenseRow[], - employeeFullName = '' -): TimesheetPeriodDto { - const week1_start = toUTCDateOnly(period_start); - const week1_end = endOfDayUTC(addDays(week1_start, 6)); - const week2_start = toUTCDateOnly(addDays(week1_start, 7)); - const week2_end = endOfDayUTC(period_end); +// export function buildPeriod( +// period_start: Date, +// period_end: Date, +// shifts: ShiftRow[], +// expenses: ExpenseRow[], +// employeeFullName = '' +// ): TimesheetPeriodDto { +// const week1_start = toUTCDateOnly(period_start); +// const week1_end = endOfDayUTC(addDays(week1_start, 6)); +// const week2_start = toUTCDateOnly(addDays(week1_start, 7)); +// const week2_end = endOfDayUTC(period_end); - const weeks: WeekDto[] = [ - buildWeek(week1_start, week1_end, shifts, expenses), - buildWeek(week2_start, week2_end, shifts, expenses), - ]; +// const weeks: WeekDto[] = [ +// buildWeek(week1_start, week1_end, shifts, expenses), +// buildWeek(week2_start, week2_end, shifts, expenses), +// ]; - return { - weeks, - employee_full_name: employeeFullName, - }; -} \ No newline at end of file +// return { +// weeks, +// employee_full_name: employeeFullName, +// }; +// } \ No newline at end of file diff --git a/src/modules/timesheets/~misc_deprecated-files/timesheets-command.service.ts b/src/modules/timesheets/~misc_deprecated-files/timesheets-command.service.ts index d9f7930..9fb3b52 100644 --- a/src/modules/timesheets/~misc_deprecated-files/timesheets-command.service.ts +++ b/src/modules/timesheets/~misc_deprecated-files/timesheets-command.service.ts @@ -1,137 +1,137 @@ -import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; -import { EmployeeTimesheetResolver } from "src/modules/shared/utils/resolve-timesheet.utils"; -import { getWeekEnd, getWeekStart } from "src/common/utils/date-utils"; -import { parseISODate, parseHHmm } from "./utils-helpers-others/timesheet.helpers"; -import { TimesheetsQueryService } from "./timesheets-query.service"; -import { BaseApprovalService } from "src/common/shared/base-approval.service"; -import { Prisma, Timesheets } from "@prisma/client"; -import { CreateTimesheetDto } from "./create-timesheet.dto"; -import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; -import { BankCodesResolver } from "src/modules/shared/utils/resolve-bank-type-id.utils"; -import { PrismaService } from "src/prisma/prisma.service"; -import { TimesheetMap } from "./utils-helpers-others/timesheet.types"; -import { Shift, Expense } from "../dtos/timesheet.dto"; +// import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common"; +// import { EmployeeTimesheetResolver } from "src/modules/shared/utils/resolve-timesheet.utils"; +// import { getWeekEnd, getWeekStart } from "src/common/utils/date-utils"; +// import { parseISODate, parseHHmm } from "./utils-helpers-others/timesheet.helpers"; +// import { TimesheetsQueryService } from "./timesheets-query.service"; +// import { BaseApprovalService } from "src/common/shared/base-approval.service"; +// import { Prisma, Timesheets } from "@prisma/client"; +// import { CreateTimesheetDto } from "./create-timesheet.dto"; +// import { EmailToIdResolver } from "src/modules/shared/utils/resolve-email-id.utils"; +// import { BankCodesResolver } from "src/modules/shared/utils/resolve-bank-type-id.utils"; +// import { PrismaService } from "src/prisma/prisma.service"; +// import { TimesheetMap } from "./utils-helpers-others/timesheet.types"; +// import { Shift, Expense } from "../dtos/timesheet.dto"; -@Injectable() -export class TimesheetsCommandService extends BaseApprovalService{ - constructor( - prisma: PrismaService, - private readonly query: TimesheetsQueryService, - private readonly emailResolver: EmailToIdResolver, - private readonly timesheetResolver: EmployeeTimesheetResolver, - private readonly bankTypeResolver: BankCodesResolver, - ) {super(prisma);} -//_____________________________________________________________________________________________ -// APPROVAL AND DELEGATE METHODS -//_____________________________________________________________________________________________ - protected get delegate() { - return this.prisma.timesheets; - } +// @Injectable() +// export class TimesheetsCommandService extends BaseApprovalService{ +// constructor( +// prisma: PrismaService, +// private readonly query: TimesheetsQueryService, +// private readonly emailResolver: EmailToIdResolver, +// private readonly timesheetResolver: EmployeeTimesheetResolver, +// private readonly bankTypeResolver: BankCodesResolver, +// ) {super(prisma);} +// //_____________________________________________________________________________________________ +// // APPROVAL AND DELEGATE METHODS +// //_____________________________________________________________________________________________ +// protected get delegate() { +// return this.prisma.timesheets; +// } - protected delegateFor(transaction: Prisma.TransactionClient) { - return transaction.timesheets; - } +// protected delegateFor(transaction: Prisma.TransactionClient) { +// return transaction.timesheets; +// } - async updateApproval(id: number, isApproved: boolean): Promise { - return this.prisma.$transaction((transaction) => - this.updateApprovalWithTransaction(transaction, id, isApproved), - ); - } +// async updateApproval(id: number, isApproved: boolean): Promise { +// return this.prisma.$transaction((transaction) => +// this.updateApprovalWithTransaction(transaction, id, isApproved), +// ); +// } - async cascadeApprovalWithtx(transaction: Prisma.TransactionClient, timesheetId: number, isApproved: boolean): Promise { - const timesheet = await this.updateApprovalWithTransaction(transaction, timesheetId, isApproved); - await transaction.shifts.updateMany({ - where: { timesheet_id: timesheetId }, - data: { is_approved: isApproved }, - }); - await transaction.expenses.updateManyAndReturn({ - where: { timesheet_id: timesheetId }, - data: { is_approved: isApproved }, - }); - return timesheet; - } +// async cascadeApprovalWithtx(transaction: Prisma.TransactionClient, timesheetId: number, isApproved: boolean): Promise { +// const timesheet = await this.updateApprovalWithTransaction(transaction, timesheetId, isApproved); +// await transaction.shifts.updateMany({ +// where: { timesheet_id: timesheetId }, +// data: { is_approved: isApproved }, +// }); +// await transaction.expenses.updateManyAndReturn({ +// where: { timesheet_id: timesheetId }, +// data: { is_approved: isApproved }, +// }); +// return timesheet; +// } -/**_____________________________________________________________________________________________ - create/update/delete shifts and expenses from 1 or many timesheet(s) +// /**_____________________________________________________________________________________________ +// create/update/delete shifts and expenses from 1 or many timesheet(s) - -this function receives an email and an array of timesheets +// -this function receives an email and an array of timesheets - -this function will find the timesheets with all shifts and expenses - -this function will calculate total hours, total expenses, filtered by types, - cumulate in daily and weekly. +// -this function will find the timesheets with all shifts and expenses +// -this function will calculate total hours, total expenses, filtered by types, +// cumulate in daily and weekly. - -the timesheet_id will be determined using the employee email - -with the timesheet_id, all shifts and expenses will be fetched +// -the timesheet_id will be determined using the employee email +// -with the timesheet_id, all shifts and expenses will be fetched - -with shift_id and expense_id, this function will compare both - datas from the DB and from the body of the function and then: - -it will create a shift if no shift is found in the DB - -it will update a shift if a shift is found in the DB - -it will delete a shift if a shift is found and no data is received from the frontend +// -with shift_id and expense_id, this function will compare both +// datas from the DB and from the body of the function and then: +// -it will create a shift if no shift is found in the DB +// -it will update a shift if a shift is found in the DB +// -it will delete a shift if a shift is found and no data is received from the frontend - This function will be used for the Timesheet Page for an employee to enter, modify or delete and entry - This function will also be used in the modal of the timesheet validation page to - allow a supervisor to enter, modify or delete and entry of a selected employee -_____________________________________________________________________________________________*/ +// This function will be used for the Timesheet Page for an employee to enter, modify or delete and entry +// This function will also be used in the modal of the timesheet validation page to +// allow a supervisor to enter, modify or delete and entry of a selected employee +// _____________________________________________________________________________________________*/ -async findTimesheetsByEmailAndPayPeriod(email: string, year: number, period_no: number, timesheets: Timesheets[]): Promise { - const employee_id = await this.emailResolver.findIdByEmail(email); +// async findTimesheetsByEmailAndPayPeriod(email: string, year: number, period_no: number, timesheets: Timesheets[]): Promise { +// const employee_id = await this.emailResolver.findIdByEmail(email); - return timesheets; -} +// return timesheets; +// } -async upsertOrDeleteShiftsByEmailAndDate(email:string, shift_ids: Shift[]) {} +// async upsertOrDeleteShiftsByEmailAndDate(email:string, shift_ids: Shift[]) {} -async upsertOrDeleteExpensesByEmailAndDate(email:string, expenses_id: Expense[]) {} +// async upsertOrDeleteExpensesByEmailAndDate(email:string, expenses_id: Expense[]) {} -//_____________________________________________________________________________________________ -// -//_____________________________________________________________________________________________ +// //_____________________________________________________________________________________________ +// // +// //_____________________________________________________________________________________________ - async createWeekShiftsAndReturnOverview( - email:string, - shifts: CreateTimesheetDto[], - week_offset = 0, - ): Promise { - //fetchs employee matchint user's email - const employee_id = await this.emailResolver.findIdByEmail(email); - if(!employee_id) throw new NotFoundException(`employee for ${ email } not found`); +// async createWeekShiftsAndReturnOverview( +// email:string, +// shifts: CreateTimesheetDto[], +// week_offset = 0, +// ): Promise { +// //fetchs employee matchint user's email +// const employee_id = await this.emailResolver.findIdByEmail(email); +// if(!employee_id) throw new NotFoundException(`employee for ${ email } not found`); - //insure that the week starts on sunday and finishes on saturday - const base = new Date(); - base.setDate(base.getDate() + week_offset * 7); - const start_week = getWeekStart(base, 0); - const end_week = getWeekEnd(start_week); +// //insure that the week starts on sunday and finishes on saturday +// const base = new Date(); +// base.setDate(base.getDate() + week_offset * 7); +// const start_week = getWeekStart(base, 0); +// const end_week = getWeekEnd(start_week); - const timesheet = await this.timesheetResolver.findTimesheetIdByEmail(email, base) - if(!timesheet) throw new NotFoundException(`no timesheet found for employe ${employee_id}`); +// const timesheet = await this.timesheetResolver.findTimesheetIdByEmail(email, base) +// if(!timesheet) throw new NotFoundException(`no timesheet found for employe ${employee_id}`); - //validations and insertions - for(const shift of shifts) { - const date = parseISODate(shift.date); - if (date < start_week || date > end_week) throw new BadRequestException(`date ${shift.date} not in current week`); +// //validations and insertions +// for(const shift of shifts) { +// const date = parseISODate(shift.date); +// if (date < start_week || date > end_week) throw new BadRequestException(`date ${shift.date} not in current week`); - const bank_code = await this.bankTypeResolver.findByType(shift.type) - if(!bank_code) throw new BadRequestException(`Invalid bank_code type: ${shift.type}`); +// const bank_code = await this.bankTypeResolver.findByType(shift.type) +// if(!bank_code) throw new BadRequestException(`Invalid bank_code type: ${shift.type}`); - await this.prisma.shifts.create({ - data: { - timesheet_id: timesheet.id, - bank_code_id: bank_code.id, - date: date, - start_time: parseHHmm(shift.start_time), - end_time: parseHHmm(shift.end_time), - comment: shift.comment ?? null, - is_approved: false, - is_remote: false, - }, - }); - } - return this.query.getTimesheetByEmail(email, week_offset); - } -} \ No newline at end of file +// await this.prisma.shifts.create({ +// data: { +// timesheet_id: timesheet.id, +// bank_code_id: bank_code.id, +// date: date, +// start_time: parseHHmm(shift.start_time), +// end_time: parseHHmm(shift.end_time), +// comment: shift.comment ?? null, +// is_approved: false, +// is_remote: false, +// }, +// }); +// } +// return this.query.getTimesheetByEmail(email, week_offset); +// } +// } \ No newline at end of file diff --git a/src/modules/timesheets/~misc_deprecated-files/timesheets-query.service.ts b/src/modules/timesheets/~misc_deprecated-files/timesheets-query.service.ts index bf09330..7999702 100644 --- a/src/modules/timesheets/~misc_deprecated-files/timesheets-query.service.ts +++ b/src/modules/timesheets/~misc_deprecated-files/timesheets-query.service.ts @@ -1,54 +1,54 @@ -import { makeEmptyTimesheet, mapExpenseRow, mapShiftRow } from './utils-helpers-others/timesheet.mappers'; -import { buildPeriod, computeWeekRange } from './utils-helpers-others/timesheet.utils'; -import { TimesheetSelectorsService } from './utils-helpers-others/timesheet.selectors'; -import { TimesheetPeriodDto } from './timesheet-period.dto'; -import { toRangeFromPeriod } from './utils-helpers-others/timesheet.helpers'; -import { EmailToIdResolver } from 'src/modules/shared/utils/resolve-email-id.utils'; -import { FullNameResolver } from 'src/modules/shared/utils/resolve-full-name.utils'; -import { PrismaService } from 'src/prisma/prisma.service'; -import { TimesheetMap } from './utils-helpers-others/timesheet.types'; -import { Injectable } from '@nestjs/common'; +// import { makeEmptyTimesheet, mapExpenseRow, mapShiftRow } from './utils-helpers-others/timesheet.mappers'; +// import { buildPeriod, computeWeekRange } from './utils-helpers-others/timesheet.utils'; +// import { TimesheetSelectorsService } from './utils-helpers-others/timesheet.selectors'; +// import { TimesheetPeriodDto } from './timesheet-period.dto'; +// import { toRangeFromPeriod } from './utils-helpers-others/timesheet.helpers'; +// import { EmailToIdResolver } from 'src/modules/shared/utils/resolve-email-id.utils'; +// import { FullNameResolver } from 'src/modules/shared/utils/resolve-full-name.utils'; +// import { PrismaService } from 'src/prisma/prisma.service'; +// import { TimesheetMap } from './utils-helpers-others/timesheet.types'; +// import { Injectable } from '@nestjs/common'; -@Injectable() -export class TimesheetsQueryService { - constructor( - private readonly prisma: PrismaService, - private readonly emailResolver: EmailToIdResolver, - private readonly fullNameResolver: FullNameResolver, - private readonly selectors: TimesheetSelectorsService, - ) {} +// @Injectable() +// export class TimesheetsQueryService { +// constructor( +// private readonly prisma: PrismaService, +// private readonly emailResolver: EmailToIdResolver, +// private readonly fullNameResolver: FullNameResolver, +// private readonly selectors: TimesheetSelectorsService, +// ) {} - async findAll(year: number, period_no: number, email: string): Promise { - const employee_id = await this.emailResolver.findIdByEmail(email); //finds the employee using email - const full_name = await this.fullNameResolver.resolveFullName(employee_id); //finds the employee full name using employee_id - const period = await this.selectors.getPayPeriod(year, period_no);//finds the pay period using year and period_no - const{ from, to } = toRangeFromPeriod(period); //finds start and end dates - //finds all shifts from selected period - const [raw_shifts, raw_expenses] = await Promise.all([ - this.selectors.getShifts(employee_id, from, to), - this.selectors.getExpenses(employee_id, from, to), - ]); - // data mapping - const shifts = raw_shifts.map(mapShiftRow); - const expenses = raw_expenses.map(mapExpenseRow); +// async findAll(year: number, period_no: number, email: string): Promise { +// const employee_id = await this.emailResolver.findIdByEmail(email); //finds the employee using email +// const full_name = await this.fullNameResolver.resolveFullName(employee_id); //finds the employee full name using employee_id +// const period = await this.selectors.getPayPeriod(year, period_no);//finds the pay period using year and period_no +// const{ from, to } = toRangeFromPeriod(period); //finds start and end dates +// //finds all shifts from selected period +// const [raw_shifts, raw_expenses] = await Promise.all([ +// this.selectors.getShifts(employee_id, from, to), +// this.selectors.getExpenses(employee_id, from, to), +// ]); +// // data mapping +// const shifts = raw_shifts.map(mapShiftRow); +// const expenses = raw_expenses.map(mapExpenseRow); - return buildPeriod(period.period_start, period.period_end, shifts , expenses, full_name); - } +// return buildPeriod(period.period_start, period.period_end, shifts , expenses, full_name); +// } - async getTimesheetByEmail(email: string, week_offset = 0): Promise { - const employee_id = await this.emailResolver.findIdByEmail(email); //finds the employee using email - const { start, start_day, end_day, label } = computeWeekRange(week_offset); - const timesheet = await this.selectors.getTimesheetWithShiftsAndExpenses(employee_id, start); //fetch timesheet shifts and expenses - if(!timesheet) return makeEmptyTimesheet({ start_day, end_day, label}); +// async getTimesheetByEmail(email: string, week_offset = 0): Promise { +// const employee_id = await this.emailResolver.findIdByEmail(email); //finds the employee using email +// const { start, start_day, end_day, label } = computeWeekRange(week_offset); +// const timesheet = await this.selectors.getTimesheetWithShiftsAndExpenses(employee_id, start); //fetch timesheet shifts and expenses +// if(!timesheet) return makeEmptyTimesheet({ start_day, end_day, label}); - //maps all shifts of selected timesheet - const shifts = timesheet.shift.map(mapShiftRow); - const expenses = timesheet.expense.map(mapExpenseRow); +// //maps all shifts of selected timesheet +// const shifts = timesheet.shift.map(mapShiftRow); +// const expenses = timesheet.expense.map(mapExpenseRow); - return { start_day, end_day, label, shifts, expenses, is_approved: timesheet.is_approved}; - } -} +// return { start_day, end_day, label, shifts, expenses, is_approved: timesheet.is_approved}; +// } +// } diff --git a/src/modules/timesheets/~misc_deprecated-files/timesheets.controller.ts b/src/modules/timesheets/~misc_deprecated-files/timesheets.controller.ts index 7eebd57..8ba1dee 100644 --- a/src/modules/timesheets/~misc_deprecated-files/timesheets.controller.ts +++ b/src/modules/timesheets/~misc_deprecated-files/timesheets.controller.ts @@ -1,51 +1,51 @@ -import { BadRequestException, Body, Controller, Get, Param, ParseIntPipe, Post, Query } from '@nestjs/common'; -import { TimesheetsQueryService } from './timesheets-query.service'; -import { CreateWeekShiftsDto } from './create-timesheet.dto'; -import { RolesAllowed } from "src/common/decorators/roles.decorators"; -import { Roles as RoleEnum } from '.prisma/client'; -import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; -import { TimesheetsCommandService } from './timesheets-command.service'; -import { TimesheetPeriodDto } from './timesheet-period.dto'; -import { TimesheetMap } from './timesheet.types'; +// import { BadRequestException, Body, Controller, Get, Param, ParseIntPipe, Post, Query } from '@nestjs/common'; +// import { TimesheetsQueryService } from './timesheets-query.service'; +// import { CreateWeekShiftsDto } from './create-timesheet.dto'; +// import { RolesAllowed } from "src/common/decorators/roles.decorators"; +// import { Roles as RoleEnum } from '.prisma/client'; +// import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; +// import { TimesheetsCommandService } from './timesheets-command.service'; +// import { TimesheetPeriodDto } from './timesheet-period.dto'; +// import { TimesheetMap } from './timesheet.types'; -@ApiTags('Timesheets') -@ApiBearerAuth('access-token') -// @UseGuards() -@Controller('timesheets') -export class TimesheetsController { - constructor( - private readonly timesheetsQuery: TimesheetsQueryService, - private readonly timesheetsCommand: TimesheetsCommandService, - ) {} +// @ApiTags('Timesheets') +// @ApiBearerAuth('access-token') +// // @UseGuards() +// @Controller('timesheets') +// export class TimesheetsController { +// constructor( +// private readonly timesheetsQuery: TimesheetsQueryService, +// private readonly timesheetsCommand: TimesheetsCommandService, +// ) {} - @Get() - //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) - async getPeriodByQuery( - @Query('year', ParseIntPipe ) year: number, - @Query('period_no', ParseIntPipe ) period_no: number, - @Query('email') email?: string - ): Promise { - if(!email || !(email = email.trim())) throw new BadRequestException('Query param "email" is mandatory for this route.'); - return this.timesheetsQuery.findAll(year, period_no, email); - } +// @Get() +// //@RolesAllowed(RoleEnum.ACCOUNTING, RoleEnum.ADMIN, RoleEnum.EMPLOYEE, RoleEnum.HR, RoleEnum.SUPERVISOR) +// async getPeriodByQuery( +// @Query('year', ParseIntPipe ) year: number, +// @Query('period_no', ParseIntPipe ) period_no: number, +// @Query('email') email?: string +// ): Promise { +// if(!email || !(email = email.trim())) throw new BadRequestException('Query param "email" is mandatory for this route.'); +// return this.timesheetsQuery.findAll(year, period_no, email); +// } - @Get('/:email') - async getByEmail( - @Param('email') email: string, - @Query('offset') offset?: string, - ): Promise { - const week_offset = Number.isFinite(Number(offset)) ? Number(offset) : 0; - return this.timesheetsQuery.getTimesheetByEmail(email, week_offset); - } +// @Get('/:email') +// async getByEmail( +// @Param('email') email: string, +// @Query('offset') offset?: string, +// ): Promise { +// const week_offset = Number.isFinite(Number(offset)) ? Number(offset) : 0; +// return this.timesheetsQuery.getTimesheetByEmail(email, week_offset); +// } - @Post('shifts/:email') - async createTimesheetShifts( - @Param('email') email: string, - @Body() dto: CreateWeekShiftsDto, - @Query('offset') offset?: string, - ): Promise { - const week_offset = Number.isFinite(Number(offset)) ? Number(offset) : 0; - return this.timesheetsCommand.createWeekShiftsAndReturnOverview(email, dto.shifts, week_offset); - } -} +// @Post('shifts/:email') +// async createTimesheetShifts( +// @Param('email') email: string, +// @Body() dto: CreateWeekShiftsDto, +// @Query('offset') offset?: string, +// ): Promise { +// const week_offset = Number.isFinite(Number(offset)) ? Number(offset) : 0; +// return this.timesheetsCommand.createWeekShiftsAndReturnOverview(email, dto.shifts, week_offset); +// } +// }