Merge branch 'Feature/InstitutionContract/add-registration-style' into Main

This commit is contained in:
2025-09-17 15:51:24 +03:30
13 changed files with 10773 additions and 63 deletions

View File

@@ -10,5 +10,6 @@ namespace Company.Domain.LawAgg
Task<Law> GetWithItems(long id);
Task<List<Law>> GetActive();
Task<LawViewModel> GetByType(LawType type);
Task<List<LawViewModel>> GetList(LawSearchModel searchModel);
}
}

View File

@@ -11,7 +11,6 @@ namespace Company.Domain.LawAgg
public string Title { get; private set; }
public bool IsActive { get; private set; }
public List<LawItem> Items { get; private set; }
public LawType Type { get; private set; }
public Law(string title, LawType lawType)

View File

@@ -22,6 +22,7 @@ public class ContractingPartyTemp : EntityBase
Gender = gender;
DateOfBirth = dateOfBirth;
PublicId = Guid.NewGuid();
Status = ContractingPartyTempStatus.InComplete;
}
/// <summary>
@@ -92,6 +93,11 @@ public class ContractingPartyTemp : EntityBase
/// </summary>
public string Address { get; private set; }
public ContractingPartyTempStatus Status { get; set; }
public string VerifyCode { get; set; }
public DateTime VerifyCodeSentDateTime { get; set; }
public Guid PublicId { get; set; }
public void UpdateAddress(string state, string city, string address)
@@ -100,4 +106,21 @@ public class ContractingPartyTemp : EntityBase
this.City = city;
this.Address = address;
}
public void SetCompleted()
{
Status = ContractingPartyTempStatus.Completed;
}
public void SetVerifyCode(string verifyCode)
{
VerifyCode = verifyCode;
VerifyCodeSentDateTime = DateTime.Now;
}
}
public enum ContractingPartyTempStatus
{
InComplete,
Completed
}

View File

@@ -1,6 +1,8 @@
using _0_Framework.Application;
using System.Collections.Generic;
using System.Security.AccessControl;
using System.Threading.Tasks;
using CompanyManagment.App.Contracts.Workshop;
namespace CompanyManagment.App.Contracts.Law
{
@@ -13,12 +15,18 @@ namespace CompanyManagment.App.Contracts.Law
OperationResult ActivateByType(LawType type);
OperationResult DeactivateByType(LawType type);
EditLaw GetDetails(long id);
List<LawViewModel> GetList();
Task<List<LawViewModel>> GetList(LawSearchModel searchModel);
Task<LawViewModel> GetLawWithItems(long id);
Task<LawViewModel> GetLawByType(LawType type);
OperationResult UpsertLaw(EditLaw command);
}
public class LawSearchModel
{
public string Title { get; set; }
public string Text { get; set; }
}
public enum LawType
{
/// <summary>

View File

@@ -195,40 +195,12 @@ public class LawApplication : ILawApplication
};
}
public List<LawViewModel> GetList()
public async Task<List<LawViewModel>> GetList(LawSearchModel searchModel)
{
// Get all laws from database
var dbLaws = _lawRepository.Get()
.Select(x => new LawViewModel
{
Id = x.id,
Title = x.Title,
IsActive = x.IsActive,
CreatedAt = x.CreationDate,
Type = x.Type
}).ToList();
// Get filtered laws from database
return await _lawRepository.GetList(searchModel);
// Create a set of existing law types
var existingTypes = dbLaws.Select(x => x.Type).ToHashSet();
// Add placeholder laws for any missing enum values
foreach (LawType lawType in Enum.GetValues(typeof(LawType)))
{
if (!existingTypes.Contains(lawType))
{
dbLaws.Add(new LawViewModel
{
Id = 0, // Indicates it doesn't exist in the database yet
Title = GetDefaultTitleForLawType(lawType),
IsActive = false,
CreatedAt = DateTime.Now,
Type = lawType,
Items = new List<LawItemViewModel>()
});
}
}
return dbLaws;
}
private string GetDefaultTitleForLawType(LawType lawType)

View File

