Compare commits

..

7 Commits

33 changed files with 1407 additions and 529 deletions

View File

@@ -1,6 +1,5 @@
using _0_Framework.Application;
using _0_Framework.Application.Sms;
using Company.Domain.ContarctingPartyAgg;
using Company.Domain.InstitutionContractAgg;
using Hangfire;
@@ -14,15 +13,13 @@ public class JobSchedulerRegistrator
private readonly IInstitutionContractRepository _institutionContractRepository;
private static DateTime? _lastRunCreateTransaction;
private static DateTime? _lastRunSendMonthlySms;
private readonly ISmsService _smsService;
public JobSchedulerRegistrator(SmsReminder smsReminder, IBackgroundJobClient backgroundJobClient, IInstitutionContractRepository institutionContractRepository, ISmsService smsService)
public JobSchedulerRegistrator(SmsReminder smsReminder, IBackgroundJobClient backgroundJobClient, IInstitutionContractRepository institutionContractRepository)
{
_smsReminder = smsReminder;
_backgroundJobClient = backgroundJobClient;
_institutionContractRepository = institutionContractRepository;
_smsService = smsService;
}
public void Register()
@@ -94,8 +91,8 @@ public class JobSchedulerRegistrator
}
catch (Exception e)
{
await _smsService.Alarm("09114221321", "خطا-ایجاد سند مالی");
//_smsService.Alarm("09114221321", "خطا-ایجاد سند مالی");
}
}

View File

@@ -1,10 +0,0 @@
using GozareshgirProgramManager.Application.Interfaces;
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
public class NullBoardNotificationPublisher:IBoardNotificationPublisher
{
public Task SendProjectStatusChanged(long userId, TaskSectionStatus oldStatus, TaskSectionStatus newStatus, Guid sectionId)
{
throw new NotImplementedException();
}
}

View File

@@ -8,7 +8,6 @@ using BackgroundInstitutionContract.Task.Jobs;
using CompanyManagment.App.Contracts.Hubs;
using CompanyManagment.EFCore.Services;
using GozareshgirProgramManager.Application._Bootstrapper;
using GozareshgirProgramManager.Application.Interfaces;
using GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser;
using GozareshgirProgramManager.Infrastructure;
using GozareshgirProgramManager.Infrastructure.Persistence.Seed;
@@ -32,7 +31,7 @@ builder.Services.AddTransient<ISmsService, SmsService>();
builder.Services.AddTransient<IUidService, UidService>();
builder.Services.AddTransient<IFileUploader, FileUploader>();
builder.Services.Configure<AppSettingConfiguration>(builder.Configuration);
builder.Services.AddScoped<IBoardNotificationPublisher, NullBoardNotificationPublisher>();
#region MongoDb
var mongoConnectionSection = builder.Configuration.GetSection("MongoDb");

View File

@@ -1,9 +1,7 @@
using _0_Framework.Application;
using _0_Framework.Domain;
using _0_Framework.Domain;
using CompanyManagment.App.Contracts.InstitutionPlan;
using CompanyManagment.App.Contracts.TemporaryClientRegistration;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Company.Domain.InstitutionPlanAgg;
@@ -28,18 +26,4 @@ public interface IPlanPercentageRepository : IRepository<long, PlanPercentage>
/// <param name="command"></param>
/// <returns></returns>
InstitutionPlanViewModel GetInstitutionPlanForWorkshop(WorkshopTempViewModel command);
/// <summary>
/// دریافت دیتای مودال ایجاد
/// </summary>
/// <returns></returns>
Task<CreateServiceAmountDto> GetCreateModalData();
/// <summary>
/// دریافت لیست مبالغ سرویس ها
/// </summary>
/// <param name="searchModel"></param>
/// <returns></returns>
Task<PagedResult<InstitutionPlanListDto>> GetList(
InstitutionPlanSearchModel searchModel);
}

View File

@@ -0,0 +1,154 @@
using System.Drawing;
using _0_Framework.Application;
using OfficeOpenXml;
using OfficeOpenXml.Style;
namespace CompanyManagement.Infrastructure.Excel.Checkout.AsghaeeAzarWorkshops;
public class AsghaeeAzarWorkshopsExcelGenerator
{
public static Dictionary<string, string> Header { get; set; } = new()
{
{ "FullName", "نام و نام خانوادگی" },
{ "NationalCode", "کد ملی" },
{ "FinalAmount", "مبلغ نهایی" }
};
public static byte[] Generate(List<AsghaeeAzarWorkshopsExcelViewModel> data)
{
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add("Sheet1");
// Add index column header
var indexCell = worksheet.Cells[1, 1];
indexCell.Value = "ردیف";
ApplyHeaderStyle(indexCell);
// Add headers to worksheet
for (int i = 0; i < Header.Count; i++)
{
worksheet.Cells[1, i + 2].Value = Header.ElementAt(i).Value;
ApplyHeaderStyle(worksheet.Cells[1, i + 2]);
}
var dataRow = 2;
int finalAmountColumnIndex = -1;
foreach (var item in data)
{
var column = 2;
foreach (var header in Header)
{
var property = item.GetType().GetProperty(header.Key);
var value = property?.GetValue(item, null)?.ToString();
// Check if the property requires MoneyToDouble()
if (header.Key == "FinalAmount")
{
worksheet.Cells[dataRow, column].Value = MoneyToDouble(value ?? "0");
finalAmountColumnIndex = column;
}
else
{
worksheet.Cells[dataRow, column].Value = value;
}
ApplyGeneralDataStyle(worksheet.Cells[dataRow, column]);
ApplySpecificStyle(worksheet.Cells[dataRow, column], header.Key);
column++;
}
// Add row number
var rowCounter = worksheet.Cells[dataRow, 1];
rowCounter.Value = dataRow - 1;
ApplyGeneralDataStyle(rowCounter);
ApplySpecificStyle(rowCounter, "RowNumber");
dataRow++;
}
worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();
worksheet.PrinterSettings.PaperSize = ePaperSize.A4;
worksheet.PrinterSettings.Orientation = eOrientation.Portrait;
worksheet.PrinterSettings.FitToPage = true;
worksheet.PrinterSettings.FitToWidth = 1;
worksheet.PrinterSettings.FitToHeight = 0;
worksheet.PrinterSettings.Scale = 85;
worksheet.View.RightToLeft = true;
if (finalAmountColumnIndex != -1)
{
ApplyConditionalFormatting(worksheet, dataRow, finalAmountColumnIndex);
}
return package.GetAsByteArray();
}
private static double MoneyToDouble(string value)
{
if (string.IsNullOrEmpty(value))
return 0;
var min = value.Length > 1 ? value.Substring(0, 2) : "";
var result = min == "\u200e\u2212" ? value.MoneyToDouble() * -1 : value.MoneyToDouble();
return result;
}
private static void ApplyHeaderStyle(ExcelRange cell)
{
cell.Style.Font.Bold = true;
cell.Style.Fill.PatternType = ExcelFillStyle.Solid;
cell.Style.Fill.BackgroundColor.SetColor(Color.LightGray);
cell.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
cell.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
cell.Style.Border.BorderAround(ExcelBorderStyle.Thin);
}
private static void ApplyGeneralDataStyle(ExcelRange cell)
{
cell.Style.Border.BorderAround(ExcelBorderStyle.Thin);
cell.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
cell.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
cell.Style.Fill.PatternType = ExcelFillStyle.Solid;
}
private static void ApplySpecificStyle(ExcelRange cell, string columnKey)
{
switch (columnKey)
{
case "RowNumber":
case "FullName":
case "NationalCode":
cell.Style.Fill.BackgroundColor.SetColor(Color.LightYellow);
break;
case "FinalAmount":
cell.Style.Fill.BackgroundColor.SetColor(ColorTranslator.FromHtml("#A8BAFE")); // Light blue
cell.Style.Numberformat.Format = "#,##0";
break;
}
}
private static void ApplyConditionalFormatting(ExcelWorksheet worksheet, int dataRow, int finalAmountColumnIndex)
{
for (int rowIndex = 2; rowIndex < dataRow; rowIndex++)
{
var finalAmountValue = worksheet.Cells[rowIndex, finalAmountColumnIndex].Value;
if (finalAmountValue != null && double.TryParse(finalAmountValue.ToString(), out double amount))
{
if (amount < 0)
{
var rowRange = worksheet.Cells[rowIndex, 1, rowIndex, worksheet.Dimension.End.Column];
rowRange.Style.Fill.PatternType = ExcelFillStyle.Solid;
rowRange.Style.Fill.BackgroundColor.SetColor(Color.Red);
foreach (var cell in rowRange)
{
cell.Style.Font.Color.SetColor(Color.White);
}
}
}
}
}
}

