/** * BranchSchedule Service * Servicio para gestión de horarios de sucursales * * @module Branches */ import { Repository, FindOptionsWhere } from 'typeorm'; import { AppDataSource } from '../../../shared/database/typeorm.config'; import { BranchSchedule, ScheduleType } from '../entities/branch-schedule.entity'; import { ServiceContext } from './branch.service'; export interface CreateBranchScheduleDto { branchId: string; name: string; description?: string; scheduleType?: ScheduleType; dayOfWeek?: number; specificDate?: Date; openTime: string; closeTime: string; shifts?: Array<{ name: string; start: string; end: string }>; isActive?: boolean; } export interface UpdateBranchScheduleDto { name?: string; description?: string; scheduleType?: ScheduleType; dayOfWeek?: number; specificDate?: Date; openTime?: string; closeTime?: string; shifts?: Array<{ name: string; start: string; end: string }>; isActive?: boolean; } export interface BranchScheduleFilters { branchId?: string; scheduleType?: ScheduleType; dayOfWeek?: number; isActive?: boolean; } export class BranchScheduleService { private repository: Repository; constructor() { this.repository = AppDataSource.getRepository(BranchSchedule); } async findAll(_ctx: ServiceContext, filters?: BranchScheduleFilters): Promise { const where: FindOptionsWhere = {}; if (filters?.branchId) { where.branchId = filters.branchId; } if (filters?.scheduleType) { where.scheduleType = filters.scheduleType; } if (filters?.dayOfWeek !== undefined) { where.dayOfWeek = filters.dayOfWeek; } if (filters?.isActive !== undefined) { where.isActive = filters.isActive; } return this.repository.find({ where, relations: ['branch'], order: { dayOfWeek: 'ASC', openTime: 'ASC' }, }); } async findById(_ctx: ServiceContext, id: string): Promise { return this.repository.findOne({ where: { id }, relations: ['branch'], }); } async findByBranch(_ctx: ServiceContext, branchId: string): Promise { return this.repository.find({ where: { branchId, isActive: true }, order: { dayOfWeek: 'ASC', openTime: 'ASC' }, }); } async findRegularSchedule(_ctx: ServiceContext, branchId: string): Promise { return this.repository.find({ where: { branchId, scheduleType: 'regular', isActive: true }, order: { dayOfWeek: 'ASC' }, }); } async findHolidaySchedule(_ctx: ServiceContext, branchId: string): Promise { return this.repository.find({ where: { branchId, scheduleType: 'holiday', isActive: true }, order: { specificDate: 'ASC' }, }); } async findScheduleForDate( _ctx: ServiceContext, branchId: string, date: Date ): Promise { // First check for specific date (holiday or special) const specificSchedule = await this.repository.findOne({ where: { branchId, specificDate: date, isActive: true, }, }); if (specificSchedule) { return specificSchedule; } // Fall back to regular schedule for day of week const dayOfWeek = date.getDay(); return this.repository.findOne({ where: { branchId, scheduleType: 'regular', dayOfWeek, isActive: true, }, }); } async create(_ctx: ServiceContext, data: CreateBranchScheduleDto): Promise { const schedule = this.repository.create(data); return this.repository.save(schedule); } async update( ctx: ServiceContext, id: string, data: UpdateBranchScheduleDto ): Promise { const schedule = await this.findById(ctx, id); if (!schedule) { return null; } Object.assign(schedule, data); return this.repository.save(schedule); } async delete(_ctx: ServiceContext, id: string): Promise { const result = await this.repository.delete({ id }); return result.affected ? result.affected > 0 : false; } async createWeeklySchedule( _ctx: ServiceContext, branchId: string, weeklyHours: Array<{ dayOfWeek: number; openTime: string; closeTime: string; shifts?: Array<{ name: string; start: string; end: string }>; }> ): Promise { // Delete existing regular schedules for this branch await this.repository.delete({ branchId, scheduleType: 'regular', }); // Create new schedules const schedules = weeklyHours.map(hours => this.repository.create({ branchId, name: `Regular - Day ${hours.dayOfWeek}`, scheduleType: 'regular', dayOfWeek: hours.dayOfWeek, openTime: hours.openTime, closeTime: hours.closeTime, shifts: hours.shifts || [], isActive: true, }) ); return this.repository.save(schedules); } async isBranchOpenAt( ctx: ServiceContext, branchId: string, dateTime: Date ): Promise { const schedule = await this.findScheduleForDate(ctx, branchId, dateTime); if (!schedule) { return false; } const timeStr = dateTime.toTimeString().slice(0, 5); // HH:MM format return timeStr >= schedule.openTime && timeStr <= schedule.closeTime; } }