@@ -848,31 +848,27 @@ public class TemporaryClientRegistrationApplication : ITemporaryClientRegistrati
public async Task<OperationResult> CheckVerifyCodeIsTrue(long contractingPartyTempId, string verifyCode)
{
var op = new OperationResult();
var institutionContractTemp = await
_institutionContractTempRepository.GetInstitutionContractTemp(0, contractingPartyTempId);
if (institutionContractTemp == null)
var contractingPartyTemp = _contractingPartyTempRepository.Get( contractingPartyTempId);
if (contractingPartyTemp == null)
return op.Failed("خظا");
if (institutionContractTemp.RegistrationStatus != InstitutionContractTempStatus.VerifyCodeSent)
return op.Failed("خطا");
if (contractingPartyTemp.Status != ContractingPartyTempStatus.InComplete)
return op.Failed("شما قبلا ثبت نام خود را تکمیل نموده اید");
if (institutionContractTemp.VerifyCodeEndTime < DateTime.Now)
if (contractingPartyTemp.VerifyCodeSentDateTime.AddMinutes(2) < DateTime.Now)
return op.Failed("کد شما منقضی شده است");
if (institutionContractTemp.SendVerifyCodeTime < DateTime.Now &&
institutionContractTemp.VerifyCodeEndTime >= DateTime.Now)
if (contractingPartyTemp.VerifyCodeSentDateTime < DateTime.Now &&
contractingPartyTemp.VerifyCodeSentDateTime >= DateTime.Now)
{
if (institutionContractTemp.VerifyCode == verifyCode)
if (contractingPartyTemp.VerifyCode == verifyCode)
{
contractingPartyTemp.SetCompleted();
await _contractingPartyTempRepository.SaveChangesAsync();
return op.Succcedded();
}
else
{
return op.Failed("کد وارد شده صحیح نیست");
}
}
return op.Failed("کد وارد شده صحیح نیست");
}
@@ -918,17 +914,21 @@ public class TemporaryClientRegistrationApplication : ITemporaryClientRegistrati
public async Task<OperationResult> SendAgreementLink(long contractingPartyTempId)
{
var op = new OperationResult();
var institutionContractTemp = _institutionContractTempRepository.Get(contractingPartyTempId);
if (institutionContractTemp == null)
var contractingPartyTemp = _contractingPartyTempRepository.Get(contractingPartyTempId);
if (contractingPartyTemp == null)
throw new NotFoundException("طرف حساب یافت نشد");
if (institutionContractTemp.RegistrationStatus == InstitutionContractTempStatus.Completed)
if (contractingPartyTemp.Status == ContractingPartyTempStatus.Completed)
throw new BadRequestException("شما قبلا ثبت نام خود را تکمیل نموده اید");
//ارسال لینک به طرف حساب
//Todo: implement the logic to send the agreement link to the contracting party
Random generator = new Random();
string verifyCode = generator.Next(1, 1000000).ToString("D6");
contractingPartyTemp.SetVerifyCode(verifyCode);
await _contractingPartyTempRepository.SaveChangesAsync();
await _smsService.SendVerifyCodeToClient(contractingPartyTemp.Phone, verifyCode);
return op.Succcedded();
}
}

View File

@@ -28,5 +28,8 @@ public class ContractingPartyTempMapping : IEntityTypeConfiguration<ContractingP
v => v.ToString(),
v => (Gender)Enum.Parse(typeof(Gender), v)).HasMaxLength(6);
builder.Property(x => x.DateOfBirth);
builder.Property(x => x.Status).HasConversion<string>().HasMaxLength(20);
builder.Property(x => x.VerifyCode).HasMaxLength(12);
}
}

View File

@@ -0,0 +1,53 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace CompanyManagment.EFCore.Migrations
{
/// <inheritdoc />
public partial class addverifyCodetocontractingpartytemp : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Status",
table: "ContractingPartyTemp",
type: "nvarchar(20)",
maxLength: 20,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "VerifyCode",
table: "ContractingPartyTemp",
type: "nvarchar(12)",
maxLength: 12,
nullable: true);
migrationBuilder.AddColumn<DateTime>(
name: "VerifyCodeSentDateTime",
table: "ContractingPartyTemp",
type: "datetime2",
nullable: false,
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Status",
table: "ContractingPartyTemp");
migrationBuilder.DropColumn(
name: "VerifyCode",
table: "ContractingPartyTemp");
migrationBuilder.DropColumn(
name: "VerifyCodeSentDateTime",
table: "ContractingPartyTemp");
}
}
}

View File