View File

@@ -0,0 +1,8 @@
namespace CompanyManagement.Infrastructure.Excel.Checkout.AsghaeeAzarWorkshops;
public class AsghaeeAzarWorkshopsExcelViewModel
{
public string FullName { get; set; }
public string NationalCode { get; set; }
public string FinalAmount { get; set; }
}

View File

@@ -76,7 +76,5 @@ public class InstitutionContractViewModel
public bool IsInstallment { get; set; }
public InstitutionContractVerificationStatus VerificationStatus { get; set; }
public InstitutionContractSigningType? SigningType { get; set; }
public List<InstitutionContractInstallmentViewModel> InstallmentList { get; set; }
}

View File

@@ -1,51 +0,0 @@
namespace CompanyManagment.App.Contracts.InstitutionPlan;
public class CreateServiceAmountDto
{
/// <summary>
/// آی دی
/// </summary>
public long Id { get; set; }
/// <summary>
/// قرارداد و تصفیه
/// درصد از مزد روزانه
/// string
/// </summary>
public string ContractAndCheckoutPercentStr { get; set; }
/// <summary>
/// بیمه
/// درصد از مزد روزانه
/// string
/// </summary>
public string InsurancePercentStr { get; set; }
/// <summary>
/// حضورغباب
/// درصد از مزد روزانه
/// string
/// </summary>
public string RollCallPercentStr { get; set; }
/// <summary>
/// فیش غیر رسمی
/// درصد از مزد روزانه
/// string
/// </summary>
public string CustomizeCheckoutPercentStr { get; set; }
/// <summary>
/// خدمات حضوری قرداد و تصفیه
/// درصد از مزد روزانه
/// string
/// </summary>
public string ContractAndCheckoutInPersonPercentStr { get; set; }
/// <summary>
/// خدمات حضوری بیمه
/// درصد از مزد روزانه
/// string
/// </summary>
public string InsuranceInPersonPercentStr { get; set; }
}

View File

@@ -1,7 +1,6 @@
using _0_Framework.Application;
using System.Collections.Generic;
using _0_Framework.Application;
using CompanyManagment.App.Contracts.TemporaryClientRegistration;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace CompanyManagment.App.Contracts.InstitutionPlan;
@@ -35,27 +34,4 @@ public interface IInstitutionPlanApplication
/// <param name="command"></param>
/// <returns></returns>
InstitutionPlanViewModel GetInstitutionPlanForWorkshop(WorkshopTempViewModel command);
/// <summary>
/// دریافت دیتای درصد سرویس برای مودال ایجاد
/// </summary>
/// <returns></returns>
Task<CreateServiceAmountDto> GetCreateModalData();
/// <summary>
/// ایجاد درصد سرویس
/// </summary>
/// <param name="command"></param>
/// <returns></returns>
Task<OperationResult> CreateInstitutionPlanPercentage(CreateServiceAmountDto command);
/// <summary>
/// دریافت لیست مبالغ سرویس ها
/// </summary>
/// <param name="searchModel"></param>
/// <returns></returns>
Task<PagedResult<InstitutionPlanListDto>> GetList(
InstitutionPlanSearchModel searchModel);
}

View File

@@ -1,84 +0,0 @@
namespace CompanyManagment.App.Contracts.InstitutionPlan;
public class InstitutionPlanListDto
{
/// <summary>
/// تعداد پرسنل
/// </summary>
public int CountPerson { get; set; }
/// <summary>
/// مبلغ قرارداد و تصفیه
/// </summary>
public string ContractAndCheckout { get; set; }
/// <summary>
/// مبلغ بیمه
/// </summary>
public string Insurance { get; set; }
/// <summary>
/// مبلغ حضورغباب
/// </summary>
public string RollCall { get; set; }
/// <summary>
/// مبلغ فیش غیر رسمی
/// </summary>
public string CustomizeCheckout { get; set; }
/// <summary>
/// مبلغ خدمات حضوری قرداد و تصفیه
/// </summary>
public string ContractAndCheckoutInPerson { get; set; }
/// <summary>
/// مبلغ خدمات حضوری بیمه
/// </summary>
public string InsuranceInPerson { get; set; }
#region Total
/// <summary>
/// مبلغ کل خدمات حضوری
/// </summary>
public string InPersonSumAmountStr { get; set; }
/// <summary>
/// مبلغ کل خدمات آنلاین
/// </summary>
public string OnlineOnlySumAmountStr { get; set; }
/// <summary>
/// مبلغ کل خدمات حضوری و آنلاین
/// </summary>
public string OnlineAndInPersonSumAmountStr { get; set; }
/// <summary>
/// مبلغ کل خدمات حضوری و آنلاین
/// double
/// </summary>
public double OnlineAndInPersonSumAmountDouble { get; set; }
/// <summary>
/// مبلغ کل خدمات حضوری
/// double
/// </summary>
public double InPersonSumAmountDouble { get; set; }
/// <summary>
/// مبلغ کل خدمات آنلاین
/// double
/// </summary>
public double OnlineOnlySumAmountDouble { get; set; }
#endregion
}

View File

@@ -1,11 +0,0 @@
using _0_Framework.Application;
namespace CompanyManagment.App.Contracts.InstitutionPlan;
public class InstitutionPlanSearchModel : PaginationRequest
{
/// <summary>
/// تعدلد پرسنل برای جستجو
/// </summary>
public int CountPeron { get; set; }
}

View File

@@ -1570,7 +1570,9 @@ public class InstitutionContractApplication : IInstitutionContractApplication
createdWorkshop.InstitutionContractWorkshopGroupId,createdWorkshop.WorkshopGroup,
createdWorkshop.WorkshopId!.Value, createdWorkshop.id);
institutionContract.WorkshopGroup.AddCurrentWorkshop(currentWorkshop);
}
if (institutionContract.WorkshopGroup.InitialWorkshops.All(x => x.WorkshopCreated && x.WorkshopId is > 0))

View File

