fix(leaves and expenses): import name fixes
This commit is contained in:
parent
10d4f11f76
commit
3984540edb
|
|
@ -77,30 +77,6 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"/archives/leaveRequests": {
|
||||
"get": {
|
||||
"operationId": "LeaveRequestsArchiveController_findOneArchived",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Archived leaveRequest found"
|
||||
}
|
||||
},
|
||||
"summary": "Fetch leaveRequest in archives with its Id",
|
||||
"tags": [
|
||||
"LeaveRequests Archives"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/archives/shifts": {
|
||||
"get": {
|
||||
"operationId": "ShiftsArchiveController_findOneArchived",
|
||||
|
|
@ -1256,215 +1232,22 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"/leave-requests": {
|
||||
"/leave-requests/holiday": {
|
||||
"post": {
|
||||
"operationId": "LeaveRequestController_create",
|
||||
"operationId": "LeaveRequestController_upsertHoliday",
|
||||
"parameters": [],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CreateLeaveRequestsDto"
|
||||
"$ref": "#/components/schemas/UpsertHolidayDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Leave request created",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CreateLeaveRequestsDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Incomplete task or invalid data"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"access-token": []
|
||||
}
|
||||
],
|
||||
"summary": "Create leave request",
|
||||
"tags": [
|
||||
"Leave Requests"
|
||||
]
|
||||
},
|
||||
"get": {
|
||||
"operationId": "LeaveRequestController_findAll",
|
||||
"parameters": [],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "List of Leave requests found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/LeaveRequestViewDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "List of leave request not found"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"access-token": []
|
||||
}
|
||||
],
|
||||
"summary": "Find all leave request",
|
||||
"tags": [
|
||||
"Leave Requests"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/leave-requests/{id}": {
|
||||
"get": {
|
||||
"operationId": "LeaveRequestController_findOne",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Leave request found",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/LeaveRequestViewDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Leave request not found"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"access-token": []
|
||||
}
|
||||
],
|
||||
"summary": "Find leave request",
|
||||
"tags": [
|
||||
"Leave Requests"
|
||||
]
|
||||
},
|
||||
"patch": {
|
||||
"operationId": "LeaveRequestController_update",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"required": true,
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/UpdateLeaveRequestsDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Leave request updated",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/LeaveRequestViewDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Leave request not found"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"access-token": []
|
||||
}
|
||||
],
|
||||
"summary": "Update leave request",
|
||||
"tags": [
|
||||
"Leave Requests"
|
||||
]
|
||||
},
|
||||
"delete": {
|
||||
"operationId": "LeaveRequestController_remove",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Leave request deleted",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CreateLeaveRequestsDto"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Leave request not found"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"access-token": []
|
||||
}
|
||||
],
|
||||
"summary": "Delete leave request",
|
||||
"tags": [
|
||||
"Leave Requests"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/leave-requests/approval/{id}": {
|
||||
"patch": {
|
||||
"operationId": "LeaveRequestController_updateApproval",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"required": true,
|
||||
"in": "path",
|
||||
"schema": {
|
||||
"type": "number"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
|
|
@ -2691,88 +2474,10 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"CreateLeaveRequestsDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bank_code_id": {
|
||||
"type": "number",
|
||||
"example": 7,
|
||||
"description": "ID number of a leave-request code (link with bank-codes)"
|
||||
},
|
||||
"leave_type": {
|
||||
"type": "string",
|
||||
"example": "Sick or Vacation or Unpaid or Bereavement or Parental or Legal",
|
||||
"description": "type of leave request for an accounting perception"
|
||||
},
|
||||
"start_date_time": {
|
||||
"type": "string",
|
||||
"example": "22/06/2463",
|
||||
"description": "Leave request`s start date"
|
||||
},
|
||||
"end_date_time": {
|
||||
"type": "string",
|
||||
"example": "25/03/3019",
|
||||
"description": "Leave request`s end date"
|
||||
},
|
||||
"comment": {
|
||||
"type": "string",
|
||||
"example": "My precious",
|
||||
"description": "Leave request`s comment"
|
||||
},
|
||||
"approval_status": {
|
||||
"type": "string",
|
||||
"example": "True or False or Pending or Denied or Cancelled or Escalated",
|
||||
"description": "Leave request`s approval status"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"bank_code_id",
|
||||
"leave_type",
|
||||
"start_date_time",
|
||||
"end_date_time",
|
||||
"comment",
|
||||
"approval_status"
|
||||
]
|
||||
},
|
||||
"LeaveRequestViewDto": {
|
||||
"UpsertHolidayDto": {
|
||||
"type": "object",
|
||||
"properties": {}
|
||||
},
|
||||
"UpdateLeaveRequestsDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bank_code_id": {
|
||||
"type": "number",
|
||||
"example": 7,
|
||||
"description": "ID number of a leave-request code (link with bank-codes)"
|
||||
},
|
||||
"leave_type": {
|
||||
"type": "string",
|
||||
"example": "Sick or Vacation or Unpaid or Bereavement or Parental or Legal",
|
||||
"description": "type of leave request for an accounting perception"
|
||||
},
|
||||
"start_date_time": {
|
||||
"type": "string",
|
||||
"example": "22/06/2463",
|
||||
"description": "Leave request`s start date"
|
||||
},
|
||||
"end_date_time": {
|
||||
"type": "string",
|
||||
"example": "25/03/3019",
|
||||
"description": "Leave request`s end date"
|
||||
},
|
||||
"comment": {
|
||||
"type": "string",
|
||||
"example": "My precious",
|
||||
"description": "Leave request`s comment"
|
||||
},
|
||||
"approval_status": {
|
||||
"type": "string",
|
||||
"example": "True or False or Pending or Denied or Cancelled or Escalated",
|
||||
"description": "Leave request`s approval status"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CreateBankCodeDto": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import { PrismaClient, Prisma, LeaveTypes, LeaveApprovalStatus } from '@prisma/client';
|
||||
|
||||
if (process.env.SKIP_LEAVE_REQUESTS === 'true') {
|
||||
console.log("⏭ Seed leave-requests ignoré (SKIP_LEAVE_REQUESTS=true)");
|
||||
console.log('?? Seed leave-requests ignoré (SKIP_LEAVE_REQUESTS=true)');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
function dateOn(y: number, m: number, d: number) {
|
||||
// stocke une date (pour @db.Date) à minuit UTC
|
||||
// stocke une date (@db.Date) à minuit UTC
|
||||
return new Date(Date.UTC(y, m - 1, d, 0, 0, 0));
|
||||
}
|
||||
|
||||
|
|
@ -19,7 +19,7 @@ async function main() {
|
|||
const employees = await prisma.employees.findMany({ select: { id: true } });
|
||||
const bankCodes = await prisma.bankCodes.findMany({
|
||||
where: { categorie: 'LEAVE' },
|
||||
select: { id: true },
|
||||
select: { id: true, type: true },
|
||||
});
|
||||
|
||||
if (!employees.length || !bankCodes.length) {
|
||||
|
|
@ -44,30 +44,31 @@ async function main() {
|
|||
LeaveApprovalStatus.ESCALATED,
|
||||
];
|
||||
|
||||
const futureMonths = [8, 9, 10, 11, 12]; // Août→Déc (1-based)
|
||||
const futureMonths = [8, 9, 10, 11, 12]; // Août ? Déc. (1-based)
|
||||
|
||||
// ✅ typer rows pour éviter never[]
|
||||
const rows: Prisma.LeaveRequestsCreateManyInput[] = [];
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const emp = employees[i % employees.length];
|
||||
const m = futureMonths[i % futureMonths.length];
|
||||
const start = dateOn(year, m, 5 + i); // 5..14
|
||||
if (start <= today) continue; // garantir "futur"
|
||||
const date = dateOn(year, m, 5 + i); // 5..14
|
||||
if (date <= today) continue; // garantir « futur »
|
||||
|
||||
const end = Math.random() < 0.5 ? null : dateOn(year, m, 6 + i);
|
||||
const type = types[i % types.length];
|
||||
const status = statuses[i % statuses.length];
|
||||
const bc = bankCodes[i % bankCodes.length];
|
||||
const requestedHours = 4 + (i % 5); // 4 ? 8 h
|
||||
const payableHours = status === LeaveApprovalStatus.APPROVED ? Math.min(requestedHours, 8) : null;
|
||||
|
||||
rows.push({
|
||||
employee_id: emp.id,
|
||||
bank_code_id: bc.id,
|
||||
leave_type: type,
|
||||
start_date_time: start,
|
||||
end_date_time: end, // ok: Date | null
|
||||
comment: `Future leave #${i + 1}`,
|
||||
date,
|
||||
comment: `Future leave #${i + 1} (${bc.type})`,
|
||||
approval_status: status,
|
||||
requested_hours: requestedHours,
|
||||
payable_hours: payableHours,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -75,7 +76,7 @@ async function main() {
|
|||
await prisma.leaveRequests.createMany({ data: rows });
|
||||
}
|
||||
|
||||
console.log(`✓ LeaveRequests (future): ${rows.length} rows`);
|
||||
console.log(`? LeaveRequests (future): ${rows.length} rows`);
|
||||
}
|
||||
|
||||
main().finally(() => prisma.$disconnect());
|
||||
main().finally(() => prisma.$disconnect());
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { PrismaClient, LeaveApprovalStatus, LeaveRequests } from '@prisma/client';
|
||||
import { PrismaClient, LeaveApprovalStatus, LeaveTypes } from '@prisma/client';
|
||||
|
||||
if (process.env.SKIP_LEAVE_REQUESTS === 'true') {
|
||||
console.log("⏭ Seed leave-requests ignoré (SKIP_LEAVE_REQUESTS=true)");
|
||||
console.log('?? Seed leave-requests ignoré (SKIP_LEAVE_REQUESTS=true)');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
|
|
@ -15,65 +15,73 @@ function daysAgo(n: number) {
|
|||
}
|
||||
|
||||
async function main() {
|
||||
// 1) Récupère tous les employés
|
||||
const employees = await prisma.employees.findMany({ select: { id: true } });
|
||||
if (!employees.length) {
|
||||
throw new Error('Aucun employé trouvé. Exécute le seed employees avant celui-ci.');
|
||||
throw new Error('Aucun employé trouvé. Exécute le seed employees avant celui-ci.');
|
||||
}
|
||||
|
||||
// 2) Va chercher les bank codes dont le type est SICK, VACATION ou HOLIDAY
|
||||
const leaveCodes = await prisma.bankCodes.findMany({
|
||||
where: { type: { in: ['SICK', 'VACATION'] } },
|
||||
select: { id: true, type: true, bank_code: true },
|
||||
where: { type: { in: ['SICK', 'VACATION', 'HOLIDAY'] } },
|
||||
select: { id: true, type: true },
|
||||
});
|
||||
if (!leaveCodes.length) {
|
||||
throw new Error("Aucun bank code trouvé avec type in ('SICK','VACATION','HOLIDAY'). Vérifie ta table bank_codes.");
|
||||
throw new Error("Aucun bank code trouvé avec type in ('SICK','VACATION','HOLIDAY'). Vérifie ta table bank_codes.");
|
||||
}
|
||||
|
||||
const statuses = Object.values(LeaveApprovalStatus);
|
||||
const created: LeaveRequests[] = [];
|
||||
const created = [] as Array<{ id: number; employee_id: number; leave_type: LeaveTypes; date: Date; comment: string; approval_status: LeaveApprovalStatus; requested_hours: number; payable_hours: number | null }>;
|
||||
|
||||
// 3) Crée quelques leave requests
|
||||
const COUNT = 12;
|
||||
for (let i = 0; i < COUNT; i++) {
|
||||
const emp = employees[i % employees.length];
|
||||
const leaveCode = leaveCodes[Math.floor(Math.random() * leaveCodes.length)];
|
||||
|
||||
const start = daysAgo(120 - i * 3);
|
||||
const end = Math.random() < 0.6 ? daysAgo(119 - i * 3) : null;
|
||||
const date = daysAgo(120 - i * 3);
|
||||
const status = statuses[(i + 2) % statuses.length];
|
||||
const requestedHours = 4 + (i % 5); // 4 ? 8 h
|
||||
const payableHours = status === LeaveApprovalStatus.APPROVED ? Math.min(requestedHours, 8) : null;
|
||||
|
||||
const lr = await prisma.leaveRequests.create({
|
||||
data: {
|
||||
employee_id: emp.id,
|
||||
bank_code_id: leaveCode.id,
|
||||
// on stocke le "type" tel qu’il est défini dans bank_codes
|
||||
leave_type: leaveCode.type as any,
|
||||
start_date_time: start,
|
||||
end_date_time: end,
|
||||
leave_type: leaveCode.type as LeaveTypes,
|
||||
date,
|
||||
comment: `Past leave #${i + 1} (${leaveCode.type})`,
|
||||
approval_status: statuses[(i + 2) % statuses.length],
|
||||
approval_status: status,
|
||||
requested_hours: requestedHours,
|
||||
payable_hours: payableHours,
|
||||
},
|
||||
});
|
||||
|
||||
created.push(lr);
|
||||
created.push({
|
||||
id: lr.id,
|
||||
employee_id: lr.employee_id,
|
||||
leave_type: lr.leave_type,
|
||||
date: lr.date,
|
||||
comment: lr.comment,
|
||||
approval_status: lr.approval_status,
|
||||
requested_hours: requestedHours,
|
||||
payable_hours: payableHours,
|
||||
});
|
||||
}
|
||||
|
||||
// 4) Archive
|
||||
for (const lr of created) {
|
||||
await prisma.leaveRequestsArchive.create({
|
||||
data: {
|
||||
leave_request_id: lr.id,
|
||||
employee_id: lr.employee_id,
|
||||
leave_type: lr.leave_type,
|
||||
start_date_time: lr.start_date_time,
|
||||
end_date_time: lr.end_date_time,
|
||||
date: lr.date,
|
||||
comment: lr.comment,
|
||||
approval_status: lr.approval_status,
|
||||
requested_hours: lr.requested_hours,
|
||||
payable_hours: lr.payable_hours,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`✓ LeaveRequestsArchive: ${created.length} rows`);
|
||||
console.log(`? LeaveRequestsArchive: ${created.length} rows`);
|
||||
}
|
||||
|
||||
main().finally(() => prisma.$disconnect());
|
||||
main().finally(() => prisma.$disconnect());
|
||||
|
|
@ -28,7 +28,7 @@ import { EmployeesModule } from "../employees/employees.module";
|
|||
LeaveRequestsArchiveController,
|
||||
ShiftsArchiveController,
|
||||
TimesheetsArchiveController,
|
||||
]
|
||||
],
|
||||
})
|
||||
|
||||
export class ArchivalModule {}
|
||||
|
|
@ -1,33 +1,7 @@
|
|||
import { Get, Param, ParseIntPipe, NotFoundException, Controller, UseGuards } from "@nestjs/common";
|
||||
import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
|
||||
import { LeaveRequestsArchive, Roles as RoleEnum } from "@prisma/client";
|
||||
import { RolesAllowed } from "src/common/decorators/roles.decorators";
|
||||
import { LeaveRequestViewDto } from "src/modules/leave-requests/dtos/leave-request.view.dto";
|
||||
import { LeaveRequestsService } from "src/modules/leave-requests/services/holiday-leave-requests.service";
|
||||
import { Controller } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
|
||||
@ApiTags('LeaveRequests Archives')
|
||||
// @UseGuards()
|
||||
@Controller('archives/leaveRequests')
|
||||
export class LeaveRequestsArchiveController {
|
||||
constructor(private readonly leaveRequestsService: LeaveRequestsService) {}
|
||||
|
||||
@Get()
|
||||
//@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||
@ApiOperation({ summary: 'List of archived leaveRequests'})
|
||||
@ApiResponse({ status: 200, description: 'List of archived leaveRequests', isArray: true })
|
||||
async findAllArchived(): Promise<LeaveRequestsArchive[]> {
|
||||
return this.leaveRequestsService.findAllArchived();
|
||||
}
|
||||
|
||||
@Get()
|
||||
//@RolesAllowed(RoleEnum.ADMIN, RoleEnum.HR, RoleEnum.SUPERVISOR)
|
||||
@ApiOperation({ summary: 'Fetch leaveRequest in archives with its Id'})
|
||||
@ApiResponse({ status: 200, description: 'Archived leaveRequest found'})
|
||||
async findOneArchived(@Param('id', ParseIntPipe) id: number ): Promise<LeaveRequestViewDto> {
|
||||
try{
|
||||
return await this.leaveRequestsService.findOneArchived(id);
|
||||
}catch {
|
||||
throw new NotFoundException(`Archived leaveRequest #${id} not found`);
|
||||
}
|
||||
}
|
||||
}
|
||||
export class LeaveRequestsArchiveController {}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
import { Injectable, Logger } from "@nestjs/common";
|
||||
import { Cron } from "@nestjs/schedule";
|
||||
import { ExpensesQueryService } from "src/modules/expenses/services/expenses-query.service";
|
||||
import { LeaveRequestsService } from "src/modules/leave-requests/services/holiday-leave-requests.service";
|
||||
import { ShiftsQueryService } from "src/modules/shifts/services/shifts-query.service";
|
||||
import { TimesheetsQueryService } from "src/modules/timesheets/services/timesheets-query.service";
|
||||
|
||||
|
|
@ -13,7 +12,6 @@ export class ArchivalService {
|
|||
private readonly timesheetsService: TimesheetsQueryService,
|
||||
private readonly expensesService: ExpensesQueryService,
|
||||
private readonly shiftsService: ShiftsQueryService,
|
||||
private readonly leaveRequestsService: LeaveRequestsService,
|
||||
) {}
|
||||
|
||||
@Cron('0 0 3 * * 1', {timeZone:'America/Toronto'}) // chaque premier lundi du mois à 03h00
|
||||
|
|
@ -31,7 +29,7 @@ export class ArchivalService {
|
|||
await this.timesheetsService.archiveOld();
|
||||
await this.expensesService.archiveOld();
|
||||
await this.shiftsService.archiveOld();
|
||||
await this.leaveRequestsService.archiveExpired();
|
||||
// await this.leaveRequestsService.archiveExpired();
|
||||
this.logger.log('archivation process done');
|
||||
} catch (err) {
|
||||
this.logger.error('an error occured during archivation process ', err);
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ export class ExpensesCommandService extends BaseApprovalService<Expenses> {
|
|||
}
|
||||
|
||||
//validate date format
|
||||
const dateOnly = toDateOnlyUTC(date);
|
||||
if(Number.isNaN(dateOnly.getTime())) {
|
||||
const date_only = toDateOnlyUTC(date);
|
||||
if(Number.isNaN(date_only.getTime())) {
|
||||
throw new BadRequestException('Invalid date format (expected: YYYY-MM-DD)');
|
||||
}
|
||||
|
||||
|
|
@ -62,14 +62,14 @@ export class ExpensesCommandService extends BaseApprovalService<Expenses> {
|
|||
const employee_id = await this.resolveEmployeeIdByEmail(email);
|
||||
|
||||
//make sure a timesheet existes
|
||||
const timesheet_id = await this.ensureTimesheetForDate(employee_id, dateOnly);
|
||||
const timesheet_id = await this.ensureTimesheetForDate(employee_id, date_only);
|
||||
|
||||
return this.prisma.$transaction(async (tx) => {
|
||||
const loadDay = async (): Promise<ExpenseResponse[]> => {
|
||||
const rows = await tx.expenses.findMany({
|
||||
where: {
|
||||
timesheet_id: timesheet_id,
|
||||
date: dateOnly,
|
||||
date: date_only,
|
||||
},
|
||||
include: {
|
||||
bank_code: {
|
||||
|
|
@ -160,7 +160,7 @@ export class ExpensesCommandService extends BaseApprovalService<Expenses> {
|
|||
return tx.expenses.findFirst({
|
||||
where: {
|
||||
timesheet_id: timesheet_id,
|
||||
date: dateOnly,
|
||||
date: date_only,
|
||||
bank_code_id: norm.bank_code_id,
|
||||
amount: norm.amount,
|
||||
comment: norm.comment,
|
||||
|
|
@ -191,7 +191,7 @@ export class ExpensesCommandService extends BaseApprovalService<Expenses> {
|
|||
await tx.expenses.create({
|
||||
data: {
|
||||
timesheet_id: timesheet_id,
|
||||
date: dateOnly,
|
||||
date: date_only,
|
||||
bank_code_id: new_exp.bank_code_id,
|
||||
amount: new_exp.amount,
|
||||
mileage: new_exp.mileage,
|
||||
|
|
|
|||
|
|
@ -9,5 +9,6 @@ export interface ExpenseResponse {
|
|||
};
|
||||
|
||||
export type UpsertExpenseResult = {
|
||||
expenses: ExpenseResponse[]
|
||||
action: UpsertAction;
|
||||
day: ExpenseResponse[]
|
||||
};
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { BadRequestException } from "@nestjs/common";
|
||||
import { DayExpenseResponse } from "../types and interfaces/expenses.types.interfaces";
|
||||
import { ExpenseResponse } from "../types and interfaces/expenses.types.interfaces";
|
||||
import { Prisma } from "@prisma/client";
|
||||
|
||||
//uppercase and trim for validation
|
||||
|
|
@ -55,7 +55,7 @@ export function mapDbExpenseToDayResponse(row: {
|
|||
comment: string;
|
||||
is_approved: boolean;
|
||||
bank_code?: { type?: string | null } | null;
|
||||
}): DayExpenseResponse {
|
||||
}): ExpenseResponse {
|
||||
const yyyyMmDd = row.date.toISOString().slice(0,10);
|
||||
const toNum = (value: any)=> (value == null ? 0 : Number(value));
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -10,5 +10,5 @@ export class LeaveRequestViewDto {
|
|||
employee_full_name!: string;
|
||||
payable_hours?: number;
|
||||
requested_hours?: number;
|
||||
action?: 'created' | 'updated' | 'deleted';
|
||||
action?: 'create' | 'update' | 'delete';
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ 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 { ShiftsCommandService } from "../shifts/services/shifts-command.service";
|
||||
|
||||
@Module({
|
||||
imports: [BusinessLogicsModule],
|
||||
|
|
@ -12,6 +13,7 @@ import { BusinessLogicsModule } from "src/modules/business-logics/business-logic
|
|||
HolidayService,
|
||||
HolidayLeaveRequestsService,
|
||||
PrismaService,
|
||||
ShiftsCommandService,
|
||||
],
|
||||
exports: [HolidayLeaveRequestsService],
|
||||
})
|
||||
|
|
|
|||
|
|
@ -6,13 +6,13 @@ const toNum = (value?: Prisma.Decimal | null) =>
|
|||
value !== null && value !== undefined ? Number(value) : undefined;
|
||||
|
||||
export function mapRowToView(row: LeaveRequestRow): LeaveRequestViewDto {
|
||||
const isoDate = row.date?.toISOString().slice(0, 10);
|
||||
if (!isoDate) throw new Error(`Leave request #${row.id} has no date set.`);
|
||||
const iso_date = row.date?.toISOString().slice(0, 10);
|
||||
if (!iso_date) throw new Error(`Leave request #${row.id} has no date set.`);
|
||||
|
||||
return {
|
||||
id: row.id,
|
||||
leave_type: row.leave_type,
|
||||
date: isoDate,
|
||||
date: iso_date,
|
||||
payable_hours: toNum(row.payable_hours),
|
||||
requested_hours: toNum(row.requested_hours),
|
||||
comment: row.comment,
|
||||
|
|
|
|||
|
|
@ -3,16 +3,14 @@ import {
|
|||
Injectable,
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { LeaveApprovalStatus, LeaveTypes } from '@prisma/client';
|
||||
|
||||
import { HolidayService } from 'src/modules/business-logics/services/holiday.service';
|
||||
import { ShiftsCommandService } from 'src/modules/shifts/services/shifts-command.service';
|
||||
import { PrismaService } from 'src/prisma/prisma.service';
|
||||
|
||||
import { LeaveRequestViewDto } from '../dtos/leave-request-view.dto';
|
||||
import { LeaveApprovalStatus, LeaveTypes } from '@prisma/client';
|
||||
import { HolidayUpsertAction, UpsertHolidayDto } from '../dtos/upsert-holiday.dto';
|
||||
import { mapRowToView } from '../mappers/leave-requests.mapper';
|
||||
import { leaveRequestsSelect } from '../utils/leave-requests.select';
|
||||
import { HolidayService } from 'src/modules/business-logics/services/holiday.service';
|
||||
import { ShiftsCommandService } from 'src/modules/shifts/services/shifts-command.service';
|
||||
import { PrismaService } from 'src/prisma/prisma.service';
|
||||
import { LeaveRequestViewDto } from '../dtos/leave-request-view.dto';
|
||||
import { mapRowToView } from '../mappers/leave-requests.mapper';
|
||||
import { leaveRequestsSelect } from '../utils/leave-requests.select';
|
||||
|
||||
interface HolidayUpsertResult {
|
||||
action: HolidayUpsertAction;
|
||||
|
|
@ -204,7 +202,7 @@ export class HolidayLeaveRequestsService {
|
|||
where: { id: { in: rows.map((row) => row.id) } },
|
||||
});
|
||||
|
||||
const deleted = rows.map((row) => ({ ...mapRowToView(row), action: 'delete' }));
|
||||
const deleted = rows.map((row) => ({ ...mapRowToView(row), action: 'delete' as const}));
|
||||
return { action: 'delete', leave_requests: deleted };
|
||||
}
|
||||
|
||||
|
|
@ -320,4 +318,4 @@ const toDateOnly = (iso: string): Date => {
|
|||
const toISODateKey = (date: Date): string => date.toISOString().slice(0, 10);
|
||||
|
||||
const normalizeDates = (dates: string[]): string[] =>
|
||||
Array.from(new Set(dates.map((iso) => toISODateKey(toDateOnly(iso)))));
|
||||
Array.from(new Set(dates.map((iso) => toISODateKey(toDateOnly(iso)))));
|
||||
|
|
|
|||
|
|
@ -1,32 +1,19 @@
|
|||
import { LeaveRequestViewDto } from "../dtos/leave-request.view.dto";
|
||||
import { mapArchiveRowToView } from "../mappers/leave-requests-archive.mapper";
|
||||
import { mapRowToView } from "../mappers/leave-requests.mapper";
|
||||
import { LeaveRequestArchiveRow } from "./leave-requests-archive.select";
|
||||
import { LeaveRequestRow } from "./leave-requests.select";
|
||||
import { LeaveRequestViewDto } from '../dtos/leave-request-view.dto';
|
||||
import { mapArchiveRowToView } from '../mappers/leave-requests-archive.mapper';
|
||||
import { mapRowToView } from '../mappers/leave-requests.mapper';
|
||||
import { LeaveRequestArchiveRow } from './leave-requests-archive.select';
|
||||
import { LeaveRequestRow } from './leave-requests.select';
|
||||
|
||||
function toUTCDateOnly(date: Date): Date {
|
||||
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
|
||||
}
|
||||
|
||||
const MS_PER_DAY = 86_400_000;
|
||||
function computeDaysRequested(start_date: Date, end_date?: Date | null): number {
|
||||
const start = toUTCDateOnly(start_date);
|
||||
const end = toUTCDateOnly(end_date ?? start_date);
|
||||
const diff = Math.floor((end.getTime() - start.getTime()) / MS_PER_DAY) + 1;
|
||||
return Math.max(1, diff);
|
||||
}
|
||||
|
||||
/** Active (table leave_requests) : map + days_requested */
|
||||
/** Active (table leave_requests) : proxy to base mapper */
|
||||
export function mapRowToViewWithDays(row: LeaveRequestRow): LeaveRequestViewDto {
|
||||
const view = mapRowToView(row);
|
||||
view.days_requested = computeDaysRequested(row.start_date_time, row.end_date_time);
|
||||
return view;
|
||||
return mapRowToView(row);
|
||||
}
|
||||
|
||||
/** Archive (table leave_requests_archive) : map + days_requested */
|
||||
export function mapArchiveRowToViewWithDays(row: LeaveRequestArchiveRow, email: string, employee_full_name?: string):
|
||||
LeaveRequestViewDto {
|
||||
const view = mapArchiveRowToView(row, email, employee_full_name!);
|
||||
view.days_requested = computeDaysRequested(row.start_date_time, row.end_date_time);
|
||||
return view;
|
||||
/** Archive (table leave_requests_archive) : proxy to base mapper */
|
||||
export function mapArchiveRowToViewWithDays(
|
||||
row: LeaveRequestArchiveRow,
|
||||
email: string,
|
||||
employee_full_name?: string,
|
||||
): LeaveRequestViewDto {
|
||||
return mapArchiveRowToView(row, email, employee_full_name!);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user