Files
Backend-Api/ProgramManager/src/Application/GozareshgirProgramManager.Application/Modules/Checkouts/Commands/CreateCheckout/CreateOrEditCheckoutCommandHandler.cs
2026-01-14 14:39:51 +03:30

280 lines
12 KiB
C#

using GozareshgirProgramManager.Application._Common.Interfaces;
using GozareshgirProgramManager.Application._Common.Models;
using GozareshgirProgramManager.Application.Modules.Checkouts.Queries.GetUserToGropCreate;
using GozareshgirProgramManager.Domain._Common;
using GozareshgirProgramManager.Domain.CheckoutAgg.Entities;
using GozareshgirProgramManager.Domain.CheckoutAgg.Enums;
using GozareshgirProgramManager.Domain.CheckoutAgg.Repositories;
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.DTOs;
using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Enums;
using GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Repositories;
using GozareshgirProgramManager.Domain.UserAgg.Entities;
using MediatR;
using PersianTools.Core;
using System.Runtime.InteropServices;
using Microsoft.EntityFrameworkCore;
using Shared.Contracts.Holidays;
namespace GozareshgirProgramManager.Application.Modules.Checkouts.Commands.CreateCheckout;
public class CreateOrEditCheckoutCommandHandler : IBaseCommandHandler<CreateOrEditCheckoutCommand>
{
private readonly ICheckoutRepository _checkoutRepository;
private readonly ISalaryPaymentSettingRepository _salaryPaymentSettingRepository;
private readonly ITaskSectionActivityRepository _taskSectionActivityRepository;
private readonly IUnitOfWork _unitOfWork;
private readonly IHolidayQueryService _holidayQueryService;
public CreateOrEditCheckoutCommandHandler(ICheckoutRepository checkoutRepository, IUnitOfWork unitOfWork,
ISalaryPaymentSettingRepository salaryPaymentSettingRepository,
ITaskSectionActivityRepository taskSectionActivityRepository, IHolidayQueryService holidayQueryService)
{
_checkoutRepository = checkoutRepository;
_unitOfWork = unitOfWork;
_salaryPaymentSettingRepository = salaryPaymentSettingRepository;
_taskSectionActivityRepository = taskSectionActivityRepository;
_holidayQueryService = holidayQueryService;
}
public async Task<OperationResult> Handle(CreateOrEditCheckoutCommand request, CancellationToken cancellationToken)
{
switch (request.TypeOfCheckoutHandler)
{
case TypeOfCheckoutHandler.CreateInGroup:
return await Create(request.Year, request.Month, request.UserIdList);
break;
case TypeOfCheckoutHandler.SingleEdit:
case TypeOfCheckoutHandler.GroupEditing:
return await GroupOrSingleEditing(request.CheckoutIdList);
break;
}
return OperationResult.Failure("نوع متد انتخاب نشده است");
}
/// <summary>
/// ایجاد گروهی فیش حقوقی
/// </summary>
/// <param name="Year"></param>
/// <param name="Month"></param>
/// <param name="UserIdList"></param>
/// <returns></returns>
public async Task<OperationResult> Create(string? Year, string? Month, List<long>? UserIdList)
{
if (string.IsNullOrWhiteSpace(Month))
return OperationResult.Failure("ماه خالی است");
if (string.IsNullOrWhiteSpace(Year))
return OperationResult.Failure("سال خالی است");
if (UserIdList == null)
return OperationResult.Failure("هیچ موردی برای ایجاد انتخاب نشده اشت");
if (UserIdList.Count == 0)
return OperationResult.Failure("هیچ موردی برای ایجاد انتخاب نشده اشت");
var startDateGr = new DateTime();
var EndDateGr = new DateTime();
var persianStart = new PersianDateTime();
int year = 0;
int month = 0;
try
{
year = Convert.ToInt32(Year);
month = Convert.ToInt32(Month);
persianStart = new PersianDateTime(year, month, 1);
var startDateFa = $"{persianStart}";
startDateGr = startDateFa.ToGeorgianDateTime();
var endDateFa = startDateFa.FindeEndOfMonth();
EndDateGr = endDateFa.ToGeorgianDateTime();
}
catch (Exception)
{
return OperationResult<GetUserToGroupCreatingResponse>.Failure(
"خطا در ورود سال و ماه");
}
var totalDays = Convert.ToInt32((EndDateGr - startDateGr).TotalDays + 1);
var getAllSettings = await _salaryPaymentSettingRepository.GetAllSettings(UserIdList);
var get = await _taskSectionActivityRepository.GetTotalTimeSpentPerUserInRangeAsync(startDateGr, EndDateGr);
foreach (var user in getAllSettings)
{
var totalWorked = get.FirstOrDefault(x => x.UserId == user.UserId);
var totalTimeTotalMinutes = (int)totalWorked.TotalTime.TotalMinutes;
var res = await ComputeSalary(user.WorkingHoursListDto, totalTimeTotalMinutes, user.MonthlySalary, startDateGr, EndDateGr, user.HolidayWorking);
var createCheckout = new Checkout(startDateGr, EndDateGr, year, month, user.FullName, user.UserId,
res.MandatoryHours, totalTimeTotalMinutes,
totalDays, res.RemainingHours, user.MonthlySalary, res.MonthlySalaryPay, res.DeductionFromSalary);
await _checkoutRepository.CreateAsync(createCheckout);
}
await _unitOfWork.SaveChangesAsync();
return OperationResult.Success();
}
/// <summary>
/// متد ویراش گروهی و تکی
/// </summary>
/// <param name="CheckoutIdList"></param>
/// <param name="CheckoutId"></param>
/// <param name="TypeOfCheckoutHandler"></param>
/// <returns></returns>
public async Task<OperationResult> GroupOrSingleEditing(List<Guid>? CheckoutIdList)
{
if (CheckoutIdList == null)
return OperationResult.Failure("هیچ موردی برای ویرایش انتخاب نشده اشت");
if (CheckoutIdList.Count == 0)
return OperationResult.Failure("هیچ موردی برای ویرایش انتخاب نشده اشت");
var checkouts = await _checkoutRepository.GetCheckoutListByIds(CheckoutIdList);
if (!checkouts.Any())
return OperationResult.Failure("هیچ موردی برای ویرایش انتخاب نشده اشت");
var UserIdList = checkouts.Select(x => x.UserId).ToList();
var getAllSettings = await _salaryPaymentSettingRepository.GetAllSettings(UserIdList);
if (!getAllSettings.Any())
return OperationResult.Failure("تنظیمات ساعت و حقوق یافت نشد");
foreach (var checkoutId in CheckoutIdList)
{
var checkout = checkouts.FirstOrDefault(x => x.Id == checkoutId);
if (checkout == null)
return OperationResult.Failure("فیش مورد نظر یافت نشد");
var userSetting = getAllSettings.FirstOrDefault(x => x.UserId == checkout.UserId);
var get = await _taskSectionActivityRepository.GetTotalTimeSpentByUserInRangeAsync(checkout.UserId, checkout.CheckoutStartDate, checkout.CheckoutEndDate);
var totalTimeTotalMinutes = (int)get.TotalMinutes;
var totalDays = Convert.ToInt32((checkout.CheckoutEndDate - checkout.CheckoutStartDate).TotalDays + 1);
var res = await ComputeSalary(userSetting.WorkingHoursListDto, totalTimeTotalMinutes, userSetting.MonthlySalary, checkout.CheckoutStartDate, checkout.CheckoutEndDate, userSetting.HolidayWorking);
checkout.Edit(res.MandatoryHours, totalTimeTotalMinutes, totalDays, res.RemainingHours, userSetting.MonthlySalary, res.MonthlySalaryPay, res.DeductionFromSalary);
await _unitOfWork.SaveChangesAsync();
}
return OperationResult.Success();
}
/// <summary>
/// محاسبه حقوق
/// </summary>
/// <returns></returns>
public async Task<ComputeResultDto> ComputeSalary(List<WorkingHoursListDto> workingHoursListDto, int totalHoursWorked, double monthlySalaryDefined, DateTime start, DateTime end, bool holidayWorking)
{
var startDate = start.ToFarsi();
var startYear = Convert.ToInt32(startDate.Substring(0, 4));
var startMonth = Convert.ToInt32(startDate.Substring(5, 2));
var startDay = Convert.ToInt32(startDate.Substring(8, 2));
var persianStart = new PersianDateTime(startYear, startMonth, startDay);
var endDate = end.ToFarsi();
var endYear = Convert.ToInt32(endDate.Substring(0, 4));
var endMonth = Convert.ToInt32(endDate.Substring(5, 2));
var endDay = Convert.ToInt32(endDate.Substring(8, 2));
var persianEnd = new PersianDateTime(endYear, endMonth, endDay);
var holidays = await _holidayQueryService.GetHolidaysInDates(start, end);
int mandatoryHours = 0;
for (var currentDay = persianStart; currentDay <= persianEnd; currentDay = currentDay.AddDays(1))
{
var currentDayOfWeek = new DNTPersianUtils.Core.PersianDateTime(currentDay.Year, currentDay.Month, currentDay.Day);
var holidayDate = currentDay.ShamsiDate.ToGeorgianDateTime();
var day = (PersianDayOfWeek)currentDayOfWeek.WeekDayNumber!;
var getDaySetting = workingHoursListDto.FirstOrDefault(x => x.PersianDayOfWeek == day);
if (getDaySetting != null)
{
if (!holidayWorking && holidays.Any(x => x.Holidaydate == holidayDate))
{
}
else
{
mandatoryHours += (int)getDaySetting.ShiftDuration.TotalMinutes;
Console.WriteLine((int)getDaySetting.ShiftDuration.TotalMinutes + " " + currentDay + " - " + day);
}
}
}
////حقوق نهایی
//var monthlySalaryPay = (totalHoursWorked * monthlySalaryDefined) / mandatoryHours;
//// اگر اضافه کار داشت حقوق تعین شده به عنوان حقوق نهایی در نظر گرفته میشود
//monthlySalaryPay = monthlySalaryPay > monthlySalaryDefined ? monthlySalaryDefined : monthlySalaryPay;
////حقوق کسر شده
//var deductionFromSalary = monthlySalaryDefined - monthlySalaryPay;
//new chang salary compute
var monthlySalaryPay = totalHoursWorked * monthlySalaryDefined;
//زمان باقی مانده
var remainingTime = totalHoursWorked - mandatoryHours;
//تناسب به دقیقه
#region MyRegion
//var monthlySalaryDefinedTest = monthlySalaryDefined * mandatoryHours;
//var monthlySalaryPayTest = totalHoursWorked * monthlySalaryDefined;
////// اگر اضافه کار داشت حقوق تعین شده به عنوان حقوق نهایی در نظر گرفته میشود
//monthlySalaryPayTest = monthlySalaryPayTest > monthlySalaryDefinedTest ? monthlySalaryDefinedTest : monthlySalaryPayTest;
//////حقوق کسر شده
//var deductionFromSalaryTest = monthlySalaryDefinedTest - monthlySalaryPayTest;
#endregion
var computeResult = new ComputeResultDto
{
MandatoryHours = mandatoryHours,
MonthlySalaryPay = monthlySalaryPay,
DeductionFromSalary = 0 /*deductionFromSalary*/,
RemainingHours = remainingTime
};
Console.WriteLine(mandatoryHours);
return computeResult;
}
}
public record CreateOrEditCheckoutCommand(TypeOfCheckoutHandler TypeOfCheckoutHandler, string? Year, string? Month, List<long>? UserIdList, List<Guid>? CheckoutIdList) : IBaseCommand;
public record ComputeResultDto
{
/// <summary>
/// ساعات باقی مانده
/// کسر کار یا اضافه کار
/// </summary>
public int RemainingHours { get; set; }
/// <summary>
/// حقوق نهایی که به پرسنل داده می شود
/// </summary>
public double MonthlySalaryPay { get; set; }
/// <summary>
/// کسر از حقوق
/// </summary>
public double DeductionFromSalary { get; set; }
/// <summary>
/// ساعت موظفی
/// </summary>
public int MandatoryHours { get; set; }
}