@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using _0_Framework.Application;
using Company.Domain.InstitutionPlanAgg;
using CompanyManagment.App.Contracts.InstitutionPlan;
@@ -85,73 +84,4 @@ public class InstitutionPlanApplication : IInstitutionPlanApplication
{
return _planPercentageRepository.GetInstitutionPlanForWorkshop(command);
}
#region ForApi
public async Task<CreateServiceAmountDto> GetCreateModalData()
{
return await _planPercentageRepository.GetCreateModalData();
}
public async Task<OperationResult> CreateInstitutionPlanPercentage(CreateServiceAmountDto command)
{
var op = new OperationResult();
if (string.IsNullOrWhiteSpace(command.ContractAndCheckoutInPersonPercentStr) || command.ContractAndCheckoutInPersonPercentStr == "0" ||
string.IsNullOrWhiteSpace(command.ContractAndCheckoutPercentStr) || (command.ContractAndCheckoutPercentStr == "0" ||
string.IsNullOrWhiteSpace(command.CustomizeCheckoutPercentStr) || command.CustomizeCheckoutPercentStr == "0" ||
string.IsNullOrWhiteSpace(command.InsuranceInPersonPercentStr) || command.InsuranceInPersonPercentStr == "0" ||
string.IsNullOrWhiteSpace(command.InsurancePercentStr) || command.InsurancePercentStr == "0" ||
string.IsNullOrWhiteSpace(command.RollCallPercentStr) || command.RollCallPercentStr == "0"))
return op.Failed("هیچ یک از فیلدها نمیتوانند صفر باشند");
int contractAndCheckoutInPersonPercent = 0;
int contractAndCheckoutPercent = 0;
int customizeCheckoutPercent = 0;
int insuranceInPersonPercent = 0;
int insurancePercent = 0;
int rollCallPercent = 0;
try
{
contractAndCheckoutInPersonPercent = Convert.ToInt32(command.ContractAndCheckoutInPersonPercentStr);
contractAndCheckoutPercent = Convert.ToInt32(command.ContractAndCheckoutPercentStr);
customizeCheckoutPercent = Convert.ToInt32(command.CustomizeCheckoutPercentStr);
insuranceInPersonPercent = Convert.ToInt32(command.InsuranceInPersonPercentStr);
insurancePercent = Convert.ToInt32(command.InsurancePercentStr);
rollCallPercent = Convert.ToInt32(command.RollCallPercentStr);
}
catch (Exception e)
{
return op.Failed("لطفا عدد معتبر وارد کنید");
}
var firstPlan =await _planPercentageRepository.GetCreateModalData();
if (firstPlan != null)
{
var planPercentage = _planPercentageRepository.Get(firstPlan.Id);
planPercentage.Edit(contractAndCheckoutPercent, insurancePercent, rollCallPercent, customizeCheckoutPercent, contractAndCheckoutInPersonPercent, insuranceInPersonPercent);
_planPercentageRepository.SaveChanges();
}
else
{
var create = new PlanPercentage(contractAndCheckoutPercent, insurancePercent, rollCallPercent,
customizeCheckoutPercent, contractAndCheckoutInPersonPercent, insuranceInPersonPercent);
await _planPercentageRepository.CreateAsync(create);
await _planPercentageRepository.SaveChangesAsync();
}
return op.Succcedded();
}
public async Task<PagedResult<InstitutionPlanListDto>> GetList(InstitutionPlanSearchModel searchModel)
{
return await _planPercentageRepository.GetList(searchModel);
}
#endregion
}

View File