@@ -5589,6 +5589,18 @@ namespace CompanyManagment.EFCore.Migrations
.HasMaxLength(35)
.HasColumnType("nvarchar(35)");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");
b.Property<string>("VerifyCode")
.HasMaxLength(12)
.HasColumnType("nvarchar(12)");
b.Property<DateTime>("VerifyCodeSentDateTime")
.HasColumnType("datetime2");
b.HasKey("id");
b.ToTable("ContractingPartyTemp", (string)null);

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@@ -42,4 +43,58 @@ public class LawRepository:RepositoryBase<long,Law>,ILawRepository
}).ToList()
}).FirstOrDefaultAsync();
}
public async Task<List<LawViewModel>> GetList(LawSearchModel searchModel)
{
var query = _context.Laws.Include(x => x.Items).AsQueryable();
if (!string.IsNullOrWhiteSpace(searchModel.Title))
query = query.Where(x => x.Title.Contains(searchModel.Title));
if (!string.IsNullOrWhiteSpace(searchModel.Text))
query = query.Where(x => x.Title.Contains(searchModel.Text) || x.Items.Any(i => i.Header.Contains(searchModel.Text) || i.Details.Contains(searchModel.Text)));
var list = await query.Select(x => new LawViewModel
{
Id = x.id,
Title = x.Title,
IsActive = x.IsActive,
CreatedAt = x.CreationDate,
Type = x.Type
}).ToListAsync();
// Create a set of existing law types
var existingTypes = list.Select(x => x.Type).ToHashSet();
if (string.IsNullOrWhiteSpace(searchModel.Text) && string.IsNullOrWhiteSpace(searchModel.Title))
{
// Add placeholder laws for any missing enum values
foreach (LawType lawType in Enum.GetValues(typeof(LawType)))
{
if (!existingTypes.Contains(lawType))
{
list.Add(new LawViewModel
{
Id = 0, // Indicates it doesn't exist in the database yet
Title = GetDefaultTitleForLawType(lawType),
IsActive = false,
CreatedAt = DateTime.Now,
Type = lawType,
Items = new List<LawItemViewModel>()
});
}
}
}
return list;
}
private string GetDefaultTitleForLawType(LawType lawType)
{
return lawType switch
{
LawType.Register => "قوانین ثبت نام",
_ => $"قوانین {lawType}"
};
}
}

View File

@@ -19,9 +19,9 @@ public class LawController : AdminBaseController
/// </summary>
/// <returns></returns>
[HttpGet]
public ActionResult<List<LawViewModel>> GetList()
public async Task<ActionResult<List<LawViewModel>>> GetList(LawSearchModel searchModel)
{
return _lawApplication.GetList();
return await _lawApplication.GetList(searchModel);
}
/// <summary>

View File

@@ -3,6 +3,7 @@ using _0_Framework.Application;
using _0_Framework.Application.Enums;
using _0_Framework.Exceptions;
using AccountManagement.Application.Contracts.Account;
using Company.Domain.TemporaryClientRegistrationAgg;
using CompanyManagement.Infrastructure.Excel.InstitutionContract;
using CompanyManagment.App.Contracts.Employer;
using CompanyManagment.App.Contracts.InstitutionContract;
@@ -32,12 +33,13 @@ public class institutionContractController : AdminBaseController
private readonly IEmployerApplication _employerApplication;
private readonly IWorkshopApplication _workshopApplication;
private readonly ITemporaryClientRegistrationApplication _temporaryClientRegistration;
private readonly ITemporaryClientRegistrationApplication _clientRegistrationApplication;
public institutionContractController(IInstitutionContractApplication institutionContractApplication,
IPersonalContractingPartyApp contractingPartyApplication, IContactInfoApplication contactInfoApplication,
IAccountApplication accountApplication, IEmployerApplication employerApplication,
IWorkshopApplication workshopApplication, ITemporaryClientRegistrationApplication temporaryClientRegistration)
IWorkshopApplication workshopApplication, ITemporaryClientRegistrationApplication temporaryClientRegistration, ITemporaryClientRegistrationApplication clientRegistrationApplication)
{
_institutionContractApplication = institutionContractApplication;
_contractingPartyApplication = contractingPartyApplication;
@@ -46,6 +48,7 @@ public class institutionContractController : AdminBaseController
_employerApplication = employerApplication;
_workshopApplication = workshopApplication;
_temporaryClientRegistration = temporaryClientRegistration;
_clientRegistrationApplication = clientRegistrationApplication;
}
/// <summary>
@@ -679,7 +682,7 @@ public class institutionContractController : AdminBaseController
{
using var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
var operationResult =
await _temporaryClientRegistration.CheckVerifyCodeIsTrue(request.ContractingPartyId, request.verifyCode);
await _clientRegistrationApplication.CheckVerifyCodeIsTrue(request.ContractingPartyId, request.verifyCode);
if (!operationResult.IsSuccedded)
return operationResult;
@@ -690,8 +693,7 @@ public class institutionContractController : AdminBaseController
return operationResult;
}
}
public class InstitutionPlanCalculatorResponse