All files / src/domains/hr/leave/leave-type leave-type.service.ts

0% Statements 0/37
0% Branches 0/16
0% Functions 0/9
0% Lines 0/33

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106                                                                                                                                                                                                                   
import {
  Injectable,
  NotFoundException,
  ConflictException,
} from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { LeaveType } from '../schemas';
import { CreateLeaveTypeDto, UpdateLeaveTypeDto } from './dto/leave-type.dto';
 
@Injectable()
export class LeaveTypeService {
  constructor(
    @InjectModel(LeaveType.name) private leaveTypeModel: Model<LeaveType>,
  ) {}
 
  async create(tenantId: string, dto: CreateLeaveTypeDto, userId: string) {
    const exists = await this.leaveTypeModel
      .findOne({ tenantId, leaveTypeCode: dto.leaveTypeCode })
      .exec();
    if (exists)
      throw new ConflictException(
        `Leave type code '${dto.leaveTypeCode}' already exists`,
      );
 
    return this.leaveTypeModel.create({ ...dto, tenantId, createdBy: userId });
  }
 
  async findAll(tenantId: string, status?: string) {
    const filter: any = { tenantId, deleted: false };
    if (status) filter.status = status;
    return this.leaveTypeModel.find(filter).sort({ leaveTypeName: 1 }).exec();
  }
 
  async findOne(tenantId: string, id: string) {
    const doc = await this.leaveTypeModel
      .findOne({ _id: id, tenantId, deleted: false })
      .exec();
    if (!doc) throw new NotFoundException('Leave type not found');
    return doc;
  }
 
  async update(
    tenantId: string,
    id: string,
    dto: UpdateLeaveTypeDto,
    userId: string,
  ) {
    const doc = await this.findOne(tenantId, id);
 
    // Check code uniqueness if changed
    if (dto.leaveTypeCode && dto.leaveTypeCode !== doc.leaveTypeCode) {
      const exists = await this.leaveTypeModel
        .findOne({
          tenantId,
          leaveTypeCode: dto.leaveTypeCode,
          _id: { $ne: id },
        })
        .exec();
      if (exists)
        throw new ConflictException(
          `Leave type code '${dto.leaveTypeCode}' already exists`,
        );
    }
 
    Object.assign(doc, dto, { updatedBy: userId });
    return doc.save();
  }
 
  async activate(tenantId: string, id: string) {
    return this.leaveTypeModel.findOneAndUpdate(
      { _id: id, tenantId },
      { $set: { status: 'active' } },
      { new: true },
    );
  }
 
  async deactivate(tenantId: string, id: string) {
    return this.leaveTypeModel.findOneAndUpdate(
      { _id: id, tenantId },
      { $set: { status: 'inactive' } },
      { new: true },
    );
  }
 
  async clone(tenantId: string, id: string, userId: string) {
    const source = await this.findOne(tenantId, id);
    const { _id, ...cloneData } = source.toObject() as any;
    cloneData.leaveTypeCode = `${cloneData.leaveTypeCode}_COPY`;
    cloneData.leaveTypeName = `${cloneData.leaveTypeName} (Copy)`;
    cloneData.status = 'inactive';
    cloneData.createdBy = userId;
    return this.leaveTypeModel.create(cloneData);
  }
 
  async softDelete(tenantId: string, id: string) {
    // Check if used in any leave request
    // If used, only soft-delete
    return this.leaveTypeModel.findOneAndUpdate(
      { _id: id, tenantId },
      { $set: { deleted: true, deletedAt: new Date(), status: 'inactive' } },
      { new: true },
    );
  }
}