@@ -4364,7 +4364,6 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
{
var sendResult = await _smsService.SendInstitutionCreationVerificationLink(item.Number, item.FullName,
item.InstitutionId, item.ContractingPartyId, item.InstitutionContractId, typeOfSms);
Thread.Sleep(1000);
}
Console.WriteLine("executed at : " + persianNow + " - " + hour + ":" + minute);
@@ -4416,13 +4415,12 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
TypeOfContract = x.TypeOfContract,
IsInstallment = x.IsInstallment,
VerificationStatus = x.VerificationStatus,
SigningType = x.SigningType,
InstallmentList = x.Installments
.Select(ins => new InstitutionContractInstallmentViewModel
{ AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr })
.OrderBy(ins => ins.InstallmentDateGr).Skip(1).ToList(),
}).Where(x =>
x.ContractStartGr < endOfMonthGr && x.ContractEndGr >= endOfMonthGr && x.ContractAmountDouble > 0 && x.VerificationStatus != InstitutionContractVerificationStatus.PendingForVerify)
x.ContractStartGr < endOfMonthGr && x.ContractEndGr >= endOfMonthGr && x.ContractAmountDouble > 0)
.ToListAsync();
#endregion
@@ -4440,13 +4438,13 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
#region GetDectivedContractOnCurrentMonth
if (futureContracts.Any())
{
List<long> futureContractIds = futureContracts.Select(x => x.ContractingPartyId).ToList();
List<InstitutionContractViewModel> deatcivedContract = await _context.InstitutionContractSet
.Where(x => x.IsActiveString == "false" && futureContractIds.Contains(x.ContractingPartyId) &&
x.ContractEndGr.Date == endOfCurrentMonth.Date && x.ContractAmount > 0 && x.VerificationStatus != InstitutionContractVerificationStatus.PendingForVerify)
x.ContractEndGr.Date == endOfCurrentMonth.Date && x.ContractAmount > 0)
.Select(x => new InstitutionContractViewModel
{
Id = x.id,
@@ -4461,7 +4459,6 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
TypeOfContract = x.TypeOfContract,
IsInstallment = x.IsInstallment,
VerificationStatus = x.VerificationStatus,
SigningType = x.SigningType,
InstallmentList = x.Installments
.Select(ins => new InstitutionContractInstallmentViewModel
{ AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr })
@@ -4472,12 +4469,6 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
institutionContracts.AddRange(deatcivedContract);
}
// قرارداد هایی که پطور یکجا پرداخت شده اند
var paidInFull = institutionContracts.Where(x =>
x.SigningType != InstitutionContractSigningType.Legacy && x.IsInstallment == false && x.SigningType != null).ToList();
//حذف قراداد هایی که یکجا پرداخت شده اند از لیست ایجاد سند ماهانه
institutionContracts = institutionContracts.Except(paidInFull).ToList();
#region RollCallServicCompute
@@ -4525,7 +4516,8 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
if (!alreadyCreated)
{
if (item.IsInstallment)
if (item.IsInstallment &&
item.VerificationStatus == InstitutionContractVerificationStatus.Verified)
{
var instalment = item.InstallmentList
.FirstOrDefault(x =>
@@ -4559,7 +4551,8 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
await _financialStatmentRepository.SaveChangesAsync();
if (item.IsInstallment)
if (item.IsInstallment &&
item.VerificationStatus == InstitutionContractVerificationStatus.Verified)
{
var instalment = item.InstallmentList
.FirstOrDefault(x =>
@@ -4586,17 +4579,12 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
#region RollCallServicCompute
//ایجاد سند مالی حضورغیاب
//قرارداد هایی که جدید نیستند و اقساط ندارند
//کارگاه های استثناء : کباب مهدی 30520 و نمونه پروتئین 30739
if (item.SigningType != InstitutionContractSigningType.OtpBased && item.SigningType != InstitutionContractSigningType.Physical
&& !item.IsInstallment && item.ContractingPartyId != 30520 && item.ContractingPartyId != 30739)
if (item.VerificationStatus != InstitutionContractVerificationStatus.Verified &&
!item.IsInstallment && item.ContractingPartyId != 30520 && item.ContractingPartyId != 30739)
{
try
{
//TODO
//@refactor Need
var employers = await _context.Employers
.Where(x => x.ContractingPartyId == item.ContractingPartyId)
.Select(x => x.id).ToListAsync();

View File

@@ -1,14 +1,12 @@
using _0_Framework.Application;
using System;
using System.Collections.Generic;
using System.Linq;
using _0_Framework.Application;
using _0_Framework.InfraStructure;
using Company.Domain.InstitutionPlanAgg;
using CompanyManagment.App.Contracts.InstitutionContract;
using CompanyManagment.App.Contracts.InstitutionPlan;
using CompanyManagment.App.Contracts.TemporaryClientRegistration;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CompanyManagment.EFCore.Repository;
@@ -46,7 +44,6 @@ public class PlanPercentageRepository : RepositoryBase<long, PlanPercentage>, IP
}).FirstOrDefault();
}
public List<InstitutionPlanViewModel> GetInstitutionPlanList(int pageIndex, int countPeron)
{
var planPercentage = _context.PlanPercentages.FirstOrDefault();
@@ -306,112 +303,4 @@ public class PlanPercentageRepository : RepositoryBase<long, PlanPercentage>, IP
return new InstitutionPlanViewModel();
}
#region ForApi
public async Task<CreateServiceAmountDto> GetCreateModalData()
{
return await _context.PlanPercentages.Select(x => new CreateServiceAmountDto()
{
Id = x.id,
ContractAndCheckoutInPersonPercentStr = $"{x.ContractAndCheckoutInPersonPercent}",
CustomizeCheckoutPercentStr = $"{x.CustomizeCheckoutPercent}",
ContractAndCheckoutPercentStr = $"{x.ContractAndCheckoutPercent}",
InsuranceInPersonPercentStr = $"{x.InsuranceInPersonPercent}",
InsurancePercentStr = $"{x.InsurancePercent}",
RollCallPercentStr = $"{x.RollCallPercent}",
}).FirstOrDefaultAsync();
}
public async Task<PagedResult<InstitutionPlanListDto>> GetList(
InstitutionPlanSearchModel searchModel)
{
var planPercentage = await _context.PlanPercentages.FirstOrDefaultAsync();
if (planPercentage == null)
return new PagedResult<InstitutionPlanListDto>();
var dailyWageYearlySalery = await _context.YearlySalaries.Include(i => i.YearlySalaryItemsList).FirstOrDefaultAsync(x =>
x.StartDate.Date <= DateTime.Now.Date && x.EndDate >= DateTime.Now.Date);
if (dailyWageYearlySalery == null)
return new PagedResult<InstitutionPlanListDto>();
var dailyWage = dailyWageYearlySalery.YearlySalaryItemsList.Where(x => x.ItemName == "مزد روزانه")
.Select(x => x.ItemValue).FirstOrDefault();
var plans = _context.InstitutionPlans.AsQueryable();
if (searchModel.CountPeron > 0)
plans = plans.Where(x => x.CountPerson == searchModel.CountPeron);
var count = await plans.CountAsync();
var planQueryFilter =await plans.ApplyPagination(searchModel.PageIndex, searchModel.PageSize).ToListAsync();
var planResult = planQueryFilter.Select(plan =>
new InstitutionPlanViewModel
{
CountPerson = plan.CountPerson,
ContractAndCheckoutDouble =
((dailyWage * planPercentage.ContractAndCheckoutPercent / 100) * plan.CountPerson *
plan.IncreasePercentage),
InsuranceDouble = (((dailyWage * planPercentage.InsurancePercent) / 100) * plan.CountPerson *
plan.IncreasePercentage),
RollCallDouble = (((dailyWage * planPercentage.RollCallPercent) / 100) * plan.CountPerson *
plan.IncreasePercentage),
CustomizeCheckoutDouble = (((dailyWage * planPercentage.CustomizeCheckoutPercent) / 100) *
plan.CountPerson *
plan.IncreasePercentage),
ContractAndCheckoutInPersonDouble =
(((dailyWage * planPercentage.ContractAndCheckoutInPersonPercent) / 100) * plan.CountPerson *
plan.IncreasePercentage),
InsuranceInPersonDouble = (((dailyWage * planPercentage.InsuranceInPersonPercent) / 100) *
plan.CountPerson *
plan.IncreasePercentage)
}).ToList();
var finalResult = planResult.Select(plan => new InstitutionPlanListDto()
{
CountPerson = plan.CountPerson,
ContractAndCheckout = plan.ContractAndCheckoutDouble.ToMoney(),
Insurance = plan.InsuranceDouble.ToMoney(),
RollCall = plan.RollCallDouble.ToMoney(),
CustomizeCheckout = plan.CustomizeCheckoutDouble.ToMoney(),
ContractAndCheckoutInPerson = plan.ContractAndCheckoutInPersonDouble.ToMoney(),
InsuranceInPerson = plan.InsuranceInPersonDouble.ToMoney(),
InPersonSumAmountStr =
(plan.ContractAndCheckoutDouble + plan.InsuranceDouble + plan.ContractAndCheckoutInPersonDouble +
plan.InsuranceInPersonDouble).ToMoney(),
OnlineAndInPersonSumAmountStr = (plan.ContractAndCheckoutDouble + plan.InsuranceDouble +
plan.ContractAndCheckoutInPersonDouble + plan.InsuranceInPersonDouble +
plan.RollCallDouble + plan.CustomizeCheckoutDouble).ToMoney(),
OnlineOnlySumAmountStr =
(plan.ContractAndCheckoutDouble + plan.InsuranceDouble + plan.RollCallDouble +
plan.CustomizeCheckoutDouble).ToMoney(),
}).ToList();
return new PagedResult<InstitutionPlanListDto>()
{
TotalCount = count,
List = finalResult
};
}
#endregion
}

View File

@@ -0,0 +1,49 @@
using GozareshgirProgramManager.Application._Common.Interfaces;
using GozareshgirProgramManager.Application._Common.Models;
using GozareshgirProgramManager.Domain._Common;
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
using Microsoft.EntityFrameworkCore;
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AutoStopOverTimeTaskSections;
public record AutoStopOverTimeTaskSectionsCommand : IBaseCommand;
public class AutoStopOverTimeTaskSectionsCommandHandler : IBaseCommandHandler<AutoStopOverTimeTaskSectionsCommand>
{
private readonly ITaskSectionRepository _taskSectionRepository;
private readonly IUnitOfWork _unitOfWork;
public AutoStopOverTimeTaskSectionsCommandHandler(ITaskSectionRepository taskSectionRepository,
IUnitOfWork unitOfWork)
{
_taskSectionRepository = taskSectionRepository;
_unitOfWork = unitOfWork;
}
public async Task<OperationResult> Handle(AutoStopOverTimeTaskSectionsCommand request,
CancellationToken cancellationToken)
{
try
{
// دریافت تمام تسک‌های در حال انجام
var taskSections = await _taskSectionRepository.GetActiveSectionsIncludeAllAsync(cancellationToken);
foreach (var taskSection in taskSections)
{
// استفاده از متد Domain برای بررسی و متوقف کردن خودکار
taskSection.AutoStopIfOverTime();
}
// ذخیره تغییرات در دیتابیس
await _unitOfWork.SaveChangesAsync(cancellationToken);
return OperationResult.Success();
}
catch (Exception ex)
{
return OperationResult.Failure($"خطا در ناتمام کردن تسک‌های overtime: {ex.Message}");
}
}
}

View File

@@ -1,3 +1,4 @@
using System.Globalization;
using GozareshgirProgramManager.Application._Common.Interfaces;
using GozareshgirProgramManager.Application._Common.Models;
using GozareshgirProgramManager.Domain._Common;
@@ -7,21 +8,23 @@ namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.Project
public record ProjectBoardDetailQuery(Guid SectionId) : IBaseQuery<ProjectBoardDetailResponse>;
public record ProjectBoardDetailResponse(List<ProjectBoardDetailUserResponse> Users, string TotalTime);
public record ProjectBoardDetailResponse(List<ProjectBoardDetailUserResponse> Users, string TotalTime,string RemainingTime );
public record ProjectBoardDetailUserResponse
{
public List<ProjectBoardDetailUserHistoryResponse> Histories { get; set; } = new();
public string UserFullName { get; set; }
public long UserId { get; set; }
public List<ProjectBoardDetailUserHistoryResponse> Histories { get; init; }
public string UserFullName { get; init; }
public string TotalTime { get; init; }
public string SpentTime { get; init; }
public long UserId { get; init; }
}
public class ProjectBoardDetailUserHistoryResponse
public record ProjectBoardDetailUserHistoryResponse
{
public string Date { get; set; }
public string startTime { get; set; }
public string EndTime { get; set; }
public string TotalTime { get; set; }
public string Date { get; init; }
public string startTime { get; init; }
public string EndTime { get; init; }
public string TotalTime { get; init; }
}
public class ProjectBoardDetailQueryHandler : IBaseQueryHandler<ProjectBoardDetailQuery, ProjectBoardDetailResponse>
@@ -38,6 +41,7 @@ public class ProjectBoardDetailQueryHandler : IBaseQueryHandler<ProjectBoardDeta
{
var section = await _programManagerDbContext.TaskSections
.Include(x => x.Activities)
.Include(x=>x.AdditionalTimes)
.FirstOrDefaultAsync(x => x.Id == request.SectionId, cancellationToken: cancellationToken);
if (section == null)
@@ -49,16 +53,22 @@ public class ProjectBoardDetailQueryHandler : IBaseQueryHandler<ProjectBoardDeta
.Where(x => userIds.Contains(x.Id))
.ToDictionaryAsync(x => x.Id, x => x.FullName, cancellationToken);
var totalTimeSpan = section.Activities
var totalActivityTimeSpan = section.Activities
.Select(x => x.GetTimeSpent())
.Aggregate(TimeSpan.Zero, (sum, next) => sum.Add(next));
var finalTime = section.FinalEstimatedHours;
var remainingTimeSpan = finalTime >= totalActivityTimeSpan
? TimeSpan.FromTicks(finalTime.Ticks - totalActivityTimeSpan.Ticks)
: TimeSpan.Zero;
var users = section.Activities.GroupBy(x => x.UserId).Select(x =>
{
return new ProjectBoardDetailUserResponse()
{
UserId = x.Key,
UserFullName = usersDict[x.Key],
TotalTime = TimeSpan.FromTicks(x.Sum(h=>h.GetTimeSpent().Ticks)).TotalHours.ToString(CultureInfo.InvariantCulture),
Histories = x.Select(h => new ProjectBoardDetailUserHistoryResponse()
{
Date = h.StartDate.ToFarsi(),
@@ -68,7 +78,8 @@ public class ProjectBoardDetailQueryHandler : IBaseQueryHandler<ProjectBoardDeta
}).ToList()
};
}).ToList();
var response = new ProjectBoardDetailResponse(users, $"{(int)totalTimeSpan.TotalHours}:{totalTimeSpan.Minutes:D2}");
var response = new ProjectBoardDetailResponse(users, $"{(int)totalActivityTimeSpan.TotalHours}:{totalActivityTimeSpan.Minutes:D2}",
$"{(int)remainingTimeSpan.TotalHours}:{remainingTimeSpan.Minutes:D2}");
return OperationResult<ProjectBoardDetailResponse>.Success(response);
}
}

View File

@@ -22,8 +22,9 @@ public class ProjectBoardListQueryHandler : IBaseQueryHandler<ProjectBoardListQu
CancellationToken cancellationToken)
{
var currentUserId = _authHelper.GetCurrentUserId();
var queryable = _programManagerDbContext.TaskSections.AsNoTracking()
.Where(x => x.InitialEstimatedHours > TimeSpan.Zero)
.Where(x => x.InitialEstimatedHours > TimeSpan.Zero && x.Status != TaskSectionStatus.Completed)
.Include(x => x.Task)
.ThenInclude(x => x.Phase)
.ThenInclude(x => x.Project)

View File

@@ -0,0 +1,67 @@
using System.Xml.Schema;
using GozareshgirProgramManager.Application._Common.Interfaces;
using GozareshgirProgramManager.Application._Common.Models;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList;
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
using Microsoft.EntityFrameworkCore;
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectDeployBoardList;
public record ProjectDeployBoardListItem()
{
public string ProjectName { get; set; }
public string PhaseName { get; set; }
public int TotalTasks { get; set; }
public int DoneTasks { get; set; }
public TimeSpan TotalTimeSpan { get; set; }
public TimeSpan DoneTimeSpan { get; set; }
}
public record GetProjectsDeployBoardListResponse(List<ProjectDeployBoardListItem> Items);
public record GetProjectDeployBoardListQuery():IBaseQuery<GetProjectsDeployBoardListResponse>;
public class ProjectDeployBoardListQueryHandler:IBaseQueryHandler<GetProjectDeployBoardListQuery, GetProjectsDeployBoardListResponse>
{
private readonly IProgramManagerDbContext _dbContext;
private readonly IAuthHelper _authHelper;
public ProjectDeployBoardListQueryHandler(IProgramManagerDbContext dbContext, IAuthHelper authHelper)
{
_dbContext = dbContext;
_authHelper = authHelper;
}
public async Task<OperationResult<GetProjectsDeployBoardListResponse>> Handle(GetProjectDeployBoardListQuery request, CancellationToken cancellationToken)
{
var userId = _authHelper.GetCurrentUserId();
if (userId == null)
{
return OperationResult<GetProjectsDeployBoardListResponse>.NotFound("کاربر یافت نشد");
}
var query =await _dbContext.TaskSections
.Include(x=>x.Task)
.ThenInclude(x => x.Phase)
.ThenInclude(x => x.Project)
.AsNoTracking()
.Where(x => x.Status == TaskSectionStatus.Completed
|| x.Status == TaskSectionStatus.PendingForCompletion
|| x.Task.Phase.DeployStatus != ProjectDeployStatus.NoTCompleted)
.GroupBy(x=>x.Task.PhaseId).ToListAsync(cancellationToken: cancellationToken);
var list = query.Select(g => new ProjectDeployBoardListItem
{
ProjectName = g.First().Task.Phase.Project.Name,
PhaseName = g.First().Task.Phase.Name,
TotalTasks = g.Select(x => x.TaskId).Distinct().Count(),
DoneTasks = g.Where(x => x.Status == TaskSectionStatus.Completed).Select(x => x.TaskId).Distinct().Count(),
TotalTimeSpan = TimeSpan.FromHours(g.Sum(x => x.InitialEstimatedHours.TotalHours)),
DoneTimeSpan = TimeSpan.FromHours(g.Where(x => x.Status == TaskSectionStatus.Completed).Sum(x => x.InitialEstimatedHours.TotalHours))
}).ToList();
var response = new GetProjectsDeployBoardListResponse(list);
return OperationResult<GetProjectsDeployBoardListResponse>.Success(response);
}
}

View File

@@ -23,6 +23,7 @@ public class ProjectPhase : ProjectHierarchyNode
ProjectId = projectId;
_tasks = new List<ProjectTask>();
_phaseSections = new List<PhaseSection>();
DeployStatus = ProjectDeployStatus.NoTCompleted;
AddDomainEvent(new PhaseCreatedEvent(Id, projectId, name));
}
@@ -36,6 +37,8 @@ public class ProjectPhase : ProjectHierarchyNode
public DateTime? StartDate { get; private set; }
public DateTime? EndDate { get; private set; }
public int OrderIndex { get; private set; }
public bool IsArchived { get; set; }
public ProjectDeployStatus DeployStatus { get; set; }
#region Task Management
@@ -196,4 +199,26 @@ public class ProjectPhase : ProjectHierarchyNode
}
#endregion
public void SetArchived()
{
IsArchived = true;
}
public void SetUnarchived()
{
IsArchived = false;
}
public void UpdateDeployStatus(ProjectDeployStatus status)
{
DeployStatus = status;
}
}
public enum ProjectDeployStatus
{
NoTCompleted,
PendingDevDeploy,
DevDeployed,
PendingDeploy,
Deployed
}

