fix(shifts): changed UTC comparison for ISOString
This commit is contained in:
parent
1954d206a8
commit
af8ea95cc4
|
|
@ -1,23 +1,27 @@
|
||||||
export function timeFromHHMMUTC(hhmm: string): Date {
|
export function timeFromHHMM(hhmm: string): Date {
|
||||||
const [hour, min] = hhmm.split(':').map(Number);
|
const [hour, min] = hhmm.split(':').map(Number);
|
||||||
return new Date(Date.UTC(1970,0,1,hour, min,0));
|
return new Date(1970, 0, 1, hour, min, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function weekStartSundayUTC(d: Date): Date {
|
export function weekStartSunday(d: Date): Date {
|
||||||
const day = d.getUTCDay();
|
const start = new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
||||||
const start = new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate()));
|
const day = start.getDay(); // 0 = dimanche
|
||||||
start.setUTCDate(start.getUTCDate()- day);
|
start.setDate(start.getDate() - day);
|
||||||
return start;
|
start.setHours(0, 0, 0, 0);
|
||||||
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toDateOnlyUTC(input: string | Date): Date {
|
export function toDateOnly(input: string | Date): Date {
|
||||||
const date = new Date(input);
|
const base = (typeof input === 'string') ? new Date(input) : new Date(input);
|
||||||
return new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
|
const y = (typeof input === 'string') ? Number(input.slice(0,4)) : base.getFullYear();
|
||||||
|
const m = (typeof input === 'string') ? Number(input.slice(5,7)) - 1 : base.getMonth();
|
||||||
|
const d = (typeof input === 'string') ? Number(input.slice(8,10)) : base.getDate();
|
||||||
|
return new Date(y, m, d, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatHHmm(time: Date): string {
|
export function formatHHmm(time: Date): string {
|
||||||
const hh = String(time.getUTCHours()).padStart(2,'0');
|
const hh = String(time.getHours()).padStart(2,'0');
|
||||||
const mm = String(time.getUTCMinutes()).padStart(2,'0');
|
const mm = String(time.getMinutes()).padStart(2,'0');
|
||||||
return `${hh}:${mm}`;
|
return `${hh}:${mm}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { BadRequestException, ConflictException, Injectable, Logger, NotFoundException, UnprocessableEntityException } from "@nestjs/common";
|
import { BadRequestException, ConflictException, Injectable, Logger, NotFoundException, UnprocessableEntityException } from "@nestjs/common";
|
||||||
import { formatHHmm, toDateOnlyUTC, weekStartSundayUTC } from "../helpers/shifts-date-time-helpers";
|
|
||||||
import { normalizeShiftPayload, overlaps } from "../utils/shifts.utils";
|
import { normalizeShiftPayload, overlaps } from "../utils/shifts.utils";
|
||||||
import { DayShiftResponse, UpsertAction } from "../types-and-interfaces/shifts-upsert.types";
|
import { DayShiftResponse, UpsertAction } from "../types-and-interfaces/shifts-upsert.types";
|
||||||
import { EmployeeIdEmailResolver } from "src/modules/shared/utils/resolve-email-id.utils";
|
import { EmployeeIdEmailResolver } from "src/modules/shared/utils/resolve-email-id.utils";
|
||||||
|
|
@ -9,6 +8,7 @@ import { UpsertShiftDto } from "../dtos/upsert-shift.dto";
|
||||||
import { BaseApprovalService } from "src/common/shared/base-approval.service";
|
import { BaseApprovalService } from "src/common/shared/base-approval.service";
|
||||||
import { PrismaService } from "src/prisma/prisma.service";
|
import { PrismaService } from "src/prisma/prisma.service";
|
||||||
import { OvertimeService } from "src/modules/business-logics/services/overtime.service";
|
import { OvertimeService } from "src/modules/business-logics/services/overtime.service";
|
||||||
|
import { formatHHmm, toDateOnly, weekStartSunday } from "../helpers/shifts-date-time-helpers";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ShiftsCommandService extends BaseApprovalService<Shifts> {
|
export class ShiftsCommandService extends BaseApprovalService<Shifts> {
|
||||||
|
|
@ -49,11 +49,11 @@ export class ShiftsCommandService extends BaseApprovalService<Shifts> {
|
||||||
throw new BadRequestException('At least one of old or new shift must be provided');
|
throw new BadRequestException('At least one of old or new shift must be provided');
|
||||||
}
|
}
|
||||||
|
|
||||||
const date_only = toDateOnlyUTC(date_string);
|
const date_only = toDateOnly(date_string);
|
||||||
const employee_id = await this.emailResolver.findIdByEmail(email);
|
const employee_id = await this.emailResolver.findIdByEmail(email);
|
||||||
|
|
||||||
return this.prisma.$transaction(async (tx) => {
|
return this.prisma.$transaction(async (tx) => {
|
||||||
const start_of_week = weekStartSundayUTC(date_only);
|
const start_of_week = weekStartSunday(date_only);
|
||||||
|
|
||||||
const timesheet = await tx.timesheets.upsert({
|
const timesheet = await tx.timesheets.upsert({
|
||||||
where: { employee_id_start_date: { employee_id, start_date: start_of_week } },
|
where: { employee_id_start_date: { employee_id, start_date: start_of_week } },
|
||||||
|
|
@ -65,16 +65,16 @@ export class ShiftsCommandService extends BaseApprovalService<Shifts> {
|
||||||
//validation/sanitation
|
//validation/sanitation
|
||||||
//resolve bank_code_id using type
|
//resolve bank_code_id using type
|
||||||
const old_norm_shift = old_shift ? await normalizeShiftPayload(old_shift) : undefined;
|
const old_norm_shift = old_shift ? await normalizeShiftPayload(old_shift) : undefined;
|
||||||
// if (old_norm_shift && old_norm_shift.end_time.getTime() <= old_norm_shift.start_time.getTime()) {
|
if (old_norm_shift && old_norm_shift.end_time.getTime() <= old_norm_shift.start_time.getTime()) {
|
||||||
// throw new UnprocessableEntityException(' old_shift.end_time must be > old_shift.start_time');
|
throw new UnprocessableEntityException(' old_shift.end_time must be > old_shift.start_time');
|
||||||
// }
|
}
|
||||||
const old_bank_code_id: number | undefined = old_norm_shift ? (await this.bankTypeResolver.findByType(old_norm_shift.type, tx))?.id : undefined;
|
const old_bank_code_id: number | undefined = old_norm_shift ? (await this.bankTypeResolver.findByType(old_norm_shift.type, tx))?.id : undefined;
|
||||||
|
|
||||||
|
|
||||||
const new_norm_shift = new_shift ? await normalizeShiftPayload(new_shift) : undefined;
|
const new_norm_shift = new_shift ? await normalizeShiftPayload(new_shift) : undefined;
|
||||||
// if (new_norm_shift && new_norm_shift.end_time.getTime() <= new_norm_shift.start_time.getTime()) {
|
if (new_norm_shift && new_norm_shift.end_time.getTime() <= new_norm_shift.start_time.getTime()) {
|
||||||
// throw new UnprocessableEntityException(' new_shift.end_time must be > new_shift.start_time');
|
throw new UnprocessableEntityException(' new_shift.end_time must be > new_shift.start_time');
|
||||||
// }
|
}
|
||||||
const new_bank_code_id: number | undefined = new_norm_shift ? (await this.bankTypeResolver.findByType(new_norm_shift.type, tx))?.id : undefined;
|
const new_bank_code_id: number | undefined = new_norm_shift ? (await this.bankTypeResolver.findByType(new_norm_shift.type, tx))?.id : undefined;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -105,28 +105,28 @@ export class ShiftsCommandService extends BaseApprovalService<Shifts> {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// //checks for overlaping shifts
|
//checks for overlaping shifts
|
||||||
// const assertNoOverlap = (exclude_shift_id?: number)=> {
|
const assertNoOverlap = (exclude_shift_id?: number)=> {
|
||||||
// if (!new_norm_shift) return;
|
if (!new_norm_shift) return;
|
||||||
// const overlap_with = day_shifts.filter((shift)=> {
|
const overlap_with = day_shifts.filter((shift)=> {
|
||||||
// if(exclude_shift_id && shift.id === exclude_shift_id) return false;
|
if(exclude_shift_id && shift.id === exclude_shift_id) return false;
|
||||||
// return overlaps(
|
return overlaps(
|
||||||
// new_norm_shift.start_time.getTime(),
|
new_norm_shift.start_time.getTime(),
|
||||||
// new_norm_shift.end_time.getTime(),
|
new_norm_shift.end_time.getTime(),
|
||||||
// shift.start_time.getTime(),
|
shift.start_time.getTime(),
|
||||||
// shift.end_time.getTime(),
|
shift.end_time.getTime(),
|
||||||
// );
|
);
|
||||||
// });
|
});
|
||||||
|
|
||||||
// if(overlap_with.length > 0) {
|
if(overlap_with.length > 0) {
|
||||||
// const conflicts = overlap_with.map((shift)=> ({
|
const conflicts = overlap_with.map((shift)=> ({
|
||||||
// start_time: formatHHmm(shift.start_time),
|
start_time: formatHHmm(shift.start_time),
|
||||||
// end_time: formatHHmm(shift.end_time),
|
end_time: formatHHmm(shift.end_time),
|
||||||
// type: shift.bank_code?.type ?? 'UNKNOWN',
|
type: shift.bank_code?.type ?? 'UNKNOWN',
|
||||||
// }));
|
}));
|
||||||
// throw new ConflictException({ error_code: 'SHIFT_OVERLAP', message: 'New shift overlaps with existing shift(s)', conflicts});
|
throw new ConflictException({ error_code: 'SHIFT_OVERLAP', message: 'New shift overlaps with existing shift(s)', conflicts});
|
||||||
// }
|
}
|
||||||
// };
|
};
|
||||||
let action: UpsertAction;
|
let action: UpsertAction;
|
||||||
//_____________________________________________________________________________________________
|
//_____________________________________________________________________________________________
|
||||||
// DELETE
|
// DELETE
|
||||||
|
|
@ -148,7 +148,7 @@ export class ShiftsCommandService extends BaseApprovalService<Shifts> {
|
||||||
//_____________________________________________________________________________________________
|
//_____________________________________________________________________________________________
|
||||||
else if (!old_shift && new_shift) {
|
else if (!old_shift && new_shift) {
|
||||||
if (new_bank_code_id === undefined) throw new NotFoundException(`bank code not found for new_shift.type: ${new_norm_shift?.type ?? ''}`);
|
if (new_bank_code_id === undefined) throw new NotFoundException(`bank code not found for new_shift.type: ${new_norm_shift?.type ?? ''}`);
|
||||||
// assertNoOverlap();
|
assertNoOverlap();
|
||||||
await tx.shifts.create({
|
await tx.shifts.create({
|
||||||
data: {
|
data: {
|
||||||
timesheet_id: timesheet.id,
|
timesheet_id: timesheet.id,
|
||||||
|
|
@ -170,7 +170,7 @@ export class ShiftsCommandService extends BaseApprovalService<Shifts> {
|
||||||
if (new_bank_code_id === undefined) throw new NotFoundException(`bank code not found for new_shift.type: ${new_norm_shift?.type ?? ''}`);
|
if (new_bank_code_id === undefined) throw new NotFoundException(`bank code not found for new_shift.type: ${new_norm_shift?.type ?? ''}`);
|
||||||
const existing = await findExactOldShift();
|
const existing = await findExactOldShift();
|
||||||
if(!existing) throw new NotFoundException({ error_code: 'SHIFT_STALE', message: 'The shift was modified or deleted by someone else'});
|
if(!existing) throw new NotFoundException({ error_code: 'SHIFT_STALE', message: 'The shift was modified or deleted by someone else'});
|
||||||
// assertNoOverlap(existing.id);
|
assertNoOverlap(existing.id);
|
||||||
|
|
||||||
await tx.shifts.update({
|
await tx.shifts.update({
|
||||||
where: {
|
where: {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { NotFoundException } from "@nestjs/common";
|
import { NotFoundException } from "@nestjs/common";
|
||||||
import { ShiftPayloadDto } from "../dtos/upsert-shift.dto";
|
import { ShiftPayloadDto } from "../dtos/upsert-shift.dto";
|
||||||
import { timeFromHHMMUTC } from "../helpers/shifts-date-time-helpers";
|
import { timeFromHHMM } from "../helpers/shifts-date-time-helpers";
|
||||||
|
|
||||||
export function overlaps(
|
export function overlaps(
|
||||||
a_start_ms: number,
|
a_start_ms: number,
|
||||||
|
|
@ -24,8 +24,8 @@ export function resolveBankCodeByType(type: string): Promise<number> {
|
||||||
|
|
||||||
export function normalizeShiftPayload(payload: ShiftPayloadDto) {
|
export function normalizeShiftPayload(payload: ShiftPayloadDto) {
|
||||||
//normalize shift's infos
|
//normalize shift's infos
|
||||||
const start_time = payload.start_time;
|
const start_time = timeFromHHMM(payload.start_time);
|
||||||
const end_time = payload.end_time;
|
const end_time = timeFromHHMM(payload.end_time );
|
||||||
const type = (payload.type || '').trim().toUpperCase();
|
const type = (payload.type || '').trim().toUpperCase();
|
||||||
const is_remote = payload.is_remote === true;
|
const is_remote = payload.is_remote === true;
|
||||||
const is_approved = payload.is_approved === false;
|
const is_approved = payload.is_approved === false;
|
||||||
|
|
@ -34,5 +34,5 @@ export function resolveBankCodeByType(type: string): Promise<number> {
|
||||||
const trimmed = typeof raw_comment === 'string' ? raw_comment.trim() : null;
|
const trimmed = typeof raw_comment === 'string' ? raw_comment.trim() : null;
|
||||||
const comment = trimmed && trimmed.length > 0 ? trimmed: null;
|
const comment = trimmed && trimmed.length > 0 ? trimmed: null;
|
||||||
|
|
||||||
return { start_time, end_time, type, is_remote, comment, is_approved };
|
return { start_time, end_time, type, is_remote, is_approved, comment };
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user