All files / src/domains/hr/leave/payroll payroll.service.ts

0% Statements 0/29
0% Branches 0/18
0% Functions 0/5
0% Lines 0/26

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                                                                                                                                                                                           
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import {
  LeavePayrollSummary,
  LeavePayrollExport,
  LeaveRequest,
} from '../schemas';
 
@Injectable()
export class PayrollReadinessService {
  constructor(
    @InjectModel(LeavePayrollSummary.name)
    private summaryModel: Model<LeavePayrollSummary>,
    @InjectModel(LeavePayrollExport.name)
    private exportModel: Model<LeavePayrollExport>,
    @InjectModel(LeaveRequest.name) private requestModel: Model<LeaveRequest>,
  ) {}
 
  async generateSummary(
    tenantId: string,
    employeeId: string,
    payrollPeriod: string,
  ) {
    // Collect all approved requests in the period
    const approvedRequests = await this.requestModel
      .find({
        tenantId,
        employeeId,
        status: 'approved',
        startDate: { $lte: `${payrollPeriod}-31` },
        endDate: { $gte: `${payrollPeriod}-01` },
      })
      .exec();
 
    let paidLeaveDays = 0;
    let unpaidLeaveDays = 0;
    let paidLeaveHours = 0;
    let unpaidLeaveHours = 0;
 
    for (const req of approvedRequests) {
      if (req.unit === 'Full Day' || req.unit === 'Half Day') {
        paidLeaveDays += req.paidQuantity;
        unpaidLeaveDays += req.unpaidQuantity;
      } else {
        paidLeaveHours += req.paidQuantity;
        unpaidLeaveHours += req.unpaidQuantity;
      }
    }
 
    return this.summaryModel.findOneAndUpdate(
      { tenantId, employeeId, payrollPeriod },
      {
        $set: {
          paidLeaveDays,
          unpaidLeaveDays,
          lopDays: unpaidLeaveDays,
          paidLeaveHours,
          unpaidLeaveHours,
          generatedAt: new Date(),
        },
      },
      { upsert: true, new: true },
    );
  }
 
  async getPayrollSummary(
    tenantId: string,
    employeeId: string,
    payrollPeriod: string,
  ) {
    return this.summaryModel
      .findOne({ tenantId, employeeId, payrollPeriod })
      .exec();
  }
 
  async runExport(tenantId: string, payrollPeriod: string, userId: string) {
    const job = await this.exportModel.create({
      tenantId,
      payrollPeriod,
      status: 'completed',
      exportedBy: userId,
      completedAt: new Date(),
    });
    return job;
  }
 
  async getExport(tenantId: string, id: string) {
    const job = await this.exportModel.findOne({ _id: id, tenantId }).exec();
    if (!job) throw new NotFoundException('Payroll export job not found');
    return job;
  }
}