View File

@@ -217,4 +217,39 @@ public class TaskSection : EntityBase<Guid>
var finalEstimate = FinalEstimatedHours;
return totalSpent < finalEstimate;
}
/// <summary>
/// اگر زمان کار شده بیش از تایم تعیین شده باشد، تسک را متوقف می‌کند
/// و EndDate را به طوری تنظیم می‌کند که کل زمان برابر با FinalEstimatedHours شود
/// </summary>
public void AutoStopIfOverTime()
{
if (Status != TaskSectionStatus.InProgress)
return;
var activeActivity = _activities.FirstOrDefault(a => a.IsActive);
if (activeActivity == null)
return;
// محاسبه کل زمان صرف شده تا کنون (بدون فعالیت فعال)
var totalTimeSpentExcludingActive = _activities.Where(a => !a.IsActive).Sum(a => a.GetTimeSpent().Ticks);
var totalTimeSpentTimeSpan = TimeSpan.FromTicks(totalTimeSpentExcludingActive);
var finalEstimate = FinalEstimatedHours;
// اگر زمان صرف شده (بدون فعالیت فعال) + فعالیت فعال > تایم تعیین شده
var activeTimeSpent = activeActivity.GetTimeSpent();
if (totalTimeSpentTimeSpan + activeTimeSpent > finalEstimate)
{
// محاسبه مدت زمانی که این فعالیت باید برای رسیدن به FinalEstimatedHours داشته باشد
var remainingTime = finalEstimate - totalTimeSpentTimeSpan;
// EndDate = StartDate + remainingTime
var adjustedEndDate = activeActivity.StartDate.Add(remainingTime);
// متوقف کردن فعالیت با EndDate دقیق شده
activeActivity.StopWorkWithSpecificTime(adjustedEndDate, "متوقف خودکار - بیش از تایم تعیین شده");
UpdateStatus(TaskSectionStatus.Incomplete);
}
}
}

View File

@@ -40,6 +40,22 @@ public class TaskSectionActivity : EntityBase<Guid>
IsActive = false;
}
/// <summary>
/// متوقف کردن فعالیت با مشخص کردن EndDate دقیق
/// </summary>
public void StopWorkWithSpecificTime(DateTime endDate, string? endNotes = null)
{
if (!IsActive)
throw new InvalidOperationException("این فعالیت قبلاً متوقف شده است.");
if (endDate < StartDate)
throw new InvalidOperationException("تاریخ پایان نمی‌تواند قبل از تاریخ شروع باشد.");
EndDate = endDate;
EndNotes = endNotes;
IsActive = false;
}
public TimeSpan GetTimeSpent()
{
if (IsActive)

View File

@@ -6,5 +6,6 @@ public enum TaskSectionStatus
ReadyToStart = 1, // آماده شروع
InProgress = 2, // درحال انجام
Incomplete = 3, // ناتمام شده
Completed = 4 // تکمیل شده
PendingForCompletion = 4, // در انتظار تکمیل
Completed = 5 // تکمیل شده
}

View File

@@ -8,171 +8,171 @@ namespace GozareshgirProgramManager.Domain.ProjectAgg.Events;
// Project Events
public record ProjectCreatedEvent(Guid ProjectId, string Name) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record ProjectStatusUpdatedEvent(Guid ProjectId, ProjectStatus Status) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record ProjectAssignedEvent(Guid ProjectId, long UserId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record ProjectUnassignedEvent(Guid ProjectId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
// Phase Events
public record PhaseCreatedEvent(Guid PhaseId, Guid ProjectId, string Name) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record PhaseAddedEvent(Guid PhaseId, Guid ProjectId, string Name) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record PhaseRemovedEvent(Guid PhaseId, Guid ProjectId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record PhaseStatusUpdatedEvent(Guid PhaseId, PhaseStatus Status) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record PhaseAssignedEvent(Guid PhaseId, long UserId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record PhaseUnassignedEvent(Guid PhaseId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
// Task Events
public record TaskCreatedEvent(Guid TaskId, Guid PhaseId, string Name) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record TaskAddedEvent(Guid TaskId, Guid PhaseId, string Name) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record TaskRemovedEvent(Guid TaskId, Guid PhaseId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record TaskStatusUpdatedEvent(Guid TaskId, TaskStatus Status) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record TaskPriorityUpdatedEvent(Guid TaskId, TaskPriority Priority) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record TaskAssignedEvent(Guid TaskId, long UserId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record TaskUnassignedEvent(Guid TaskId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record TaskSectionAddedEvent(Guid TaskId, Guid SectionId, Guid SkillId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record TaskSectionRemovedEvent(Guid TaskId, Guid SectionId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
// TaskSection Events
public record TaskSectionStatusChangedEvent(Guid SectionId, TaskSectionStatus OldStatus,
TaskSectionStatus NewStatus,long UserId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record TaskSectionAssignedEvent(Guid SectionId, long UserId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record TaskSectionTransferredEvent(Guid SectionId, long FromUserId, long ToUserId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
// Section Events (Legacy - keeping for backward compatibility)
public record ProjectPhaseAddedEvent(Guid ProjectId, Guid PhaseId, string PhaseName) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record ProjectTaskStatusChangedEvent(Guid SectionId, TaskStatus OldStatus, TaskStatus NewStatus) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record ProjectSectionAddedEvent(Guid SectionId, Guid TaskId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record ProjectSectionAssignedEvent(Guid SectionId, long UserId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record ProjectSectionTransferredEvent(Guid SectionId, long FromUserId, long ToUserId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record WorkStartedEvent(Guid SectionId, long UserId, DateTime StartTime, string? Notes) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record WorkStoppedEvent(Guid SectionId, long UserId, DateTime StartTime, DateTime EndTime, TimeSpan Duration, string? Notes) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record ProjectSectionCompletedEvent(Guid ProjectId, long UserId, TimeSpan TotalTimeSpent, string? Notes) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record AdditionalTimeAddedEvent(Guid ProjectId, Guid AdditionalTimeId, TimeSpan Hours, string? Reason, long? AddedByUserId) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record AdditionalTimeRemovedEvent(Guid ProjectId, Guid AdditionalTimeId, TimeSpan RemovedHours) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}
public record InitialEstimatedTimeUpdatedEvent(Guid ProjectId, TimeSpan OldEstimate, TimeSpan NewEstimate) : IDomainEvent
{
public DateTime OccurredOn { get; init; } = DateTime.UtcNow;
public DateTime OccurredOn { get; init; } = DateTime.Now;
}

View File

@@ -1,3 +1,4 @@
using System.Collections;
using GozareshgirProgramManager.Domain._Common;
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
@@ -11,4 +12,5 @@ public interface ITaskSectionRepository: IRepository<Guid,TaskSection>
Task<TaskSection?> GetByIdWithFullDataAsync(Guid id, CancellationToken cancellationToken = default);
Task<List<TaskSection>> GetAssignedToUserAsync(long userId);
Task<List<TaskSection>> GetActiveSectionsIncludeAllAsync(CancellationToken cancellationToken);
}

View File

@@ -0,0 +1,865 @@
// <auto-generated />
using System;
using GozareshgirProgramManager.Infrastructure.Persistence.Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace GozareshgirProgramManager.Infrastructure.Migrations
{
[DbContext(typeof(ProgramManagerDbContext))]
[Migration("20251227094008_add phase deploy status and is archived")]
partial class addphasedeploystatusandisarchived
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "10.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("GozareshgirProgramManager.Domain.CheckoutAgg.Entities.Checkout", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CheckoutEndDate")
.HasColumnType("datetime2");
b.Property<DateTime>("CheckoutStartDate")
.HasColumnType("datetime2");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<double>("DeductionFromSalary")
.HasColumnType("float");
b.Property<string>("FullName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<int>("MandatoryHours")
.HasColumnType("int");
b.Property<int>("Month")
.HasColumnType("int");
b.Property<double>("MonthlySalaryDefined")
.HasColumnType("float");
b.Property<double>("MonthlySalaryPay")
.HasColumnType("float");
b.Property<int>("RemainingHours")
.HasColumnType("int");
b.Property<int>("TotalDaysWorked")
.HasColumnType("int");
b.Property<int>("TotalHoursWorked")
.HasColumnType("int");
b.Property<long>("UserId")
.HasColumnType("bigint");
b.Property<int>("Year")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("Checkouts", (string)null);
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.CustomerAgg.Customer", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime2");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Email")
.IsRequired()
.HasMaxLength(256)
.HasColumnType("nvarchar(256)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("Id");
b.ToTable("Customers", (string)null);
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<Guid>("PhaseId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("SkillId")
.HasColumnType("uniqueidentifier");
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("PhaseId");
b.HasIndex("SkillId");
b.ToTable("PhaseSections");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<DateTime?>("EndDate")
.HasColumnType("datetime2");
b.Property<bool>("HasAssignmentOverride")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<DateTime?>("PlannedEndDate")
.HasColumnType("datetime2");
b.Property<DateTime?>("PlannedStartDate")
.HasColumnType("datetime2");
b.Property<DateTime?>("StartDate")
.HasColumnType("datetime2");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.ToTable("Projects", (string)null);
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("DeployStatus")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<string>("Description")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<DateTime?>("EndDate")
.HasColumnType("datetime2");
b.Property<bool>("HasAssignmentOverride")
.HasColumnType("bit");
b.Property<bool>("IsArchived")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<int>("OrderIndex")
.HasColumnType("int");
b.Property<Guid>("ProjectId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime?>("StartDate")
.HasColumnType("datetime2");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.HasIndex("ProjectId");
b.ToTable("ProjectPhases", (string)null);
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<Guid>("ProjectId")
.HasColumnType("uniqueidentifier");
b.Property<Guid>("SkillId")
.HasColumnType("uniqueidentifier");
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("ProjectId");
b.HasIndex("SkillId");
b.ToTable("ProjectSections");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<string>("AllocatedTime")
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<DateTime?>("DueDate")
.HasColumnType("datetime2");
b.Property<DateTime?>("EndDate")
.HasColumnType("datetime2");
b.Property<bool>("HasAssignmentOverride")
.HasColumnType("bit");
b.Property<bool>("HasTimeOverride")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<int>("OrderIndex")
.HasColumnType("int");
b.Property<Guid>("PhaseId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Priority")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<DateTime?>("StartDate")
.HasColumnType("datetime2");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.HasIndex("PhaseId");
b.ToTable("ProjectTasks", (string)null);
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<long>("CurrentAssignedUserId")
.HasColumnType("bigint");
b.Property<string>("InitialDescription")
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<string>("InitialEstimatedHours")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<long>("OriginalAssignedUserId")
.HasColumnType("bigint");
b.Property<Guid>("SkillId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<Guid>("TaskId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("SkillId");
b.HasIndex("TaskId");
b.ToTable("TaskSections", (string)null);
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<DateTime?>("EndDate")
.HasColumnType("datetime2");
b.Property<string>("EndNotes")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<string>("Notes")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<Guid>("SectionId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("StartDate")
.HasColumnType("datetime2");
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("SectionId");
b.ToTable("TaskSectionActivities", (string)null);
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionAdditionalTime", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("AddedAt")
.HasColumnType("datetime2");
b.Property<long?>("AddedByUserId")
.HasColumnType("bigint");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Hours")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<string>("Reason")
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<Guid?>("TaskSectionId")
.HasColumnType("uniqueidentifier");
b.HasKey("Id");
b.HasIndex("TaskSectionId");
b.ToTable("TaskSectionAdditionalTimes", (string)null);
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<long?>("GozareshgirRoleId")
.HasColumnType("bigint");
b.Property<string>("RoleName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.HasKey("Id");
b.ToTable("PmRoles", (string)null);
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<DateTime?>("EndSettingDate")
.HasColumnType("datetime2");
b.Property<bool>("HolidayWorking")
.HasColumnType("bit");
b.Property<double>("MonthlySalary")
.HasColumnType("float");
b.Property<DateTime?>("StartSettingDate")
.HasColumnType("datetime2");
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.ToTable("SalaryPaymentSetting", (string)null);
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.HasKey("Id");
b.ToTable("Skills", (string)null);
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
b.Property<long?>("AccountId")
.HasColumnType("bigint");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Email")
.HasMaxLength(150)
.HasColumnType("nvarchar(150)");
b.Property<string>("FullName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<string>("Mobile")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");
b.Property<string>("Password")
.IsRequired()
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
b.Property<string>("ProfilePhotoPath")
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<string>("UserName")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("VerifyCode")
.HasMaxLength(10)
.HasColumnType("nvarchar(10)");
b.HasKey("Id");
b.ToTable("Users", (string)null);
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<DateTime>("ExpiresAt")
.HasColumnType("datetime2");
b.Property<string>("IpAddress")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<DateTime?>("RevokedAt")
.HasColumnType("datetime2");
b.Property<string>("Token")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<string>("UserAgent")
.HasMaxLength(500)
.HasColumnType("nvarchar(500)");
b.Property<long>("UserId")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("ExpiresAt");
b.HasIndex("Token")
.IsUnique();
b.HasIndex("UserId");
b.ToTable("UserRefreshTokens", (string)null);
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.PhaseSection", b =>
{
b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase")
.WithMany("PhaseSections")
.HasForeignKey("PhaseId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill")
.WithMany()
.HasForeignKey("SkillId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("Phase");
b.Navigation("Skill");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b =>
{
b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project")
.WithMany("Phases")
.HasForeignKey("ProjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Project");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectSection", b =>
{
b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", "Project")
.WithMany("ProjectSections")
.HasForeignKey("ProjectId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill")
.WithMany()
.HasForeignKey("SkillId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("Project");
b.Navigation("Skill");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b =>
{
b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", "Phase")
.WithMany("Tasks")
.HasForeignKey("PhaseId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Phase");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b =>
{
b.HasOne("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", "Skill")
.WithMany("Sections")
.HasForeignKey("SkillId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", "Task")
.WithMany("Sections")
.HasForeignKey("TaskId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Skill");
b.Navigation("Task");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionActivity", b =>
{
b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", "Section")
.WithMany("Activities")
.HasForeignKey("SectionId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Section");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSectionAdditionalTime", b =>
{
b.HasOne("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", null)
.WithMany("AdditionalTimes")
.HasForeignKey("TaskSectionId");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.RoleAgg.Entities.Role", b =>
{
b.OwnsMany("GozareshgirProgramManager.Domain.PermissionAgg.Entities.Permission", "Permissions", b1 =>
{
b1.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property<long>("Id"));
b1.Property<int>("Code")
.HasColumnType("int");
b1.Property<long>("RoleId")
.HasColumnType("bigint");
b1.HasKey("Id");
b1.HasIndex("RoleId");
b1.ToTable("PmRolePermissions", (string)null);
b1.WithOwner("Role")
.HasForeignKey("RoleId");
b1.Navigation("Role");
});
b.Navigation("Permissions");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.SalaryPaymentSetting", b =>
{
b.OwnsMany("GozareshgirProgramManager.Domain.SalaryPaymentSettingAgg.Entities.WorkingHours", "WorkingHoursList", b1 =>
{
b1.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property<long>("Id"));
b1.Property<TimeSpan>("EndShiftOne")
.HasColumnType("time(0)");
b1.Property<TimeSpan>("EndShiftTwo")
.HasColumnType("time(0)");
b1.Property<bool>("HasRestTime")
.HasColumnType("bit");
b1.Property<bool>("HasShiftOne")
.HasColumnType("bit");
b1.Property<bool>("HasShiftTow")
.HasColumnType("bit");
b1.Property<bool>("IsActiveDay")
.HasColumnType("bit");
b1.Property<int>("PersianDayOfWeek")
.HasColumnType("int");
b1.Property<TimeSpan>("RestTime")
.HasColumnType("time(0)");
b1.Property<long>("SalaryPaymentSettingId")
.HasColumnType("bigint");
b1.Property<int>("ShiftDurationInMinutes")
.HasColumnType("int");
b1.Property<TimeSpan>("StartShiftOne")
.HasColumnType("time(0)");
b1.Property<TimeSpan>("StartShiftTwo")
.HasColumnType("time(0)");
b1.HasKey("Id");
b1.HasIndex("SalaryPaymentSettingId");
b1.ToTable("WorkingHours", (string)null);
b1.WithOwner("SalaryPaymentSetting")
.HasForeignKey("SalaryPaymentSettingId");
b1.Navigation("SalaryPaymentSetting");
});
b.Navigation("WorkingHoursList");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b =>
{
b.OwnsMany("GozareshgirProgramManager.Domain.RoleUserAgg.RoleUser", "RoleUser", b1 =>
{
b1.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property<long>("Id"));
b1.Property<long>("RoleId")
.HasColumnType("bigint");
b1.Property<long>("UserId")
.HasColumnType("bigint");
b1.HasKey("Id");
b1.HasIndex("UserId");
b1.ToTable("RoleUsers", (string)null);
b1.WithOwner("User")
.HasForeignKey("UserId");
b1.Navigation("User");
});
b.Navigation("RoleUser");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.UserRefreshToken", b =>
{
b.HasOne("GozareshgirProgramManager.Domain.UserAgg.Entities.User", "User")
.WithMany("RefreshTokens")
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("User");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b =>
{
b.Navigation("Phases");
b.Navigation("ProjectSections");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectPhase", b =>
{
b.Navigation("PhaseSections");
b.Navigation("Tasks");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b =>
{
b.Navigation("Sections");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.TaskSection", b =>
{
b.Navigation("Activities");
b.Navigation("AdditionalTimes");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.SkillAgg.Entities.Skill", b =>
{
b.Navigation("Sections");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.UserAgg.Entities.User", b =>
{
b.Navigation("RefreshTokens");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,41 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace GozareshgirProgramManager.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class addphasedeploystatusandisarchived : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "DeployStatus",
table: "ProjectPhases",
type: "nvarchar(30)",
maxLength: 30,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<bool>(
name: "IsArchived",
table: "ProjectPhases",
type: "bit",
nullable: false,
defaultValue: false);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "DeployStatus",
table: "ProjectPhases");
migrationBuilder.DropColumn(
name: "IsArchived",
table: "ProjectPhases");
}
}
}

View File

@@ -126,7 +126,7 @@ namespace GozareshgirProgramManager.Infrastructure.Migrations
b.HasIndex("SkillId");
b.ToTable("PhaseSections", (string)null);
b.ToTable("PhaseSections");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.Project", b =>
@@ -179,6 +179,11 @@ namespace GozareshgirProgramManager.Infrastructure.Migrations
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("DeployStatus")
.IsRequired()
.HasMaxLength(30)
.HasColumnType("nvarchar(30)");
b.Property<string>("Description")
.HasMaxLength(1000)
.HasColumnType("nvarchar(1000)");
@@ -189,6 +194,9 @@ namespace GozareshgirProgramManager.Infrastructure.Migrations
b.Property<bool>("HasAssignmentOverride")
.HasColumnType("bit");
b.Property<bool>("IsArchived")
.HasColumnType("bit");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
@@ -238,7 +246,7 @@ namespace GozareshgirProgramManager.Infrastructure.Migrations
b.HasIndex("SkillId");
b.ToTable("ProjectSections", (string)null);
b.ToTable("ProjectSections");
});
modelBuilder.Entity("GozareshgirProgramManager.Domain.ProjectAgg.Entities.ProjectTask", b =>

View File

@@ -48,6 +48,9 @@ public class ProjectPhaseMapping : IEntityTypeConfiguration<ProjectPhase>
builder.Property(ph => ph.HasAssignmentOverride)
.IsRequired();
builder.Property(x => x.DeployStatus)
.HasConversion<string>().HasMaxLength(30);
// Relationship with Project
builder.HasOne(ph => ph.Project)
.WithMany(p => p.Phases)

View File

@@ -1,4 +1,5 @@
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
using GozareshgirProgramManager.Infrastructure.Persistence._Common;
using GozareshgirProgramManager.Infrastructure.Persistence.Context;
@@ -35,4 +36,13 @@ public class TaskSectionRepository:RepositoryBase<Guid,TaskSection>,ITaskSection
.Where(x => x.CurrentAssignedUserId == userId)
.ToListAsync();
}
public Task<List<TaskSection>> GetActiveSectionsIncludeAllAsync(CancellationToken cancellationToken)
{
return _context.TaskSections
.Where(x => x.Status == TaskSectionStatus.InProgress)
.Include(x => x.Activities)
.Include(x => x.AdditionalTimes)
.ToListAsync(cancellationToken);
}
}

View File

@@ -1,6 +1,7 @@
using System.Runtime.InteropServices;
using GozareshgirProgramManager.Application._Common.Models;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.AssignProject;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.AutoStopOverTimeTaskSections;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeStatusSection;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.DeleteProject;
@@ -11,6 +12,7 @@ using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectA
using GozareshgirProgramManager.Application.Modules.Projects.Queries.GetProjectsList;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardDetail;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectBoardList;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectDeployBoardList;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectSetTimeDetails;
using MediatR;
using Microsoft.AspNetCore.Mvc;
@@ -98,6 +100,9 @@ public class ProjectController : ProgramManagerBaseController
[HttpGet("board")]
public async Task<ActionResult<OperationResult<List<ProjectBoardListResponse>>>> GetProjectBoard([FromQuery] ProjectBoardListQuery query)
{
// اجرای Command برای متوقف کردن تسک‌های overtime قبل از نمایش
await _mediator.Send(new AutoStopOverTimeTaskSectionsCommand());
var res = await _mediator.Send(query);
return res;
}
@@ -108,4 +113,11 @@ public class ProjectController : ProgramManagerBaseController
var res = await _mediator.Send(query);
return res;
}
[HttpGet("deploy-board")]
public async Task<ActionResult<OperationResult<GetProjectsDeployBoardListResponse>>> GetProjectDeployBoard()
{
var request = new GetProjectDeployBoardListQuery();
return await _mediator.Send(request);
}
}

View File

@@ -1,63 +0,0 @@
using _0_Framework.Application;
using AccountManagement.Application.Contracts.Ticket;
using CompanyManagment.App.Contracts.InstitutionPlan;
using CompanyManagment.App.Contracts.Workshop;
using Microsoft.AspNetCore.Mvc;
using ServiceHost.BaseControllers;
namespace ServiceHost.Areas.Admin.Controllers;
public class ServiceAmountsManagement : AdminBaseController
{
private readonly IInstitutionPlanApplication _institutionPlanApplication;
private readonly IAuthHelper _authHelper;
public ServiceAmountsManagement(IInstitutionPlanApplication institutionPlanApplication, IAuthHelper authHelper)
{
_institutionPlanApplication = institutionPlanApplication;
_authHelper = authHelper;
}
/// <summary>
/// دریافت دیتای مودال ایجاد
/// </summary>
/// <returns></returns>
[HttpGet("GetCreateModalData")]
public async Task<ActionResult<CreateServiceAmountDto>> GetCreateModalData()
{
if(!_authHelper.HasPermission(315))
return Forbid();
var data = await _institutionPlanApplication.GetCreateModalData();
return data;
}
/// <summary>
/// ذخیره درصدها
/// </summary>
/// <param name="command"></param>
/// <returns></returns>
[HttpPost("CreateServicePercentage")]
public async Task<ActionResult<OperationResult>> CreateServicePercentage([FromBody] CreateServiceAmountDto command)
{
if (!_authHelper.HasPermission(315))
return Forbid();
var result = await _institutionPlanApplication.CreateInstitutionPlanPercentage(command);
return result;
}
/// <summary>
/// دریافت لیست مبالغ سرویس ها
/// </summary>
/// <param name="searchModel"></param>
/// <returns></returns>
[HttpGet("GetList")]
public async Task<ActionResult<PagedResult<InstitutionPlanListDto>>> GetList(InstitutionPlanSearchModel searchModel)
{
return await _institutionPlanApplication.GetList(searchModel);
}
}

View File

@@ -14,6 +14,7 @@ using Company.Domain.PaymentTransactionAgg;
using Company.Domain.RewardAgg;
using Company.Domain.RollCallAgg.DomainService;
using CompanyManagement.Infrastructure.Excel.WorkshopsRollCall;
using CompanyManagement.Infrastructure.Excel.Checkout.AsghaeeAzarWorkshops;
using CompanyManagment.App.Contracts.AndroidApkVersion;
using CompanyManagment.App.Contracts.InstitutionContract;
using CompanyManagment.App.Contracts.PaymentTransaction;
@@ -152,7 +153,10 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk
{
//await UpdateInstitutionContract();
//await UpdateFaceEmbeddingNames();
await SetInstitutionContractSigningType();
//await SetInstitutionContractSigningType();
var data = OnGetExportAsghaeeAzarWorkshops();
return File(data, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"AsghaeeAzarWorkshops.xlsx");
ViewData["message"] = "تومام یک";
return Page();
}
@@ -1111,6 +1115,28 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk
}
#endregion
#region Excel
/// <summary>
/// خروجی اکسل آقایی آذر ورکشاپ
/// </summary>
/// <returns></returns>
private byte[] OnGetExportAsghaeeAzarWorkshops()
{
var data = _context.CheckoutSet
.Where(x => x.WorkshopId == 768 && x.Month =="آذر" && x.Year =="1404")
.Select(x => new AsghaeeAzarWorkshopsExcelViewModel()
{
FinalAmount = x.TotalPayment.ToMoney(),
FullName = x.EmployeeFullName,
NationalCode = x.NationalCode
}).ToList();
return AsghaeeAzarWorkshopsExcelGenerator.Generate(data);
}
#endregion
}
public class IndexModel2 : PageModel