Compare commits

...

44 Commits

Author SHA1 Message Date
8e72b56758 refactor: format BlockMessageForElectronicContract method parameters for improved readability 2025-12-31 18:16:51 +03:30
a6e1251445 Merge branch 'master' of https://github.com/syntax24/OriginalGozareshgir into Feature/gateway/add-debt-payment
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
2025-12-31 18:13:06 +03:30
490a1a69d5 add: implement Sepehr payment gateway integration and enhance financial invoice handling 2025-12-31 18:12:27 +03:30
7e3ea39d5b add: update payment gateway integration and enhance transaction handling in callback 2025-12-31 16:08:52 +03:30
66a6c411d6 add: implement payment callback handling and enhance financial invoice structure 2025-12-31 15:49:44 +03:30
SamSys
b03a806dfb BackgroundTask change for new institutionContract sms 2025-12-31 14:11:10 +03:30
14ff0a2e59 Merge branch 'Feature/program-manager/test-upload' 2025-12-30 20:58:25 +03:30
58f695fe95 Merge branch 'Feature/institution-contract/change-account-with-data' 2025-12-30 20:58:12 +03:30
b4ccacd37e Merge branch 'Feature/institution-contract/refactor-creation'
# Conflicts:
#	CompanyManagment.EFCore/Repository/InstitutionContractRepository.cs
2025-12-30 20:56:34 +03:30
1fef8e355a Merge remote-tracking branch 'origin/master' 2025-12-30 20:54:58 +03:30
147621de34 feat: update institution contract creation to retrieve representatives and set contracting party info 2025-12-30 20:53:44 +03:30
d663857de1 feat: add contracting party response class and update endpoints for institution contract creation 2025-12-30 19:51:28 +03:30
SamSys
4d326b1983 reminderSms Change to electronicInstitutionContract 2025-12-30 18:38:08 +03:30
aa37ca4b28 add: enhance deployment status validation in ChangeDeployStatusProject command and include Activities in ProjectDeployBoardList query 2025-12-30 17:19:59 +03:30
9bbdff9bc6 fix bug InstitutionContractRepository.cs 2025-12-30 16:44:02 +03:30
45615684ed add: enhance skill calculation in ProjectDeployBoardDetailsQueryHandler and refine query conditions in ProjectDeployBoardListQueryHandler 2025-12-30 15:55:57 +03:30
d11fdcf106 feat: enhance institution contract creation with representative retrieval and code formatting improvements 2025-12-30 14:25:11 +03:30
eb9a3e52fe feat: implement async methods for activating and deactivating personal contracting parties 2025-12-30 13:50:09 +03:30
94955ea1b4 add: update GetProjectDeployBoardDetails method to use ProjectDeployBoardDetailsQuery 2025-12-30 12:54:53 +03:30
16c1ae04a9 remove some injections 2025-12-30 12:44:55 +03:30
656bb49fab add: remove GetByIdAsync method and add Id property to ProjectDeployBoardListItem 2025-12-30 12:30:06 +03:30
cf3f0564f9 feat: remove Excel download endpoint from institution contract controller 2025-12-30 12:13:57 +03:30
fb5b98bf25 add: update UpdateDeployStatus method to archive project phase upon deployment 2025-12-30 11:54:56 +03:30
12318a6a51 refactor: comment out unused methods and clean up repository interfaces 2025-12-30 11:37:33 +03:30
1e733f3f20 add: implement ChangeDeployStatusProject command and handler for updating project deployment status 2025-12-30 11:10:40 +03:30
836e721b6f feat: refactor institution contract creation classes and endpoints 2025-12-30 10:38:07 +03:30
8fca1f3a91 feat: add institution contract creation inquiry functionality 2025-12-29 22:19:16 +03:30
2feca1f7f8 add creation 2025-12-29 19:31:18 +03:30
4e9cecbb74 Merge branch 'Feature/Excel/instiutition-contract' 2025-12-29 17:21:58 +03:30
adf297455f feat: enhance Excel export for institution contracts by removing row number and adding dynamic physical contract status 2025-12-29 17:20:07 +03:30
1d656a590f Merge remote-tracking branch 'origin/master' 2025-12-29 16:26:08 +03:30
SamSys
a33d7c019c launchsettnig 2025-12-29 15:08:53 +03:30
SamSys
d62b5ca155 Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-29 14:37:47 +03:30
SamSys
18a4334d8a change WarningMessage on InsuranceList Edit 2025-12-29 14:36:03 +03:30
84416fe1f5 feat: add validation for in-person contract approval and suppress documentation warnings 2025-12-29 13:29:32 +03:30
d855684cd7 add: implement AutoUpdateDeployStatusCommand for automatic deployment status updates 2025-12-29 12:16:51 +03:30
9e5e8d8e5d refactor: improve code formatting and structure in ProjectController 2025-12-29 11:45:32 +03:30
9eefdd8fd1 add: implement GetProjectDeployBoardDetails endpoint for retrieving project board details 2025-12-29 10:27:23 +03:30
2159901614 add: implement ProjectDeployBoardDetailsQuery and its handler with validation for project phase details 2025-12-27 19:42:13 +03:30
7ce7854091 add: include DeployStatus in ProjectDeployBoardListItem for deployment status tracking 2025-12-27 16:26:07 +03:30
4c638cbdae add: implement DeployStatus and IsArchived properties in ProjectPhase, and create ProjectDeployBoardListQueryHandler for project deployment management 2025-12-27 13:59:37 +03:30
39a5918a11 add: implement ProjectDeployBoardListQueryHandler and initialize GetProjectsListQueryHandler structure 2025-12-24 18:55:01 +03:30
b9e271de1a fix: update OccurredOn property to use DateTime.Now instead of DateTime.UtcNow in event records 2025-12-23 15:00:18 +03:30
e661bc2dcb add: enhance ProjectBoardListQueryHandler and ProjectPhase to manage task section statuses and deployment states 2025-12-23 14:52:41 +03:30
69 changed files with 5015 additions and 1277 deletions

View File

@@ -64,6 +64,7 @@ public interface ISmsService
/// <summary>
/// پیامک مسدودی طرف حساب
/// قراردادهای قدیم
/// </summary>
/// <param name="number"></param>
/// <param name="fullname"></param>
@@ -74,6 +75,19 @@ public interface ISmsService
/// <returns></returns>
Task<(byte status, string message, int messaeId, bool isSucceded)> BlockMessage(string number, string fullname, string amount, string accountType, string id, string aprove);
/// <summary>
/// پیامک مسدودی طرف حساب
/// قرارداد های جدید
/// </summary>
/// <param name="number"></param>
/// <param name="fullname"></param>
/// <param name="amount"></param>
/// <param name="code1"></param>
/// <param name="code2"></param>
/// <returns></returns>
Task<(byte status, string message, int messaeId, bool isSucceded)> BlockMessageForElectronicContract(string number,
string fullname,
string amount, string code1, string code2);
#endregion
#region AlarmMessage

View File

@@ -34,7 +34,7 @@ public interface IAccountApplication
OperationResult DeActive(long id);
OperationResult DirectLogin(long id);
AccountLeftWorkViewModel WorkshopList(long accountId);
// AccountLeftWorkViewModel WorkshopList(long accountId);
OperationResult SaveWorkshopAccount(
List<WorkshopAccountlistViewModel> workshopAccountList,
string startDate,
@@ -75,7 +75,6 @@ public interface IAccountApplication
void CameraLogin(CameraLoginRequest request);
Task<GetPmUserDto> GetPmUserAsync(long accountId);
}
public class CameraLoginRequest

View File

@@ -745,25 +745,25 @@ public class AccountApplication : IAccountApplication
}
public AccountLeftWorkViewModel WorkshopList(long accountId)
{
string fullname = this._accountRepository.GetById(accountId).Fullname;
List<WorkshopAccountlistViewModel> source = _accountLeftworkRepository.WorkshopList(accountId);
List<long> userWorkshopIds = source.Select(x => x.WorkshopId).ToList();
List<WorkshopSelectList> allWorkshops = this._accountLeftworkRepository.GetAllWorkshops();
List<AccountViewModel> accountSelectList = this._accountRepository.GetAdminAccountSelectList();
(string StartWorkFa, string LeftWorkFa) byAccountId = this._accountLeftworkRepository.GetByAccountId(accountId);
return new AccountLeftWorkViewModel()
{
AccountId = accountId,
AccountFullName = fullname,
StartDateFa = byAccountId.StartWorkFa,
LeftDateFa = byAccountId.LeftWorkFa,
WorkshopAccountlist = source,
WorkshopSelectList = new SelectList(allWorkshops.Where(x => !userWorkshopIds.Contains(x.Id)), "Id", "WorkshopFullName"),
AccountSelectList = new SelectList(accountSelectList, "Id", "Fullname")
};
}
// public AccountLeftWorkViewModel WorkshopList(long accountId)
// {
// string fullname = this._accountRepository.GetById(accountId).Fullname;
// List<WorkshopAccountlistViewModel> source = _accountLeftworkRepository.WorkshopList(accountId);
// List<long> userWorkshopIds = source.Select(x => x.WorkshopId).ToList();
// List<WorkshopSelectList> allWorkshops = this._accountLeftworkRepository.GetAllWorkshops();
// List<AccountViewModel> accountSelectList = this._accountRepository.GetAdminAccountSelectList();
// (string StartWorkFa, string LeftWorkFa) byAccountId = this._accountLeftworkRepository.GetByAccountId(accountId);
// return new AccountLeftWorkViewModel()
// {
// AccountId = accountId,
// AccountFullName = fullname,
// StartDateFa = byAccountId.StartWorkFa,
// LeftDateFa = byAccountId.LeftWorkFa,
// WorkshopAccountlist = source,
// WorkshopSelectList = new SelectList(allWorkshops.Where(x => !userWorkshopIds.Contains(x.Id)), "Id", "WorkshopFullName"),
// AccountSelectList = new SelectList(accountSelectList, "Id", "Fullname")
// };
// }
public OperationResult SaveWorkshopAccount(
List<WorkshopAccountlistViewModel> workshopAccountList,
@@ -1024,4 +1024,5 @@ public class AccountApplication : IAccountApplication
{
return await _pmUserQueryService.GetPmUserDataByAccountId(accountId);
}
}

View File

@@ -10,7 +10,7 @@ public interface IAccountLeftworkRepository : IRepository<long, AccountLeftWork>
{
(string StartWorkFa, string LeftWorkFa) GetByAccountId(long accountId);
List<WorkshopAccountlistViewModel> WorkshopList(long accountId);
List<WorkshopSelectList> GetAllWorkshops();
// List<WorkshopSelectList> GetAllWorkshops();
OperationResult CopyWorkshopToNewAccount(long currentAccountId, long newAccountId);

View File

@@ -18,14 +18,13 @@ public class AccountLeftworkRepository : RepositoryBase<long, AccountLeftWork>,
{
private readonly AccountContext _accountContext;
private readonly IWorkshopAccountRepository _workshopAccountRepository;
private readonly IWorkshopApplication _workshopApplication;
public AccountLeftworkRepository(AccountContext accountContext, IWorkshopAccountRepository workshopAccountRepository, IWorkshopApplication workshopApplication) : base(accountContext)
public AccountLeftworkRepository(AccountContext accountContext,
IWorkshopAccountRepository workshopAccountRepository) : base(accountContext)
{
_accountContext = accountContext;
_workshopAccountRepository = workshopAccountRepository;
_workshopApplication = workshopApplication;
}
}
public (string StartWorkFa, string LeftWorkFa) GetByAccountId(long accountId)
{
@@ -58,14 +57,14 @@ public class AccountLeftworkRepository : RepositoryBase<long, AccountLeftWork>,
}).ToList();
}
public List<WorkshopSelectList> GetAllWorkshops()
{
return this._workshopApplication.GetWorkshopAll().Select(x => new WorkshopSelectList()
{
Id = x.Id,
WorkshopFullName = x.WorkshopFullName
}).ToList();
}
// public List<WorkshopSelectList> GetAllWorkshops()
// {
// return this._workshopApplication.GetWorkshopAll().Select(x => new WorkshopSelectList()
// {
// Id = x.Id,
// WorkshopFullName = x.WorkshopFullName
// }).ToList();
// }
public OperationResult CopyWorkshopToNewAccount(long currentAccountId, long newAccountId)
{

View File

@@ -57,6 +57,18 @@ public class JobSchedulerRegistrator
() => SendInstitutionContractConfirmSms(),
"*/1 * * * *" // هر 1 دقیقه یکبار چک کن
);
RecurringJob.AddOrUpdate(
"InstitutionContract.SendWarningSms",
() => SendWarningSms(),
"*/1 * * * *" // هر 1 دقیقه یکبار چک کن
);
RecurringJob.AddOrUpdate(
"InstitutionContract.SendLegalActionSms",
() => SendLegalActionSms(),
"*/1 * * * *" // هر 1 دقیقه یکبار چک کن
);
}
@@ -170,4 +182,22 @@ public class JobSchedulerRegistrator
await _institutionContractRepository.SendInstitutionContractConfirmSmsTask();
}
/// <summary>
/// ارسال پیامک هشدار
/// </summary>
/// <returns></returns>
[DisableConcurrentExecution(timeoutInSeconds: 100)]
public async System.Threading.Tasks.Task SendWarningSms()
{
_logger.LogInformation("SendWarningSms job run");
await _institutionContractRepository.SendWarningSmsTask();
}
[DisableConcurrentExecution(timeoutInSeconds: 100)]
public async System.Threading.Tasks.Task SendLegalActionSms()
{
_logger.LogInformation("SendWarningSms job run");
await _institutionContractRepository.SendLegalActionSmsTask();
}
}

View File

@@ -1,4 +1,5 @@
using CompanyManagment.App.Contracts.PersonalContractingParty;
using System;
using CompanyManagment.App.Contracts.PersonalContractingParty;
using System.Collections.Generic;
using _0_Framework.Application;
using _0_Framework.Domain;
@@ -32,7 +33,9 @@ public interface IPersonalContractingPartyRepository :IRepository<long, Personal
List<PersonalContractingPartyViewModel> SearchForMain(PersonalContractingPartySearchModel searchModel2);
OperationResult DeletePersonalContractingParties(long id);
bool GetHasContract(long id);
[Obsolete("از متدهای async استفاده کنید")]
OperationResult DeActiveAll(long id);
[Obsolete("از متدهای async استفاده کنید")]
OperationResult ActiveAll(long id);
#endregion
@@ -76,4 +79,9 @@ public interface IPersonalContractingPartyRepository :IRepository<long, Personal
Task<PersonalContractingParty> GetByNationalCode(string nationalCode);
Task<PersonalContractingParty> GetByNationalId(string registerId);
Task<OperationResult> DeActiveAllAsync(long id);
Task<OperationResult> ActiveAllAsync(long id);
}

View File

@@ -10,4 +10,6 @@ public interface IFinancialInvoiceRepository : IRepository<long, FinancialInvoic
EditFinancialInvoice GetDetails(long id);
List<FinancialInvoiceViewModel> Search(FinancialInvoiceSearchModel searchModel);
Task<FinancialInvoice> GetUnPaidByEntityId(long entityId, FinancialInvoiceItemType financialInvoiceItemType);
Task<FinancialInvoice> GetUnPaidFinancialInvoiceByContractingPartyIdAndAmount(long contractingPartyId,
double amount);
}

View File

@@ -13,7 +13,7 @@ namespace Company.Domain.InstitutionContractAgg;
public interface IInstitutionContractRepository : IRepository<long, InstitutionContract>
{
EditInstitutionContract GetDetails(long id);
EditInstitutionContract GetFirstContract(long contractingPartyId, string typeOfContract);
List<InstitutionContractViewModel> InstitutionContractsWithoutAccount();
@@ -56,9 +56,13 @@ public interface IInstitutionContractRepository : IRepository<long, InstitutionC
void UpdateStatusIfNeeded(long institutionContractId);
Task<GetInstitutionVerificationDetailsViewModel> GetVerificationDetails(Guid id);
Task<InstitutionContract> GetByPublicIdAsync(Guid id);
InstitutionContractDiscountResponse CalculateDiscount(InstitutionContractSetDiscountRequest request,string contractStart = null);
InstitutionContractDiscountResponse CalculateDiscount(InstitutionContractSetDiscountRequest request, string contractStart = null);
InstitutionContractDiscountResponse ResetDiscountCreate(InstitutionContractResetDiscountForCreateRequest request);
#region Creation
#endregion
#region Extension
@@ -69,19 +73,19 @@ public interface IInstitutionContractRepository : IRepository<long, InstitutionC
Task<InstitutionContractDiscountResponse> SetDiscountForExtension(
InstitutionContractSetDiscountForExtensionRequest request);
Task<InstitutionContractDiscountResponse> ResetDiscountForExtension(InstitutionContractResetDiscountForExtensionRequest request);
Task<OperationResult> ExtensionComplete(InstitutionContractExtensionCompleteRequest request);
#endregion
#region Upgrade(Amendment)
Task<InstitutionContractAmendmentWorkshopsResponse> GetAmendmentWorkshops(long institutionContractId);
Task<InsitutionContractAmendmentPaymentResponse> GetAmendmentPaymentDetails(InsitutionContractAmendmentPaymentRequest request);
Task<InstitutionContractAmendmentWorkshopsResponse> GetAmendmentWorkshops(long institutionContractId);
Task<InsitutionContractAmendmentPaymentResponse> GetAmendmentPaymentDetails(InsitutionContractAmendmentPaymentRequest request);
Task<InsertAmendmentTempWorkshopResponse> InsertAmendmentTempWorkshops(InstitutionContractAmendmentTempWorkshopViewModel request);
Task RemoveAmendmentWorkshops(Guid workshopTempId);
#endregion
Task<InsertAmendmentTempWorkshopResponse> InsertAmendmentTempWorkshops(InstitutionContractAmendmentTempWorkshopViewModel request);
Task RemoveAmendmentWorkshops(Guid workshopTempId);
#endregion
Task<List<InstitutionContractSelectListViewModel>> GetInstitutionContractSelectList(string search, string selected);
Task<List<InstitutionContractPrintViewModel>> PrintAllAsync(List<long> ids);
@@ -156,8 +160,35 @@ public interface IInstitutionContractRepository : IRepository<long, InstitutionC
Task CreateTransactionForInstitutionContracts(DateTime endOfMonthGr, string endOfMonthFa, string description);
#endregion
#region WarningSms
/// <summary>
/// پیامک های هشدار
/// </summary>
/// <returns></returns>
Task SendWarningSmsTask();
#endregion
#region legalAction
/// <summary>
/// پیامک اقدام قضائی
/// </summary>
/// <returns></returns>
Task SendLegalActionSmsTask();
#endregion
Task<long> GetIdByInstallmentId(long installmentId);
Task<InstitutionContract> GetPreviousContract(long currentInstitutionContractId);
Task<InstitutionContractCreationInquiryResult> CreationInquiry(InstitutionContractCreationInquiryRequest request);
Task<InstitutionContractCreationWorkshopsResponse> GetCreationWorkshops(InstitutionContractCreationWorkshopsRequest request);
Task<InstitutionContractCreationPlanResponse> GetCreationInstitutionPlan(InstitutionContractCreationPlanRequest request);
Task<InstitutionContractCreationPaymentResponse> GetCreationPaymentMethod(InstitutionContractCreationPaymentRequest request);
Task<InstitutionContractDiscountResponse> SetDiscountForCreation(InstitutionContractSetDiscountForCreationRequest request);
Task<InstitutionContractDiscountResponse> ResetDiscountForCreation(InstitutionContractResetDiscountForExtensionRequest request);
Task<OperationResult> CreationComplete(InstitutionContractExtensionCompleteRequest request);
Task<InstitutionContract> GetIncludeInstallments(long id);
}

View File

@@ -23,6 +23,8 @@ public class InstitutionContractWorkshopGroup : EntityBase
!InitialWorkshops.Cast<InstitutionContractWorkshopBase>()
.SequenceEqual(CurrentWorkshops.Cast<InstitutionContractWorkshopBase>());
public bool IsInPersonContract => InitialWorkshops.Any(x => x.Services.ContractInPerson);
public InstitutionContractWorkshopGroup(long institutionContractId,
List<InstitutionContractWorkshopInitial> initialDetails)
{

View File

@@ -0,0 +1,340 @@
using System;
using System.Collections.Generic;
using _0_Framework.Application;
using _0_Framework.Application.Enums;
using CompanyManagment.App.Contracts.InstitutionContract;
using CompanyManagment.App.Contracts.InstitutionContractContactinfo;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
namespace Company.Domain.InstitutionContractCreationTempAgg;
public class InstitutionContractCreationTemp
{
public InstitutionContractCreationTemp()
{
Id = Guid.NewGuid();
}
[BsonId] // Specifies this field as the _id in MongoDB
[BsonRepresentation(BsonType.String)] // Ensures the GUID is stored as a string
public Guid Id { get; set; }
/// <summary>
/// نوع حقوقی طرف قرارداد (حقیقی یا حقوقی)
/// </summary>
public LegalType ContractingPartyLegalType { get; set; }
/// <summary>
/// اطلاعات شخص حقیقی
/// </summary>
public InstitutionContractCreationTempRealParty RealParty { get; set; }
/// <summary>
/// اطلاعات شخص حقوقی
/// </summary>
public InstitutionContractCreationTempLegalParty LegalParty { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string Province { get; set; }
public List<EditContactInfo> ContactInfos { get; set; }
public long RepresentativeId { get; set; }
public List<InstitutionContractCreationTempWorkshop> Workshops { get; set; }
public InstitutionContractCreationPlanDetail OneMonth { get; set; }
public InstitutionContractCreationPlanDetail ThreeMonths { get; set; }
public InstitutionContractCreationPlanDetail SixMonths { get; set; }
public InstitutionContractCreationPlanDetail TwelveMonths { get; set; }
public InstitutionContractPaymentMonthlyViewModel MonthlyPayment { get; set; }
public InstitutionContractPaymentOneTimeViewModel OneTimePayment { get; set; }
public bool HasContractInPerson { get; set; }
public InstitutionContractDuration? Duration { get; set; }
public void SetContractingPartyInfo(LegalType legalType,
InstitutionContractCreationTempRealParty realParty,
InstitutionContractCreationTempLegalParty legalParty)
{
ContractingPartyLegalType = legalType;
RealParty = realParty;
LegalParty = legalParty;
}
public void SetWorkshopsAndPlanAmounts(List<InstitutionContractCreationTempWorkshop> workshops,
InstitutionContractCreationPlanDetail oneMonth,
InstitutionContractCreationPlanDetail threeMonth, InstitutionContractCreationPlanDetail sixMonth,
InstitutionContractCreationPlanDetail twelveMonth, bool hasContractInPerson)
{
Workshops = workshops;
OneMonth = oneMonth;
ThreeMonths = threeMonth;
SixMonths = sixMonth;
TwelveMonths = twelveMonth;
HasContractInPerson = hasContractInPerson;
}
public void SetAmountAndDuration(InstitutionContractDuration duration,InstitutionContractPaymentMonthlyViewModel monthly,
InstitutionContractPaymentOneTimeViewModel oneTime)
{
Duration = duration;
MonthlyPayment = monthly;
OneTimePayment = oneTime;
}
public void SetContractingPartyContactInfo(string address, string city, string province, List<EditContactInfo> requestContactInfos,long representativeId)
{
Address = address;
City = city;
Province = province;
ContactInfos = requestContactInfos;
RepresentativeId = representativeId;
}
}
public class InstitutionContractCreationTempLegalParty
{
/// <summary>
/// آیدی طرف حساب در صورتی که از قبل ایجاد شده باشد
/// </summary>
public long Id { get; set; }
/// <summary>
/// نام شرکت
/// </summary>
public string CompanyName { get; set; }
/// <summary>
/// شماره ثبت
/// </summary>
public string RegisterId { get; set; }
/// <summary>
/// شناسه ملی شرکت
/// </summary>
public string NationalId { get; set; }
/// <summary>
/// شماره تلفن شرکت
/// </summary>
public string PhoneNumber { get; set; }
/// <summary>
/// شناسه موقت طرف قرارداد
/// </summary>
public long ContractingPartyTempId { get; set; }
/// <summary>
/// کد ملی نماینده قانونی
/// </summary>
public string NationalCode { get; set; }
/// <summary>
/// تاریخ تولد نماینده قانونی فارسی
/// </summary>
public string BirthDateFa { get; set; }
/// <summary>
/// نام نماینده قانونی
/// </summary>
public string FName { get; set; }
/// <summary>
/// نام خانوادگی نماینده قانونی
/// </summary>
public string LName { get; set; }
/// <summary>
/// نام پدر نماینده قانونی
/// </summary>
public string FatherName { get; set; }
/// <summary>
/// شماره شناسنامه نماینده قانونی
/// </summary>
public string IdNumber { get; set; }
/// <summary>
/// وضعیت احراز هویت نماینده قانونی
/// </summary>
public bool IsAuth { get; set; }
/// <summary>
/// سمت نماینده قانونی در شرکت
/// </summary>
public string Position { get; set; }
/// <summary>
/// جنسیت نماینده قانونی
/// </summary>
public Gender Gender { get; set; }
public string IdNumberSeri { get; set; }
public string IdNumberSerial { get; set; }
}
public class InstitutionContractCreationTempRealParty
{
/// <summary>
/// آیدی طرف حساب در صورتی که از قبل ایجاد شده باشد
/// </summary>
public long Id { get; set; }
/// <summary>
/// کد ملی
/// </summary>
public string NationalCode { get; set; }
/// <summary>
/// تاریخ تولد فارسی
/// </summary>
public string BirthDateFa { get; set; }
/// <summary>
/// شماره تلفن
/// </summary>
public string PhoneNumber { get; set; }
/// <summary>
/// وضعیت احراز هویت
/// </summary>
public bool IsAuth { get; set; }
/// <summary>
/// نام
/// </summary>
public string FName { get; set; }
/// <summary>
/// نام خانوادگی
/// </summary>
public string LName { get; set; }
/// <summary>
/// نام پدر
/// </summary>
public string FatherName { get; set; }
/// <summary>
/// شماره شناسنامه
/// </summary>
public string IdNumber { get; set; }
/// <summary>
/// شناسه موقت طرف قرارداد
/// </summary>
public long ContractingPartyTempId { get; set; }
/// <summary>
/// جنسیت
/// </summary>
public Gender Gender { get; set; }
public string IdNumberSeri { get; set; }
public string IdNumberSerial { get; set; }
}
public class InstitutionContractCreationTempPlan
{
public InstitutionContractCreationTempPlan(string contractStart, string contractEnd,
string oneMonthPaymentDiscounted, string oneMonthDiscount, string oneMonthOriginalPayment,
string totalPayment, string dailyCompensation, string obligation)
{
ContractStart = contractStart;
ContractEnd = contractEnd;
OneMonthPaymentDiscounted = oneMonthPaymentDiscounted;
OneMonthDiscount = oneMonthDiscount;
OneMonthOriginalPayment = oneMonthOriginalPayment;
TotalPayment = totalPayment;
DailyCompensation = dailyCompensation;
Obligation = obligation;
}
public string ContractStart { get; set; }
public string ContractEnd { get; set; }
public string OneMonthPaymentDiscounted { get; set; }
public string OneMonthDiscount { get; set; }
public string OneMonthOriginalPayment { get; set; }
public string TotalPayment { get; set; }
public string DailyCompensation { get; set; }
public string Obligation { get; set; }
}
public class InstitutionContractCreationTempWorkshop
{
public InstitutionContractCreationTempWorkshop(string workshopName, int countPerson, bool contractAndCheckout, bool contractAndCheckoutInPerson,
bool insurance, bool insuranceInPerson,
bool rollCall,bool rollCallInPerson, bool customizeCheckout,double price,long workshopId)
{
WorkshopName = workshopName;
CountPerson = countPerson;
ContractAndCheckout = contractAndCheckout;
Insurance = insurance;
RollCall = rollCall;
CustomizeCheckout = customizeCheckout;
ContractAndCheckoutInPerson = contractAndCheckoutInPerson;
InsuranceInPerson = insuranceInPerson;
RollCallInPerson = rollCallInPerson;
Price = price;
WorkshopId = workshopId;
}
public long WorkshopId { get; set; }
/// <summary>
/// نام کارگاه
/// </summary>
public string WorkshopName { get; private set; }
/// <summary>
/// تعداد پرسنل
/// </summary>
public int CountPerson { get; private set; }
#region ServiceSelection
/// <summary>
/// قرارداد و تصفیه
/// </summary>
public bool ContractAndCheckout { get; private set; }
/// <summary>
/// بیمه
/// </summary>
public bool Insurance { get; private set; }
/// <summary>
/// حضورغباب
/// </summary>
public bool RollCall { get; private set; }
public bool RollCallInPerson { get; set; }
/// <summary>
/// فیش غیر رسمی
/// </summary>
public bool CustomizeCheckout { get;private set; }
/// <summary>
/// خدمات حضوری قرداد و تصفیه
/// </summary>
public bool ContractAndCheckoutInPerson { get; private set; }
/// <summary>
/// خدمات حضوری بیمه
/// </summary>
public bool InsuranceInPerson { get; private set; }
public double Price{ get; set; }
#endregion
}

View File

@@ -38,7 +38,6 @@ public class ExcelColumnConfig
// فعلاً تمام ستون‌ها فعال هستند
VisibleColumns = new List<ExcelColumnType>
{
ExcelColumnType.RowNumber,
ExcelColumnType.PhysicalContract,
ExcelColumnType.ContractNo,
ExcelColumnType.Representative,
@@ -286,11 +285,20 @@ public class InstitutionContractExcelGenerator
switch (columnType)
{
case ExcelColumnType.RowNumber:
// TODO: مقدار ردیف رو از user input دریافت کن
break;
case ExcelColumnType.PhysicalContract:
// TODO: مقدار قرارداد فیزیکی رو دریافت کن
var physicalText = contract.IsOldContract
? (contract.HasSigniture ? "موجود" : "ناموجود")
: (contract.IsInPersonContract ? "الکترونیکی حضوری" : "الکترونیکی غیر حضوری");
cell.Value = physicalText;
cell.Style.Font.Bold = true;
cell.Style.Font.Color.SetColor(physicalText switch
{
"موجود" => Color.Green,
"ناموجود" => Color.Red,
"الکترونیکی حضوری" => Color.Purple,
_ => Color.Blue
});
break;
case ExcelColumnType.ContractNo:
cell.Value = contract.ContractNo;

View File

@@ -3,6 +3,7 @@
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
<ItemGroup>

View File

@@ -8,7 +8,7 @@ public class CreateFinancialInvoice
public double Amount { get; set; }
public long ContractingPartyId { get; set; }
public string Description { get; set; }
public List<CreateFinancialInvoiceItem>? Items { get; set; }
public List<CreateFinancialInvoiceItem> Items { get; set; }
}
public class CreateFinancialInvoiceItem

View File

@@ -10,7 +10,8 @@ public class EditFinancialInvoice
public double Amount { get; set; }
public FinancialInvoiceStatus Status { get; set; }
public List<EditFinancialInvoiceItem>? Items { get; set; }
public List<EditFinancialInvoiceItem> Items { get; set; }
public long ContractingPartyId { get; set; }
}
public class EditFinancialInvoiceItem

View File

@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CompanyManagment.App.Contracts.SepehrPaymentGateway;
namespace CompanyManagment.App.Contracts.FinancialStatment;
@@ -62,7 +63,17 @@ public interface IFinancialStatmentApplication
/// <returns></returns>
Task<FinancialStatmentDetailsByContractingPartyViewModel> GetDetailsByContractingParty(long contractingPartyId,
FinancialStatementSearchModel searchModel);
/// <summary>
/// پردازش شارژ حساب از طریق درگاه پرداخت سپهر
/// </summary>
/// <param name="request"></param>
/// <param name="gateWayCallBackUrl">مسیر برگشت درگاه پرداخت</param>
///
Task<OperationResult<CreateSepehrPaymentGatewayResponse>> CreatePaymentGateWayAndCreateInvoice(
CreateFinancialPayRequest request, string gateWayCallBackUrl);
}
public record CreateFinancialPayRequest(long Id, string BaseUrl);
public class FinancialStatmentDetailsByContractingPartyViewModel
{

View File

@@ -5,8 +5,10 @@ using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using _0_Framework.Application;
using _0_Framework.Application.Enums;
using _0_Framework.Application.Sms;
using CompanyManagment.App.Contracts.Checkout;
using CompanyManagment.App.Contracts.InstitutionContractContactinfo;
using CompanyManagment.App.Contracts.TemporaryClientRegistration;
using CompanyManagment.App.Contracts.Workshop;
using CompanyManagment.App.Contracts.WorkshopPlan;
@@ -26,21 +28,21 @@ public interface IInstitutionContractApplication
/// <param name="command">اطلاعات قرارداد جدید</param>
/// <returns>نتیجه عملیات</returns>
OperationResult Create(CreateInstitutionContract command);
/// <summary>
/// تمدید قرارداد موجود
/// </summary>
/// <param name="command">اطلاعات قرارداد برای تمدید</param>
/// <returns>نتیجه عملیات</returns>
OperationResult Extension(CreateInstitutionContract command);
/// <summary>
/// ویرایش قرارداد موجود
/// </summary>
/// <param name="command">اطلاعات جدید قرارداد</param>
/// <returns>نتیجه عملیات</returns>
OperationResult Edit(EditInstitutionContract command);
/// <summary>
/// دریافت جزئیات قرارداد برای ویرایش
/// </summary>
@@ -54,7 +56,7 @@ public interface IInstitutionContractApplication
/// <param name="searchModel">مدل جستجو</param>
/// <returns>لیست قراردادها</returns>
List<InstitutionContractViewModel> Search(InstitutionContractSearchModel searchModel);
/// <summary>
/// جستجوی جدید در قراردادها
/// </summary>
@@ -76,7 +78,7 @@ public interface IInstitutionContractApplication
/// <param name="id">لیست شناسه قراردادها</param>
/// <returns>لیست قراردادها برای چاپ</returns>
List<InstitutionContractViewModel> PrintAll(List<long> id);
[Obsolete("استفاده نشود، از متد غیرهمزمان استفاده شود")]
/// <summary>
@@ -146,7 +148,7 @@ public interface IInstitutionContractApplication
/// <param name="id">شناسه قرارداد</param>
/// <returns>نتیجه عملیات</returns>
OperationResult UnSign(long id);
/// <summary>
/// ایجاد حساب کاربری برای طرف قرارداد
/// </summary>
@@ -191,32 +193,56 @@ public interface IInstitutionContractApplication
/// <param name="command"></param>
/// <returns></returns>
Task<OperationResult> EditAsync(EditInstitutionContractRequest command);
/// <summary>
/// دریافت لیست طرف حساب هایی که ثبت نام آنها تکمیل شده
/// جهت نمایش در کارپوشه
/// </summary>
/// <returns></returns>
Task<List<RegistrationWorkflowMainListViewModel>> RegistrationWorkflowMainList();
/// <summary>
/// دریافت آیتم های کارپوشه ثبت نام
/// </summary>
/// <param name="institutionContractId"></param>
/// <returns></returns>
Task<List<RegistrationWorkflowItemsViewModel>> RegistrationWorkflowItems(long institutionContractId);
#endregion
Task<GetInstitutionVerificationDetailsViewModel> GetVerificationDetails(Guid id);
Task<OperationResult<OtpResultViewModel>> SendVerifyOtp(Guid id);
Task<OperationResult<string>> VerifyOtpAndMakeGateway(Guid publicId, string code, string callbackUrl);
Task<InstitutionContractWorkshopDetailViewModel> GetWorkshopInitialDetails(long workshopDetailsId);
InstitutionContractDiscountResponse CalculateDiscount(InstitutionContractSetDiscountRequest request);
InstitutionContractDiscountResponse ResetDiscountCreate(InstitutionContractResetDiscountForCreateRequest request);
#region Creation
/// <summary>
/// تب ایجاد قرارداد مؤسسه - احراز هویت
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
Task<InstitutionContractCreationInquiryResult> CreationInquiry(InstitutionContractCreationInquiryRequest request);
/// <summary>
/// تب ایجاد قرارداد مؤسسه -مشخصات طرف قرارداد و انتخاب کارگاه ها
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
Task<InstitutionContractCreationWorkshopsResponse> GetCreationWorkshops(
InstitutionContractCreationWorkshopsRequest request);
/// <summary>
/// تب ایجاد قرارداد مؤسسه - مالی
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
Task<InstitutionContractCreationPlanResponse> GetCreationInstitutionPlan(InstitutionContractCreationPlanRequest request);
#endregion
#region Extension
Task<InstitutionContractExtensionInquiryResult> GetExtensionInquiry(long previousContractId);
@@ -229,25 +255,31 @@ public interface IInstitutionContractApplication
Task<InstitutionContractExtensionPaymentResponse> GetExtensionPaymentMethod(
InstitutionContractExtensionPaymentRequest request);
Task<InstitutionContractDiscountResponse> SetDiscountForExtension(
InstitutionContractSetDiscountForExtensionRequest request);
Task<InstitutionContractDiscountResponse> ResetDiscountForExtension(
InstitutionContractResetDiscountForExtensionRequest request);
Task<OperationResult> ExtensionComplete(InstitutionContractExtensionCompleteRequest request);
Task<List<InstitutionContractSelectListViewModel>> GetInstitutionContractSelectList(string search,string selected);
Task<List<InstitutionContractSelectListViewModel>> GetInstitutionContractSelectList(string search, string selected);
#endregion
#region Upgrade (Amendment)
Task<InstitutionContractAmendmentWorkshopsResponse> GetAmendmentWorkshops(long institutionContractId);
Task<InsertAmendmentTempWorkshopResponse> InsertAmendmentTempWorkshops(InstitutionContractAmendmentTempWorkshopViewModel request);
Task<InsertAmendmentTempWorkshopResponse> InsertAmendmentTempWorkshops(
InstitutionContractAmendmentTempWorkshopViewModel request);
Task RemoveAmendmentWorkshops(Guid workshopTempId);
Task<InsitutionContractAmendmentPaymentResponse> GetAmendmentPaymentDetails(InsitutionContractAmendmentPaymentRequest request);
Task<InsitutionContractAmendmentPaymentResponse> GetAmendmentPaymentDetails(
InsitutionContractAmendmentPaymentRequest request);
#endregion
Task<OperationResult> ResendVerifyLink(long institutionContractId);
@@ -259,8 +291,9 @@ public interface IInstitutionContractApplication
/// <returns></returns>
Task<InstitutionContractPrintViewModel> PrintOneAsync(long id);
Task<OperationResult> SetPendingWorkflow(long entityId,InstitutionContractSigningType signingType);
Task<OperationResult> SetPendingWorkflow(long entityId, InstitutionContractSigningType signingType);
Task<long> GetIdByInstallmentId(long installmentId);
/// <summary>
/// تایید قرارداد مالی به صورت دستی
/// </summary>
@@ -268,4 +301,42 @@ public interface IInstitutionContractApplication
/// <returns></returns>
Task<OperationResult> VerifyInstitutionContractManually(long institutionContractId);
Task<InstitutionContractCreationPaymentResponse> GetCreationPaymentMethod(InstitutionContractCreationPaymentRequest request);
Task<InstitutionContractDiscountResponse> SetDiscountForCreation(InstitutionContractSetDiscountForCreationRequest request);
Task<InstitutionContractDiscountResponse> ResetDiscountForCreation(InstitutionContractResetDiscountForExtensionRequest request);
Task<OperationResult> CreationComplete(InstitutionContractExtensionCompleteRequest request);
}
public class CreationSetContractingPartyResponse
{
public long RepresentativeId { get; set; }
}
public class InstitutionContractCreationWorkshopsResponse
{
public List<WorkshopTempViewModel> WorkshopTemps { get; set; }
public string TotalAmount { get; set; }
}
public class InstitutionContractCreationWorkshopsRequest
{
public Guid TempId { get; set; }
public string City { get; set; }
public string Province { get; set; }
public string Address { get; set; }
public List<EditContactInfo> ContactInfos { get; set; }
/// <summary>
/// اطلاعات شخص حقیقی
/// </summary>
public CreateInstitutionContractRealPartyRequest RealParty { get; set; }
/// <summary>
/// اطلاعات شخص حقوقی
/// </summary>
public CreateInstitutionContractLegalPartyRequest LegalParty { get; set; }
public LegalType LegalType { get; set; }
public long RepresentativeId { get; set; }
}

View File

@@ -0,0 +1,11 @@
using _0_Framework.Application.Enums;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractCreationInquiryRequest
{
public string NationalCode { get; set; }
public string DateOfBirth { get; set; }
public string Mobile { get; set; }
public LegalType LegalType { get; set; }
}

View File

@@ -3,6 +3,13 @@ using System;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractExtensionCompleteRequest
{
public Guid TemporaryId { get; set; }
public bool IsInstallment { get; set; }
public long LawId { get; set; }
}
public class InstitutionContractCreationCompleteRequest
{
public Guid TemporaryId { get; set; }
public bool IsInstallment { get; set; }

View File

@@ -24,4 +24,21 @@ public class InstitutionContractExtensionInquiryResult
public string Province { get; set; }
public List<EditContactInfo> ContactInfoViewModels { get; set; }
public long RepresentativeId { get; set; }
}
public class InstitutionContractCreationInquiryResult
{
/// <summary>
/// اطلاعات شخص حقیقی
/// </summary>
public CreateInstitutionContractRealPartyRequest RealParty { get; set; }
/// <summary>
/// اطلاعات شخص حقوقی
/// </summary>
public CreateInstitutionContractLegalPartyRequest LegalParty { get; set; }
public LegalType LegalType { get; set; }
public Guid TempId { get; set; }
}

View File

@@ -3,6 +3,11 @@ using System;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractExtensionPaymentRequest
{
public InstitutionContractDuration Duration { get; set; }
public Guid TempId { get; set; }
}
public class InstitutionContractCreationPaymentRequest
{
public InstitutionContractDuration Duration { get; set; }
public Guid TempId { get; set; }

View File

@@ -5,4 +5,11 @@ public class InstitutionContractExtensionPaymentResponse
public InstitutionContractPaymentOneTimeViewModel OneTime { get; set; }
public InstitutionContractPaymentMonthlyViewModel Monthly { get; set; }
}
public class InstitutionContractCreationPaymentResponse
{
public InstitutionContractPaymentOneTimeViewModel OneTime { get; set; }
public InstitutionContractPaymentMonthlyViewModel Monthly { get; set; }
}

View File

@@ -5,6 +5,13 @@ using CompanyManagment.App.Contracts.TemporaryClientRegistration;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractExtensionPlanRequest
{
public List<WorkshopTempViewModel> WorkshopTemps { get; set; }
public string TotalAmount { get; set; }
public Guid TempId { get; set; }
}
public class InstitutionContractCreationPlanRequest
{
public List<WorkshopTempViewModel> WorkshopTemps { get; set; }
public string TotalAmount { get; set; }

View File

@@ -7,7 +7,18 @@ public class InstitutionContractExtensionPlanResponse
public InstitutionContractExtensionPlanDetail SixMonths { get; set; }
public InstitutionContractExtensionPlanDetail TwelveMonths { get; set; }
}
public class InstitutionContractExtensionPlanDetail
public class InstitutionContractExtensionPlanDetail:InstitutionContractCreationPlanDetail
{
}
public class InstitutionContractCreationPlanResponse
{
public InstitutionContractCreationPlanDetail OneMonth { get; set; }
public InstitutionContractCreationPlanDetail ThreeMonths { get; set; }
public InstitutionContractCreationPlanDetail SixMonths { get; set; }
public InstitutionContractCreationPlanDetail TwelveMonths { get; set; }
}
public class InstitutionContractCreationPlanDetail
{
public string ContractStart { get; set; }
public string ContractEnd { get; set; }

View File

@@ -33,5 +33,5 @@ public class InstitutionContractPaymentOneTimeViewModel
}
public class InstitutionContractPaymentMonthlyViewModel:InstitutionContractPaymentOneTimeViewModel
{
public List<MonthlyInstallment> Installments { get; set; }
public List<MonthlyInstallment> Installments { get; set; } = [];
}

View File

@@ -3,6 +3,11 @@ using System;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractResetDiscountForExtensionRequest
{
public Guid TempId { get; set; }
public bool IsInstallment { get; set; }
}
public class InstitutionContractResetCreationForExtensionRequest
{
public Guid TempId { get; set; }
public bool IsInstallment { get; set; }

View File

@@ -3,6 +3,13 @@ using System;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractSetDiscountForExtensionRequest
{
public Guid TempId { get; set; }
public int DiscountPercentage { get; set; }
public double TotalAmount { get; set; }
public bool IsInstallment { get; set; }
}
public class InstitutionContractSetDiscountForCreationRequest
{
public Guid TempId { get; set; }
public int DiscountPercentage { get; set; }

View File

@@ -94,4 +94,19 @@ public class BlockSmsListData
/// آی دی صورت حساب مالی
/// </summary>
public string AproveId { get; set; }
/// <summary>
/// آیا قرداد مالی قدیمی است
/// </summary>
public bool IsElectronicContract { get; set; }
/// <summary>
/// پابلیک آی دی بخش یک
/// </summary>
public string Code1 { get; set; }
/// <summary>
/// پابلیک آی دی بخش دو
/// </summary>
public string Code2 { get; set; }
}

View File

@@ -0,0 +1,21 @@
using _0_Framework.Application;
using System.Threading;
using System.Threading.Tasks;
namespace CompanyManagment.App.Contracts.PaymentCallback;
/// <summary>
/// رابط برای مدیریت Callback درگاه‌های پرداخت
/// </summary>
public interface IPaymentCallbackHandler
{
/// <summary>
/// تأیید و پردازش callback درگاه پرداخت سپهر
/// </summary>
/// <param name="command">داده‌های callback درگاه</param>
/// <param name="cancellationToken">توکن لغو عملیات</param>
/// <returns>نتیجه عملیات</returns>
Task<OperationResult> VerifySepehrPaymentCallback(VerifyPaymentCallbackCommand command,
CancellationToken cancellationToken = default);
}

View File

@@ -0,0 +1,53 @@
namespace CompanyManagment.App.Contracts.PaymentCallback;
/// <summary>
/// دستور تأیید callback درگاه پرداخت
/// </summary>
public class VerifyPaymentCallbackCommand
{
/// <summary>
/// کد پاسخ درگاه (0 = موفق)
/// </summary>
public int ResponseCode { get; set; }
/// <summary>
/// شناسه فاکتور/تراکنش
/// </summary>
public long InvoiceId { get; set; }
/// <summary>
/// داده‌های اضافی JSON
/// </summary>
public string Payload { get; set; }
/// <summary>
/// مبلغ تراکنش
/// </summary>
public long Amount { get; set; }
/// <summary>
/// شماره پیگیری درگاه
/// </summary>
public long TraceNumber { get; set; }
/// <summary>
/// شماره سند بانکی (RRN)
/// </summary>
public long Rrn { get; set; }
/// <summary>
/// رسید دیجیتال
/// </summary>
public string DigitalReceipt { get; set; }
/// <summary>
/// بانک صادر کننده کارت
/// </summary>
public string IssuerBank { get; set; }
/// <summary>
/// شماره کارت
/// </summary>
public string CardNumber { get; set; }
}

View File

@@ -132,4 +132,5 @@ public interface IPersonalContractingPartyApp
#endregion
Task<long> GetRepresentativeIdByNationalCode(string nationalCode);
}

View File

@@ -0,0 +1,22 @@
namespace CompanyManagment.App.Contracts.SepehrPaymentGateway;
/// <summary>
/// پاسخ ایجاد درگاه پرداخت سپهر
/// </summary>
public class CreateSepehrPaymentGatewayResponse
{
/// <summary>
/// توکن درگاه
/// </summary>
public string Token { get; set; }
/// <summary>
/// شناسه تراکنش
/// </summary>
public long TransactionId { get; set; }
/// <summary>
/// URL درگاه پرداخت
/// </summary>
public string PaymentUrl { get; set; }
}

View File

@@ -0,0 +1,32 @@
using _0_Framework.Application;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace CompanyManagment.App.Contracts.SepehrPaymentGateway;
/// <summary>
/// رابط برای سرویس مشترک ایجاد درگاه پرداخت سپهر
/// </summary>
public interface ISepehrPaymentGatewayService
{
/// <summary>
/// ایجاد درگاه پرداخت سپهر برای یک تراکنش
/// </summary>
/// <param name="amount">مبلغ</param>
/// <param name="contractingPartyId">شناسه طرف قرارداد</param>
/// <param name="frontCallbackUrl">آدرس بازگشتی به فرانت برای نمایش نتیجه</param>
/// <param name="gatewayCallbackUrl">آدرس بازگشتی درگاه پرداخت</param>
/// <param name="financialInvoiceId">شناسه فاکتور مالی (اختیاری) - این پارامتر مستقیماً به درگاه فرستاده می‌شود</param>
/// <param name="extraData">داده‌های اضافی سفارشی برای payload (اختیاری)</param>
/// <param name="cancellationToken">توکن لغو</param>
/// <returns>شامل Token درگاه یا OperationResult با خطا</returns>
Task<OperationResult<CreateSepehrPaymentGatewayResponse>> CreateSepehrPaymentGateway(
double amount,
long contractingPartyId,
long financialInvoiceId,
string gatewayCallbackUrl,
string frontCallbackUrl="https://client.gozareshgir.ir",
Dictionary<string, object> extraData = null,
CancellationToken cancellationToken = default);
}

View File

@@ -9,15 +9,13 @@ using CompanyManagment.EFCore;
namespace CompanyManagment.Application;
public class FinancialInvoiceApplication : RepositoryBase<long, FinancialInvoice>, IFinancialInvoiceApplication
public class FinancialInvoiceApplication : IFinancialInvoiceApplication
{
private readonly IFinancialInvoiceRepository _financialInvoiceRepository;
private readonly CompanyContext _context;
public FinancialInvoiceApplication(IFinancialInvoiceRepository financialInvoiceRepository, CompanyContext context) : base(context)
public FinancialInvoiceApplication(IFinancialInvoiceRepository financialInvoiceRepository)
{
_financialInvoiceRepository = financialInvoiceRepository;
_context = context;
}
public OperationResult Create(CreateFinancialInvoice command)
@@ -185,6 +183,7 @@ public class FinancialInvoiceApplication : RepositoryBase<long, FinancialInvoice
{
return _financialInvoiceRepository.Search(searchModel);
}
//public OperationResult Remove(long id)
//{

View File

@@ -3,9 +3,12 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using _0_Framework.Application;
using Company.Domain.ContarctingPartyAgg;
using Company.Domain.FinancialInvoiceAgg;
using Company.Domain.FinancialStatmentAgg;
using CompanyManagment.App.Contracts.FinancialInvoice;
using CompanyManagment.App.Contracts.FinancialStatment;
using CompanyManagment.App.Contracts.FinancilTransaction;
using CompanyManagment.App.Contracts.SepehrPaymentGateway;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Mvc;
@@ -16,12 +19,20 @@ public class FinancialStatmentApplication : IFinancialStatmentApplication
private readonly IFinancialStatmentRepository _financialStatmentRepository;
private readonly IFinancialTransactionApplication _financialTransactionApplication;
private readonly IPersonalContractingPartyRepository _contractingPartyRepository;
private readonly IFinancialInvoiceRepository _financialInvoiceRepository;
private readonly ISepehrPaymentGatewayService _sepehrPaymentGatewayService;
public FinancialStatmentApplication(IFinancialStatmentRepository financialStatmentRepository, IFinancialTransactionApplication financialTransactionApplication, IPersonalContractingPartyRepository contractingPartyRepository)
public FinancialStatmentApplication(IFinancialStatmentRepository financialStatmentRepository,
IFinancialTransactionApplication financialTransactionApplication,
IPersonalContractingPartyRepository contractingPartyRepository,
IFinancialInvoiceRepository financialInvoiceRepository,
ISepehrPaymentGatewayService sepehrPaymentGatewayService)
{
_financialStatmentRepository = financialStatmentRepository;
_financialTransactionApplication = financialTransactionApplication;
_contractingPartyRepository = contractingPartyRepository;
_financialInvoiceRepository = financialInvoiceRepository;
_sepehrPaymentGatewayService = sepehrPaymentGatewayService;
}
public OperationResult CreateFromBankGateway(CreateFinancialStatment command)
@@ -51,7 +62,6 @@ public class FinancialStatmentApplication : IFinancialStatmentApplication
if (createTransaction.IsSuccedded)
return op.Succcedded();
return op.Failed("خطا در انجام عملیات");
}
else
{
@@ -71,8 +81,6 @@ public class FinancialStatmentApplication : IFinancialStatmentApplication
Balance = 0,
TypeOfTransaction = command.TypeOfTransaction,
DescriptionOption = command.DescriptionOption
};
var createTransaction = _financialTransactionApplication.Create(transaction);
if (createTransaction.IsSuccedded)
@@ -98,22 +106,22 @@ public class FinancialStatmentApplication : IFinancialStatmentApplication
{
debtor = 0;
creditor = command.CreditorString.MoneyToDouble();
}
else if (command.TypeOfTransaction == "debt")
{
creditor = 0;
debtor = command.DeptorString.MoneyToDouble();
}
if (!command.TdateFa.TryToGeorgianDateTime(out var tDateGr))
{
return op.Failed("تاریخ وارد شده صحیح نمی باشد");
}
if (_financialStatmentRepository.Exists(x => x.ContractingPartyId == command.ContractingPartyId))
{
var financialStatment = _financialStatmentRepository.GetDetailsByContractingPartyId(command.ContractingPartyId);
var financialStatment =
_financialStatmentRepository.GetDetailsByContractingPartyId(command.ContractingPartyId);
var transaction = new CreateFinancialTransaction()
{
FinancialStatementId = financialStatment.Id,
@@ -124,20 +132,15 @@ public class FinancialStatmentApplication : IFinancialStatmentApplication
Creditor = creditor,
TypeOfTransaction = command.TypeOfTransaction,
DescriptionOption = command.DescriptionOption
};
var createTransaction = _financialTransactionApplication.Create(transaction);
var createTransaction = _financialTransactionApplication.Create(transaction);
if (createTransaction.IsSuccedded)
return op.Succcedded();
return op.Failed("خطا در انجام عملیات");
}
else
{
var statement = new FinancialStatment(command.ContractingPartyId, command.ContractingPartyName);
_financialStatmentRepository.Create(statement);
_financialStatmentRepository.SaveChanges();
@@ -153,20 +156,14 @@ public class FinancialStatmentApplication : IFinancialStatmentApplication
Balance = 0,
TypeOfTransaction = command.TypeOfTransaction,
DescriptionOption = command.DescriptionOption
};
var createTransaction = _financialTransactionApplication.Create(transaction);
if (createTransaction.IsSuccedded)
return op.Succcedded();
return op.Failed("خطا در انجام عملیات");
}
}
public List<FinancialStatmentViewModel> Search(FinancialStatmentSearchModel searchModel)
{
@@ -203,6 +200,45 @@ public class FinancialStatmentApplication : IFinancialStatmentApplication
public async Task<FinancialStatmentDetailsByContractingPartyViewModel> GetDetailsByContractingParty(
long contractingPartyId, FinancialStatementSearchModel searchModel)
{
return await _financialStatmentRepository.GetDetailsByContractingParty(contractingPartyId,searchModel);
return await _financialStatmentRepository.GetDetailsByContractingParty(contractingPartyId, searchModel);
}
public async Task<OperationResult<CreateSepehrPaymentGatewayResponse>> CreatePaymentGateWayAndCreateInvoice(
CreateFinancialPayRequest request, string gateWayCallBackUrl)
{
var op = new OperationResult<CreateSepehrPaymentGatewayResponse>();
// گام 1: دریافت موجودی حساب
var balanceAmount = await GetBalanceAmount(request.Id);
if (balanceAmount.Amount <= 0)
{
return op.Failed("موجودی حساب شما صفر است");
}
// گام 2: ایجاد درگاه پرداخت سپهر
var financialInvoice = await _financialInvoiceRepository
.GetUnPaidFinancialInvoiceByContractingPartyIdAndAmount(balanceAmount.ContractingPartyId,
balanceAmount.Amount);
if (financialInvoice == null)
{
financialInvoice = new FinancialInvoice(balanceAmount.Amount, balanceAmount.ContractingPartyId,
"پرداخت بدهی صورت حساب مالی");
var items = new FinancialInvoiceItem("پرداخت بدهی صورت حساب مالی", balanceAmount.Amount,
financialInvoice.id, FinancialInvoiceItemType.PreviousDebt, 0);
financialInvoice.AddItem(items);
await _financialInvoiceRepository.CreateAsync(financialInvoice);
await _financialInvoiceRepository.SaveChangesAsync();
}
var gatewayResult = await _sepehrPaymentGatewayService.CreateSepehrPaymentGateway(
amount: balanceAmount.Amount,
contractingPartyId: balanceAmount.ContractingPartyId,
frontCallbackUrl: request.BaseUrl,
gatewayCallbackUrl: gateWayCallBackUrl,
financialInvoiceId: financialInvoice.id,
extraData: null);
return gatewayResult;
}
}

View File

@@ -1,40 +1,31 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using _0_Framework.Application;
using _0_Framework.Application.Enums;
using _0_Framework.Application.PaymentGateway;
using _0_Framework.Application.Sms;
using _0_Framework.Application.UID;
using _0_Framework.Exceptions;
using AccountManagement.Application.Contracts.Account;
using Company.Domain.ContarctingPartyAgg;
using Company.Domain.EmployeeAgg;
using Company.Domain.empolyerAgg;
using Company.Domain.FinancialInvoiceAgg;
using Company.Domain.FinancialStatmentAgg;
using Company.Domain.FinancialTransactionAgg;
using Company.Domain.InstitutionContractAgg;
using Company.Domain.LeftWorkAgg;
using Company.Domain.PaymentTransactionAgg;
using Company.Domain.RepresentativeAgg;
using Company.Domain.RollCallServiceAgg;
using Company.Domain.TemporaryClientRegistrationAgg;
using Company.Domain.WorkshopAgg;
using CompanyManagment.App.Contracts.FinancialInvoice;
using CompanyManagment.App.Contracts.FinancialStatment;
using CompanyManagment.App.Contracts.InstitutionContract;
using CompanyManagment.App.Contracts.InstitutionContractContactinfo;
using CompanyManagment.App.Contracts.PaymentTransaction;
using CompanyManagment.App.Contracts.PersonalContractingParty;
using CompanyManagment.App.Contracts.SepehrPaymentGateway;
using CompanyManagment.App.Contracts.Workshop;
using CompanyManagment.EFCore.Migrations;
using Microsoft.AspNetCore.Mvc;
using OfficeOpenXml.Packaging.Ionic.Zip;
using PersianTools.Core;
using ConnectedPersonnelViewModel = CompanyManagment.App.Contracts.Workshop.ConnectedPersonnelViewModel;
using FinancialStatment = Company.Domain.FinancialStatmentAgg.FinancialStatment;
@@ -49,48 +40,44 @@ public class InstitutionContractApplication : IInstitutionContractApplication
private readonly IFinancialStatmentApplication _financialStatmentApplication;
private readonly IEmployerRepository _employerRepository;
private readonly IWorkshopRepository _workshopRepository;
private readonly ILeftWorkRepository _leftWorkRepository;
private readonly IWorkshopApplication _workshopApplication;
private readonly IContractingPartyTempRepository _contractingPartyTempRepository;
private readonly IFinancialStatmentRepository _financialStatmentRepository;
private readonly IContactInfoApplication _contactInfoApplication;
private readonly IAccountApplication _accountApplication;
private readonly ISmsService _smsService;
private readonly IUidService _uidService;
private readonly IFinancialInvoiceRepository _financialInvoiceRepository;
private readonly IPaymentGateway _paymentGateway;
private readonly IPaymentTransactionRepository _paymentTransactionRepository;
private readonly IRollCallServiceRepository _rollCallServiceRepository;
private readonly ISepehrPaymentGatewayService _sepehrPaymentGatewayService;
public InstitutionContractApplication(IInstitutionContractRepository institutionContractRepository,
IPersonalContractingPartyRepository contractingPartyRepository,
IRepresentativeRepository representativeRepository, IEmployerRepository employerRepository,
IWorkshopRepository workshopRepository, ILeftWorkRepository leftWorkRepository,
IWorkshopRepository workshopRepository,
IFinancialStatmentApplication financialStatmentApplication, IWorkshopApplication workshopApplication,
IContractingPartyTempRepository contractingPartyTempRepository,
IFinancialStatmentRepository financialStatmentRepository, IContactInfoApplication contactInfoApplication,
IAccountApplication accountApplication, ISmsService smsService, IUidService uidService,
IAccountApplication accountApplication, ISmsService smsService,
IFinancialInvoiceRepository financialInvoiceRepository, IHttpClientFactory httpClientFactory,
IPaymentTransactionRepository paymentTransactionRepository, IRollCallServiceRepository rollCallServiceRepository)
IPaymentTransactionRepository paymentTransactionRepository, IRollCallServiceRepository rollCallServiceRepository,
ISepehrPaymentGatewayService sepehrPaymentGatewayService)
{
_institutionContractRepository = institutionContractRepository;
_contractingPartyRepository = contractingPartyRepository;
_representativeRepository = representativeRepository;
_employerRepository = employerRepository;
_workshopRepository = workshopRepository;
_leftWorkRepository = leftWorkRepository;
_financialStatmentApplication = financialStatmentApplication;
_workshopApplication = workshopApplication;
_contractingPartyTempRepository = contractingPartyTempRepository;
_financialStatmentRepository = financialStatmentRepository;
_contactInfoApplication = contactInfoApplication;
_accountApplication = accountApplication;
_smsService = smsService;
_uidService = uidService;
_financialInvoiceRepository = financialInvoiceRepository;
_paymentTransactionRepository = paymentTransactionRepository;
_rollCallServiceRepository = rollCallServiceRepository;
_sepehrPaymentGatewayService = sepehrPaymentGatewayService;
_paymentGateway = new SepehrPaymentGateway(httpClientFactory);
}
@@ -817,20 +804,11 @@ public class InstitutionContractApplication : IInstitutionContractApplication
var contractingParty = _contractingPartyRepository.Get(institutionContract.ContractingPartyId);
if (contractingParty != null)
{
contractingParty.DeActive();
_contractingPartyRepository.SaveChanges();
var employers =
_employerRepository.GetEmployerByContracrtingPartyID(institutionContract.ContractingPartyId);
//var employersIdList = employers.Select(x => x.Id).ToList();
//var workshops = _workshopApplication.GetWorkshopsByEmployerId(employersIdList);
//foreach (var workshop in workshops)
//{
// var res = _workshopApplication.DeActive(workshop.Id);
//}
foreach (var employer in employers)
{
var res = _employerRepository.DeActiveAll(employer.Id);
}
var accountsDeActiveRes = _contractingPartyRepository.DeActiveAllAsync(contractingParty.id)
.GetAwaiter().GetResult();
if (!accountsDeActiveRes.IsSuccedded)
return opration.Failed(accountsDeActiveRes.Message);
}
return opration.Succcedded();
@@ -847,20 +825,10 @@ public class InstitutionContractApplication : IInstitutionContractApplication
var contractingParty = _contractingPartyRepository.Get(institutionContract.ContractingPartyId);
if (contractingParty != null)
{
contractingParty.Active();
_contractingPartyRepository.SaveChanges();
var employers =
_employerRepository.GetEmployerByContracrtingPartyID(institutionContract.ContractingPartyId);
//var employersIdList = employers.Select(x => x.Id).ToList();
//var workshops = _workshopApplication.GetWorkshopsByEmployerId(employersIdList);
//foreach (var workshop in workshops)
//{
// var res = _workshopApplication.DeActive(workshop.Id);
//}
foreach (var employer in employers)
{
var res = _employerRepository.ActiveAll(employer.Id);
}
var activeRes = _contractingPartyRepository.ActiveAllAsync(contractingParty.id).GetAwaiter()
.GetResult();
if (!activeRes.IsSuccedded)
return opration.Failed(activeRes.Message);
}
return opration.Succcedded();
@@ -1294,119 +1262,93 @@ public class InstitutionContractApplication : IInstitutionContractApplication
if (contractingParty == null)
throw new NotFoundException("طرف قرارداد یافت نشد");
if (institutionContract.VerifyCode != code)
return op.Failed("کد وارد شده صحیح نمی باشد");
var financialStatement =await _financialStatmentRepository.GetByContractingPartyId(contractingParty.id);
if (institutionContract.VerifyCode != code)
return op.Failed("کد وارد شده صحیح نمی باشد");
var dbTransaction = await _institutionContractRepository.BeginTransactionAsync();
FinancialInvoice financialInvoice;
FinancialInvoiceItem financialInvoiceItem;
var today = DateTime.Today;
double invoiceAmount = 0;
string invoiceItemDescription = string.Empty;
FinancialInvoiceItemType invoiceItemType = FinancialInvoiceItemType.BuyInstitutionContract;
long invoiceItemEntityId = 0;
var financialStatement = await _financialStatmentRepository.GetByContractingPartyId(contractingParty.id);
if (institutionContract.IsInstallment)
{
var firstInstallment = institutionContract.Installments.First();
var firstInstallmentAmount = firstInstallment.Amount;
var dbTransaction = await _institutionContractRepository.BeginTransactionAsync();
FinancialInvoice financialInvoice;
FinancialInvoiceItem financialInvoiceItem;
var today = DateTime.Today;
double invoiceAmount = 0;
string invoiceItemDescription = string.Empty;
FinancialInvoiceItemType invoiceItemType = FinancialInvoiceItemType.BuyInstitutionContract;
long invoiceItemEntityId = 0;
financialInvoice = await _financialInvoiceRepository.GetUnPaidByEntityId(firstInstallment.Id, FinancialInvoiceItemType.BuyInstitutionContractInstallment);
if (financialInvoice == null)
{
var financialTransaction = new FinancialTransaction(0, today, today.ToFarsi(),
"قسط اول سرویس", "debt", "بابت خدمات", firstInstallmentAmount, 0, 0);
financialStatement.AddFinancialTransaction(financialTransaction);
invoiceAmount = firstInstallmentAmount;
invoiceItemDescription = $"پرداخت قسط اول قرارداد شماره {institutionContract.ContractNo}";
invoiceItemType = FinancialInvoiceItemType.BuyInstitutionContractInstallment;
invoiceItemEntityId = firstInstallment.Id;
}
else
{
invoiceAmount = financialInvoice.Amount;
invoiceItemDescription = financialInvoice.Items.First().Description;
invoiceItemType = financialInvoice.Items.First().Type;
invoiceItemEntityId = financialInvoice.Items.First().EntityId;
}
}
else
{
financialInvoice = await _financialInvoiceRepository.GetUnPaidByEntityId(institutionContract.id, FinancialInvoiceItemType.BuyInstitutionContract);
if (financialInvoice == null)
{
var financialTransaction = new FinancialTransaction(0, today, today.ToFarsi(),
"پرداخت کل سرویس", "debt", "بابت خدمات", institutionContract.TotalAmount, 0, 0);
financialStatement.AddFinancialTransaction(financialTransaction);
invoiceAmount = institutionContract.TotalAmount;
invoiceItemDescription = $"پرداخت کل قرارداد شماره {institutionContract.ContractNo}";
invoiceItemType = FinancialInvoiceItemType.BuyInstitutionContract;
invoiceItemEntityId = institutionContract.id;
}
else
{
invoiceAmount = financialInvoice.Amount;
invoiceItemDescription = financialInvoice.Items.First().Description;
invoiceItemType = financialInvoice.Items.First().Type;
invoiceItemEntityId = financialInvoice.Items.First().EntityId;
}
}
if (institutionContract.IsInstallment)
{
var firstInstallment = institutionContract.Installments.First();
var firstInstallmentAmount = firstInstallment.Amount;
if (financialInvoice == null)
{
financialInvoice = new FinancialInvoice(invoiceAmount, contractingParty.id, $"خرید قرارداد مالی شماره {institutionContract.ContractNo}");
financialInvoiceItem = new FinancialInvoiceItem(invoiceItemDescription, invoiceAmount, 0, invoiceItemType, invoiceItemEntityId);
financialInvoice.AddItem(financialInvoiceItem);
await _financialInvoiceRepository.CreateAsync(financialInvoice);
}
financialInvoice = await _financialInvoiceRepository.GetUnPaidByEntityId(firstInstallment.Id, FinancialInvoiceItemType.BuyInstitutionContractInstallment);
if (financialInvoice == null)
{
var financialTransaction = new FinancialTransaction(0, today, today.ToFarsi(),
"قسط اول سرویس", "debt", "بابت خدمات", firstInstallmentAmount, 0, 0);
financialStatement.AddFinancialTransaction(financialTransaction);
invoiceAmount = firstInstallmentAmount;
invoiceItemDescription = $"پرداخت قسط اول قرارداد شماره {institutionContract.ContractNo}";
invoiceItemType = FinancialInvoiceItemType.BuyInstitutionContractInstallment;
invoiceItemEntityId = firstInstallment.Id;
}
else
{
invoiceAmount = financialInvoice.Amount;
invoiceItemDescription = financialInvoice.Items.First().Description;
invoiceItemType = financialInvoice.Items.First().Type;
invoiceItemEntityId = financialInvoice.Items.First().EntityId;
}
}
else
{
financialInvoice = await _financialInvoiceRepository.GetUnPaidByEntityId(institutionContract.id, FinancialInvoiceItemType.BuyInstitutionContract);
if (financialInvoice == null)
{
var financialTransaction = new FinancialTransaction(0, today, today.ToFarsi(),
"پرداخت کل سرویس", "debt", "بابت خدمات", institutionContract.TotalAmount, 0, 0);
financialStatement.AddFinancialTransaction(financialTransaction);
invoiceAmount = institutionContract.TotalAmount;
invoiceItemDescription = $"پرداخت کل قرارداد شماره {institutionContract.ContractNo}";
invoiceItemType = FinancialInvoiceItemType.BuyInstitutionContract;
invoiceItemEntityId = institutionContract.id;
}
else
{
invoiceAmount = financialInvoice.Amount;
invoiceItemDescription = financialInvoice.Items.First().Description;
invoiceItemType = financialInvoice.Items.First().Type;
invoiceItemEntityId = financialInvoice.Items.First().EntityId;
}
}
await _financialInvoiceRepository.SaveChangesAsync();
if (financialInvoice == null)
{
financialInvoice = new FinancialInvoice(invoiceAmount, contractingParty.id, $"خرید قرارداد مالی شماره {institutionContract.ContractNo}");
financialInvoiceItem = new FinancialInvoiceItem(invoiceItemDescription, invoiceAmount, 0, invoiceItemType, invoiceItemEntityId);
financialInvoice.AddItem(financialInvoiceItem);
await _financialInvoiceRepository.CreateAsync(financialInvoice);
}
var transaction = new PaymentTransaction(institutionContract.ContractingPartyId, invoiceAmount,
institutionContract.ContractingPartyName, "https://client.gozareshgir.ir",
PaymentTransactionGateWay.SepehrPay);
await _paymentTransactionRepository.CreateAsync(transaction);
await _financialInvoiceRepository.SaveChangesAsync();
await _financialInvoiceRepository.SaveChangesAsync();
var createPayment = new CreatePaymentGatewayRequest()
{
Amount = invoiceAmount,
TransactionId = transaction.id.ToString(),
CallBackUrl = callbackUrl,
FinancialInvoiceId = financialInvoice.id,
};
var gatewayResponse = await _paymentGateway.Create(createPayment);
if (!gatewayResponse.IsSuccess)
return op.Failed("خطا در ایجاد درگاه پرداخت: " + gatewayResponse.Message + gatewayResponse.ErrorCode);
// استفاده از سرویس مشترک برای ایجاد درگاه پرداخت
var gatewayResult = await _sepehrPaymentGatewayService.CreateSepehrPaymentGateway(
amount: (long)invoiceAmount,
contractingPartyId: institutionContract.ContractingPartyId,
gatewayCallbackUrl: callbackUrl,
financialInvoiceId: financialInvoice.id,
extraData: null);
// institutionContract.SetPendingWorkflow();
//
// var phone = institutionContract.ContactInfoList.FirstOrDefault(x =>
// x.SendSms && x.Position == "طرف قرارداد" && x.PhoneType == "شماره همراه");
// if (phone !=null)
// {
// var userPass = contractingParty.IsLegal == "حقیقی"
// ? contractingParty.Nationalcode
// : contractingParty.NationalId;
// var createAcc = new RegisterAccount
// {
// Fullname = contractingParty.LName,
// Username = userPass,
// Password = userPass,
// Mobile = phone.PhoneNumber,
// NationalCode = userPass
// };
// var res = _accountApplication.RegisterClient(createAcc);
// if (res.IsSuccedded)
// CreateContractingPartyAccount(contractingParty.id, res.SendId);
// }
if (!gatewayResult.IsSuccedded)
{
await dbTransaction.RollbackAsync();
return op.Failed(gatewayResult.Message);
}
await dbTransaction.CommitAsync();
await _institutionContractRepository.SaveChangesAsync();
return op.Succcedded(gatewayResponse.Token);
return op.Succcedded(gatewayResult.Data.Token);
}
public async Task<InstitutionContractWorkshopDetailViewModel> GetWorkshopInitialDetails(long workshopDetailsId)
@@ -1444,6 +1386,22 @@ public class InstitutionContractApplication : IInstitutionContractApplication
return _institutionContractRepository.ResetDiscountCreate(request);
}
public Task<InstitutionContractCreationInquiryResult> CreationInquiry(InstitutionContractCreationInquiryRequest request)
{
return _institutionContractRepository.CreationInquiry(request);
}
public Task<InstitutionContractCreationWorkshopsResponse> GetCreationWorkshops(InstitutionContractCreationWorkshopsRequest request)
{
return _institutionContractRepository.GetCreationWorkshops(request);
}
public Task<InstitutionContractCreationPlanResponse> GetCreationInstitutionPlan(InstitutionContractCreationPlanRequest request)
{
return _institutionContractRepository.GetCreationInstitutionPlan(request);
}
public async Task<InstitutionContractExtensionInquiryResult> GetExtensionInquiry(long previousContractId)
{
return await _institutionContractRepository.GetExtensionInquiry(previousContractId);
@@ -1634,6 +1592,11 @@ public class InstitutionContractApplication : IInstitutionContractApplication
if (institutionContract.VerificationStatus == InstitutionContractVerificationStatus.Verified)
return op.Failed("قرارداد مالی قبلا تایید شده است");
if (!institutionContract.WorkshopGroup.IsInPersonContract)
{
return op.Failed("قرارداد مالی غیر حضوری نمی تواند به صورت دستی تایید شود");
}
var transaction = await _institutionContractRepository.BeginTransactionAsync();
await SetPendingWorkflow(institutionContractId,InstitutionContractSigningType.Physical);
@@ -1657,6 +1620,28 @@ public class InstitutionContractApplication : IInstitutionContractApplication
return op.Succcedded();
}
public Task<InstitutionContractCreationPaymentResponse> GetCreationPaymentMethod(InstitutionContractCreationPaymentRequest request)
{
return _institutionContractRepository.GetCreationPaymentMethod(request);
}
public Task<InstitutionContractDiscountResponse> SetDiscountForCreation(InstitutionContractSetDiscountForCreationRequest request)
{
return _institutionContractRepository.SetDiscountForCreation(request);
}
public Task<InstitutionContractDiscountResponse> ResetDiscountForCreation(InstitutionContractResetDiscountForExtensionRequest request)
{
return _institutionContractRepository.ResetDiscountForCreation(request);
}
public Task<OperationResult> CreationComplete(InstitutionContractExtensionCompleteRequest request)
{
return _institutionContractRepository.CreationComplete(request);
}
private async Task<OperationResult<PersonalContractingParty>> CreateLegalContractingPartyEntity(
CreateInstitutionContractLegalPartyRequest request, long representativeId, string address, string city,
string state)

View File

@@ -0,0 +1,237 @@
using _0_Framework.Application;
using Company.Domain.PaymentTransactionAgg;
using CompanyManagment.App.Contracts.FinancialInvoice;
using CompanyManagment.App.Contracts.FinancialStatment;
using CompanyManagment.App.Contracts.InstitutionContract;
using CompanyManagment.App.Contracts.PaymentCallback;
using CompanyManagment.App.Contracts.PaymentTransaction;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Transactions;
using _0_Framework.Application.PaymentGateway;
using Company.Domain.FinancialStatmentAgg;
using Company.Domain.FinancialTransactionAgg;
using Company.Domain.InstitutionContractAgg;
using CompanyManagment.EFCore.Migrations;
namespace CompanyManagment.Application;
public class PaymentCallbackHandler : IPaymentCallbackHandler
{
private readonly IPaymentTransactionApplication _paymentTransactionApplication;
private readonly IFinancialStatmentApplication _financialStatmentApplication;
private readonly IFinancialStatmentRepository _financialStatmentRepository;
private readonly IFinancialInvoiceApplication _financialInvoiceApplication;
private readonly IInstitutionContractApplication _institutionContractApplication;
private readonly IInstitutionContractRepository _institutionContractRepository;
private readonly IPaymentGateway _paymentGateway;
public PaymentCallbackHandler(
IPaymentTransactionApplication paymentTransactionApplication,
IFinancialStatmentApplication financialStatmentApplication,
IFinancialInvoiceApplication financialInvoiceApplication,
IInstitutionContractApplication institutionContractApplication,
IHttpClientFactory httpClientFactory, IInstitutionContractRepository institutionContractRepository,
IFinancialStatmentRepository financialStatmentRepository)
{
_paymentTransactionApplication = paymentTransactionApplication;
_financialStatmentApplication = financialStatmentApplication;
_financialInvoiceApplication = financialInvoiceApplication;
_institutionContractApplication = institutionContractApplication;
_institutionContractRepository = institutionContractRepository;
_financialStatmentRepository = financialStatmentRepository;
_paymentGateway = new SepehrPaymentGateway(httpClientFactory);
}
/// <summary>
/// تأیید و پردازش callback درگاه پرداخت سپهر
/// </summary>
public async Task<OperationResult> VerifySepehrPaymentCallback(VerifyPaymentCallbackCommand command,
CancellationToken cancellationToken = default)
{
var operation = new OperationResult();
try
{
await using var transactionScope =await _financialStatmentRepository.BeginTransactionAsync();
// گام 1: دریافت اطلاعات تراکنش
var transaction = await _paymentTransactionApplication.GetDetails(command.InvoiceId);
if (transaction == null)
return operation.Failed("تراکنش مورد نظر یافت نشد");
// گام 2: بررسی وضعیت قبلی تراکنش
if (transaction.Status != PaymentTransactionStatus.Pending)
return operation.Failed("این تراکنش قبلا پرداخت شده است");
// گام 3: بررسی کد پاسخ درگاه
if (command.ResponseCode != 0)
{
var failResult = _paymentTransactionApplication.SetFailed(command.InvoiceId);
return failResult.IsSuccedded
? operation.Failed("تراکنش توسط درگاه رد شد")
: operation.Failed("خطا در به‌روزرسانی وضعیت تراکنش");
}
// گام 4: استخراج اطلاعات فاکتور مالی
var extraData = JsonConvert.DeserializeObject<IDictionary<string, object>>(command.Payload ?? "{}");
extraData.TryGetValue("financialInvoiceId", out var financialInvoiceIdObj);
if (financialInvoiceIdObj == null ||
!long.TryParse(financialInvoiceIdObj.ToString(), out var financialInvoiceId))
return operation.Failed("فاکتور مالی نامعتبر است");
// گام 5: دریافت اطلاعات فاکتور مالی
var financialInvoice = _financialInvoiceApplication.GetDetails(financialInvoiceId);
if (financialInvoice == null)
return operation.Failed("فاکتور مالی نامعتبر است");
if (financialInvoice.Status != FinancialInvoiceStatus.Unpaid)
return operation.Failed("فاکتور مالی نامعتبر است");
// گام 6: بررسی تطابق مبلغ
if ((long)financialInvoice.Amount != command.Amount)
{
var failResult = _paymentTransactionApplication.SetFailed(command.InvoiceId);
return operation.Failed("مبلغ تراکنش با مبلغ فاکتور مطابقت ندارد");
}
// گام 7: به‌روزرسانی فاکتور مالی
var setPaidResult = _financialInvoiceApplication.SetPaid(financialInvoiceId, DateTime.Now);
if (!setPaidResult.IsSuccedded)
{
var failResult = _paymentTransactionApplication.SetFailed(command.InvoiceId);
return operation.Failed("خطا در به‌روزرسانی فاکتور مالی");
}
// گام 8: به‌روزرسانی وضعیت تراکنش
var setSuccessResult = _paymentTransactionApplication.SetSuccess(
command.InvoiceId,
command.CardNumber,
command.IssuerBank,
command.Rrn.ToString(),
command.DigitalReceipt);
if (!setSuccessResult.IsSuccedded)
{
return operation.Failed("خطا در به‌روزرسانی وضعیت تراکنش");
}
// گام 9: به‌روزرسانی وضعیت قرارداد‌های نهادی (اگر وجود داشته باشند)
var institutionContractItems = financialInvoice.Items.Where(x =>
x.Type is FinancialInvoiceItemType.BuyInstitutionContract
or FinancialInvoiceItemType.BuyInstitutionContractInstallment).ToList();
if (institutionContractItems.Any())
{
await HandleInstitutionContractItems(financialInvoice);
}
// گام 10: ایجاد سند مالی (Financial Statement)
var createCreditStatementCommand = new CreateFinancialStatment()
{
ContractingPartyId = transaction.ContractingPartyId,
Deptor = 0,
Creditor = command.Amount,
DeptorString = "0",
TypeOfTransaction = "credit",
DescriptionOption = (financialInvoice.Description ?? "") + " شماره فاکتور: " +
(financialInvoice.InvoiceNumber ?? ""),
Description = "درگاه بانکی",
};
var statementResult = _financialStatmentApplication.CreateFromBankGateway(createCreditStatementCommand);
if (!statementResult.IsSuccedded)
{
_paymentTransactionApplication.SetFailed(command.InvoiceId);
return operation.Failed("خطا در ایجاد سند مالی");
}
// گام 11: تأیید نهایی با درگاه پرداخت
var verifyCommand = new VerifyPaymentGateWayRequest()
{
Amount = transaction.Amount,
TransactionId = command.InvoiceId.ToString(),
DigitalReceipt = command.DigitalReceipt
};
var verifyRes = await _paymentGateway.Verify(verifyCommand, cancellationToken);
#if DEBUG
verifyRes.IsSuccess = true;
#endif
if (!verifyRes.IsSuccess)
{
return operation.Failed("خطا در تایید پرداخت از درگاه");
}
// تمام عملیات موفق - تایید transaction
await transactionScope.CommitAsync(cancellationToken);
return operation.Succcedded();
}
catch (Exception ex)
{
// در صورت بروز هرگونه خطا، transaction خودکار rollback می‌شود
return operation.Failed($"خطا در پردازش callback: {ex.Message}");
}
}
/// <summary>
/// مدیریت آپدیت قرارداد‌های نهادی
/// </summary>
private async Task HandleInstitutionContractItems(EditFinancialInvoice financialInvoice)
{
// قرارداد‌های خریداری مستقیم
var directContractItems = financialInvoice.Items
.Where(x => x.Type == FinancialInvoiceItemType.BuyInstitutionContract);
var financialStatement =
await _financialStatmentRepository.GetByContractingPartyId(financialInvoice.ContractingPartyId);
var today = DateTime.Now;
foreach (var item in directContractItems)
{
var institutionContract = _institutionContractRepository.Get(item.EntityId);
await _institutionContractApplication.SetPendingWorkflow(item.EntityId,
InstitutionContractSigningType.OtpBased);
var financialTransaction = new FinancialTransaction(0, today, today.ToFarsi(),
"پرداخت کل سرویس", "debt", "بابت خدمات", institutionContract.TotalAmount, 0, 0);
financialStatement.AddFinancialTransaction(financialTransaction);
}
// قرارداد‌های خریداری با اقساط
var installmentItems = financialInvoice.Items
.Where(x => x.Type == FinancialInvoiceItemType.BuyInstitutionContractInstallment);
foreach (var item in installmentItems)
{
var institutionContractId =await _institutionContractRepository.GetIdByInstallmentId(item.EntityId);
var institutionContract = _institutionContractRepository.Get(institutionContractId);
await _institutionContractApplication.SetPendingWorkflow(institutionContractId,
InstitutionContractSigningType.OtpBased);
var firstInstallment = institutionContract.Installments.First();
var firstInstallmentAmount = firstInstallment.Amount;
var financialTransaction = new FinancialTransaction(0, today, today.ToFarsi(),
"قسط اول سرویس", "debt", "بابت خدمات", firstInstallmentAmount, 0, 0);
financialStatement.AddFinancialTransaction(financialTransaction);
}
await _financialStatmentRepository.SaveChangesAsync();
}
}

View File

@@ -722,5 +722,11 @@ public class PersonalContractingPartyApplication : IPersonalContractingPartyApp
return await _personalContractingPartyRepository.GetLegalDetails(id);
}
public async Task<long> GetRepresentativeIdByNationalCode(string nationalCode)
{
var entity = await _personalContractingPartyRepository.GetByNationalCode(nationalCode);
return entity?.RepresentativeId??0;
}
#endregion
}

View File

@@ -0,0 +1,117 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using _0_Framework.Application;
using _0_Framework.Application.PaymentGateway;
using CompanyManagment.App.Contracts.PaymentTransaction;
using CompanyManagment.App.Contracts.SepehrPaymentGateway;
namespace CompanyManagment.Application;
/// <summary>
/// سرویس مشترک برای ایجاد درگاه پرداخت سپهر
/// </summary>
public class SepehrPaymentGatewayService : ISepehrPaymentGatewayService
{
private readonly IPaymentGateway _paymentGateway;
private readonly IPaymentTransactionApplication _paymentTransactionApplication;
public SepehrPaymentGatewayService(
IPaymentTransactionApplication paymentTransactionApplication,
IHttpClientFactory httpClientFactory)
{
_paymentGateway = new SepehrPaymentGateway(httpClientFactory);
_paymentTransactionApplication = paymentTransactionApplication;
}
/// <summary>
/// ایجاد درگاه پرداخت سپهر برای یک تراکنش
/// </summary>
/// <param name="amount">مبلغ</param>
/// <param name="contractingPartyId">شناسه طرف قرارداد</param>
/// <param name="frontCallbackUrl">آدرس بازگشتی به فرانت برای نمایش نتیجه</param>
/// <param name="gatewayCallbackUrl">آدرس بازگشتی درگاه پرداخت</param>
/// <param name="financialInvoiceId">شناسه فاکتور مالی (اختیاری)</param>
/// <param name="extraData">داده‌های اضافی (اختیاری)</param>
/// <param name="cancellationToken">توکن لغو</param>
/// <returns>شامل Token درگاه یا OperationResult با خطا</returns>
public async Task<OperationResult<CreateSepehrPaymentGatewayResponse>> CreateSepehrPaymentGateway(
double amount,
long contractingPartyId,
long financialInvoiceId,
string gatewayCallbackUrl,
string frontCallbackUrl="https://client.gozareshgir.ir",
Dictionary<string, object> extraData = null,
CancellationToken cancellationToken = default)
{
var op = new OperationResult<CreateSepehrPaymentGatewayResponse>();
try
{
// گام 1: ایجاد تراکنش پرداخت
var transactionCommand = new CreatePaymentTransaction()
{
Amount = amount,
ContractingPartyId = contractingPartyId,
CallBackUrl = frontCallbackUrl,
Gateway = PaymentTransactionGateWay.SepehrPay
};
var transactionResult = await _paymentTransactionApplication.Create(transactionCommand);
if (!transactionResult.IsSuccedded)
{
return op.Failed(transactionResult.Message);
}
// گام 2: ایجاد درخواست درگاه پرداخت
extraData ??= new Dictionary<string, object>();
var createPaymentCommand = new CreatePaymentGatewayRequest()
{
Amount = amount,
TransactionId = transactionResult.SendId.ToString(),
CallBackUrl = gatewayCallbackUrl,
FinancialInvoiceId = financialInvoiceId,
ExtraData = extraData
};
// گام 3: ارسال درخواست به درگاه سپهر
var gatewayResponse = await _paymentGateway.Create(createPaymentCommand, cancellationToken);
#if DEBUG
gatewayResponse.IsSuccess = true;
#endif
if (!gatewayResponse.IsSuccess)
{
return op.Failed($"خطا در ایجاد درگاه پرداخت: {gatewayResponse.Message ?? gatewayResponse.ErrorCode?.ToString()}");
}
// گام 4: ذخیره Token در تراکنش
var setTokenResult = await _paymentTransactionApplication.SetTransactionId(
transactionResult.SendId,
gatewayResponse.Token);
if (!setTokenResult.IsSuccedded)
{
return op.Failed("خطا در ذخیره Token درگاه");
}
// گام 5: بازگشت اطلاعات درگاه پرداخت
var response = new CreateSepehrPaymentGatewayResponse
{
Token = gatewayResponse.Token,
TransactionId = transactionResult.SendId,
PaymentUrl = _paymentGateway.GetStartPayUrl(gatewayResponse.Token)
};
return op.Succcedded(response);
}
catch (Exception ex)
{
return op.Failed($"خطا در ایجاد درگاه پرداخت: {ex.Message}");
}
}
}

View File

@@ -34,6 +34,7 @@ public class FinancialInvoiceRepository : RepositoryBase<long, FinancialInvoice>
Amount = financialInvoice.Amount,
Status = financialInvoice.Status,
InvoiceNumber = financialInvoice.InvoiceNumber,
ContractingPartyId = financialInvoice.ContractingPartyId,
Items = financialInvoice.Items?.Select(x => new EditFinancialInvoiceItem
{
Id = x.id,
@@ -100,4 +101,12 @@ public class FinancialInvoiceRepository : RepositoryBase<long, FinancialInvoice>
.Where(x => x.Status == FinancialInvoiceStatus.Unpaid).FirstOrDefaultAsync(x => x.Items
.Any(y => y.Type == financialInvoiceItemType && y.EntityId == entityId));
}
public async Task<FinancialInvoice> GetUnPaidFinancialInvoiceByContractingPartyIdAndAmount(long contractingPartyId,
double amount)
{
return await _context.FinancialInvoices.FirstOrDefaultAsync(x=>x.ContractingPartyId == contractingPartyId &&
x.Amount == amount &&
x.Status == FinancialInvoiceStatus.Unpaid);
}
}

View File

@@ -177,7 +177,7 @@ public class InsuranceListRepository : RepositoryBase<long, InsuranceList>, IIns
{
checkout.SetUpdateNeeded();
if (!_context.CheckoutWarningMessages.Any(x =>
x.CheckoutId == checkout.id && x.TypeOfCheckoutWarning !=
x.CheckoutId == checkout.id && x.TypeOfCheckoutWarning ==
TypeOfCheckoutWarning.InsuranceEmployeeShare))
{
var createWarrning =

View File

@@ -773,6 +773,137 @@ public class PersonalContractingPartyRepository : RepositoryBase<long, PersonalC
return await _context.PersonalContractingParties.FirstOrDefaultAsync(x => x.NationalId == nationalId);
}
public async Task<OperationResult> DeActiveAllAsync(long id)
{
OperationResult result = new OperationResult();
await using var transaction = await _context.Database.BeginTransactionAsync();
await using var accountTransaction = await _accountContext.Database.BeginTransactionAsync();
try
{
var contractingParty = _context.PersonalContractingParties
.FirstOrDefault(x => x.id == id);
if (contractingParty == null)
return result.Failed("طرف حساب یافت نشد");
contractingParty.DeActive();
var employers = _context.Employers
.Where(x => x.ContractingPartyId == id).ToList();
employers.ForEach(x => x.DeActive());
var employerIds = employers.Select(x => x.id).ToList();
var workshopIds = _context.WorkshopEmployers
.Where(x => employerIds.Contains(x.EmployerId))
.Select(x => x.WorkshopId).ToList();
var workshops = _context.Workshops
.Where(x => workshopIds.Contains(x.id)).ToList();
workshops.ForEach(x => x.DeActive(x.ArchiveCode));
var contracts = _context.Contracts
.Where(x => workshopIds.Contains(x.WorkshopIds)).ToList();
contracts.ForEach(x => x.DeActive());
var contractIds = contracts.Select(x => x.id).ToList();
var checkouts = _context.CheckoutSet
.Where(x => contractIds.Contains(x.ContractId)).ToList();
checkouts.ForEach(x => x.DeActive());
var contractingPartyAccount =await _context.ContractingPartyAccounts
.FirstOrDefaultAsync(x => x.PersonalContractingPartyId == id);
if (contractingPartyAccount != null)
{
var account = await _accountContext.Accounts
.FirstOrDefaultAsync(x => x.id == contractingPartyAccount.AccountId);
account?.DeActive();
var cameraAccount =await _accountContext.CameraAccounts
.FirstOrDefaultAsync(x=>x.AccountId==account.id);
cameraAccount?.DeActive();
await _accountContext.SaveChangesAsync();
}
await _context.SaveChangesAsync();
await transaction.CommitAsync();
await accountTransaction.CommitAsync();
result.Succcedded();
}
catch (Exception)
{
result.Failed("غیرفعال کردن طرف حساب با خطا مواجه شد");
await transaction.RollbackAsync();
await accountTransaction.RollbackAsync();
}
return result;
}
public async Task<OperationResult> ActiveAllAsync(long id)
{
OperationResult result = new OperationResult();
await using var transaction =await _context.Database.BeginTransactionAsync();
await using var accountTransaction = await _accountContext.Database.BeginTransactionAsync();
try
{
var personel = _context.PersonalContractingParties
.FirstOrDefault(x => x.id == id);
if (personel == null)
return result.Failed("طرف حساب یافت نشد");
personel.Active();
var employers = _context.Employers.Where(x => x.ContractingPartyId == id).ToList();
employers.ForEach(x => x.Active());
var employerIds = employers.Select(x => x.id).ToList();
var workshopIds = _context.WorkshopEmployers.Where(x => employerIds.Contains(x.EmployerId))
.Select(x => x.WorkshopId).ToList();
var workshops = _context.Workshops.Where(x => workshopIds.Contains(x.id)).ToList();
workshops.ForEach(x => x.Active(x.ArchiveCode));
var contracts = _context.Contracts.Where(x => workshopIds.Contains(x.WorkshopIds)).ToList();
contracts.ForEach(x => x.Active());
var contractIds = contracts.Select(x => x.id).ToList();
var checkouts = _context.CheckoutSet.Where(x => contractIds.Contains(x.ContractId)).ToList();
checkouts.ForEach(x => x.Active());
var contractingPartyAccount =await _context.ContractingPartyAccounts
.FirstOrDefaultAsync(x => x.PersonalContractingPartyId == id);
if (contractingPartyAccount != null)
{
var account = await _accountContext.Accounts
.FirstOrDefaultAsync(x => x.id == contractingPartyAccount.AccountId);
account?.Active();
var cameraAccount =await _accountContext.CameraAccounts
.FirstOrDefaultAsync(x=>x.AccountId==account.id);
cameraAccount?.Active();
await _accountContext.SaveChangesAsync();
}
await _context.SaveChangesAsync();
await transaction.CommitAsync();
await accountTransaction.CommitAsync();
result.Succcedded();
}
catch (Exception)
{
result.Failed("فعال کردن طرف حساب با خطا مواجه شد");
await transaction.RollbackAsync();
await accountTransaction.RollbackAsync();
}
return result;
}
#endregion
}

View File

@@ -518,6 +518,31 @@ public class SmsService : ISmsService
return result;
}
public async Task<(byte status, string message, int messaeId, bool isSucceded)> BlockMessageForElectronicContract(string number, string fullname, string amount,string code1, string code2)
{
var tamplateId = 117685;
var result = new ValueTuple<byte, string, int, bool>();
var smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa");
var sendResult = await smsIr.VerifySendAsync(number, tamplateId,
new VerifySendParameter[]
{
new("FULLNAME", fullname), new("AMOUNT", amount), new("CODE1", code1), new("CODE2", code2)
});
Thread.Sleep(500);
if (sendResult.Message == "موفق")
{
result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, true);
return result;
}
result = (sendResult.Status, sendResult.Message, sendResult.Data.MessageId, false);
return result;
}
#endregion

View File

@@ -229,153 +229,15 @@ using CompanyManagment.Application;
using CompanyManagment.EFCore;
using CompanyManagment.EFCore._common;
using CompanyManagment.EFCore.Repository;
using CompanyManagment.EFCore.Repository;
using File.EfCore.Repository;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using P_TextManager.Domin.TextManagerAgg;
using CompanyManagment.App.Contracts.CrossJobItems;
using Company.Domain.CrossJobItemsAgg;
using Company.Domain.DateSalaryAgg;
using Company.Domain.DateSalaryItemAgg;
using Company.Domain.FinancialStatmentAgg;
using Company.Domain.FinancialTransactionAgg;
using Company.Domain.GroupPlanAgg;
using Company.Domain.GroupPlanJobItemAgg;
using Company.Domain.InstitutionContractAgg;
using Company.Domain.InstitutionContractContactInfoAgg;
using CompanyManagment.App.Contracts.Insurance;
using Company.Domain.InsuranceAgg;
using Company.Domain.InsuranceEmployeeInfoAgg;
using Company.Domain.InsuranceJobItemAgg;
using Company.Domain.InsuranceListAgg;
using Company.Domain.InsurancJobAgg;
using Company.Domain.InsurancWorkshopInfoAgg;
using Company.Domain.LeftWorkInsuranceAgg;
using Company.Domain.PaymentToEmployeeAgg;
using Company.Domain.PaymentToEmployeeItemAgg;
using Company.Domain.PercentageAgg;
using Company.Domain.PersonnelCodeAgg;
using Company.Domain.SmsResultAgg;
using Company.Domain.WorkingHoursTempAgg;
using Company.Domain.WorkingHoursTempItemAgg;
using Company.Domain.WorkshopPlanAgg;
using Company.Domain.WorkshopPlanEmployeeAgg;
using Company.Domain.ZoneAgg;
using CompanyManagment.App.Contracts.ClassifiedSalary;
using CompanyManagment.App.Contracts.DateSalary;
using CompanyManagment.App.Contracts.DateSalaryItem;
using CompanyManagment.App.Contracts.EmployeeInsurancListData;
using CompanyManagment.App.Contracts.FinancialStatment;
using CompanyManagment.App.Contracts.FinancilTransaction;
using CompanyManagment.App.Contracts.InstitutionContract;
using CompanyManagment.App.Contracts.InstitutionContractContactinfo;
using CompanyManagment.App.Contracts.InsuranceEmployeeInfo;
using CompanyManagment.App.Contracts.InsuranceJob;
using CompanyManagment.App.Contracts.InsuranceList;
using CompanyManagment.App.Contracts.InsuranceWorkshopInfo;
using CompanyManagment.App.Contracts.LeftWorkInsurance;
using CompanyManagment.App.Contracts.PaymentToEmployee;
using CompanyManagment.App.Contracts.Percentage;
using CompanyManagment.App.Contracts.PersonnleCode;
using CompanyManagment.App.Contracts.SmsResult;
using CompanyManagment.App.Contracts.WorkingHoursTemp;
using CompanyManagment.App.Contracts.WorkingHoursTempItem;
using CompanyManagment.App.Contracts.WorkshopPlan;
using CompanyManagment.App.Contracts.Zone;
using CompanyManagment.App.Contracts.EmployeeComputeOptions;
using Company.Domain.EmployeeComputeOptionsAgg;
using Company.Domain.InsuranceYearlySalaryAgg;
using Company.Domain.ReportAgg;
using Company.Domain.RollCallAgg;
using Company.Domain.RollCallEmployeeAgg;
using Company.Domain.RollCallPlanAgg;
using Company.Domain.RollCallServiceAgg;
using CompanyManagment.App.Contracts.InsuranceYearlySalary;
using CompanyManagment.App.Contracts.Report;
using CompanyManagment.App.Contracts.RollCall;
using CompanyManagment.App.Contracts.RollCallEmployee;
using CompanyManagment.App.Contracts.RollCallService;
using CompanyManagment.App.Contracts.RollCallPlan;
using Company.Domain.ReportClientAgg;
using Company.Domain.TaxJobCategoryAgg;
using Company.Domain.WorkshopAccountAgg;
using CompanyManagment.App.Contracts.ReportClient;
using CompanyManagment.App.Contracts.TaxJobCategory;
using Company.Domain.RollCallEmployeeStatusAgg;
using CompanyManagment.App.Contracts.RollCallEmployeeStatus;
using Company.Domain.CustomizeWorkshopEmployeeSettingsAgg;
using Company.Domain.CustomizeWorkshopGroupSettingsAgg;
using Company.Domain.CustomizeWorkshopSettingsAgg;
using Company.Domain.FineAgg;
using Company.Domain.LoanAgg;
using Company.Domain.RewardAgg;
using Company.Domain.SalaryAidAgg;
using CompanyManagment.App.Contracts.CustomizeWorkshopSettings;
using CompanyManagment.App.Contracts.Fine;
using CompanyManagment.App.Contracts.Loan;
using CompanyManagment.App.Contracts.Reward;
using CompanyManagment.App.Contracts.SalaryAid;
using Company.Domain.AndroidApkVersionAgg;
using Company.Domain.BankAgg;
using CompanyManagment.App.Contracts.AndroidApkVersion;
using Company.Domain.FineSubjectAgg;
using CompanyManagment.App.Contracts.FineSubject;
using Company.Domain.CustomizeCheckoutAgg;
using CompanyManagment.App.Contracts.CustomizeCheckout;
using Company.Domain.WorkshopSubAccountAgg;
using Company.Domain.CustomizeCheckoutTempAgg;
using Company.Domain.EmployeeBankInformationAgg;
using Company.Domain.RollCallAgg.DomainService;
using CompanyManagment.App.Contracts.Bank;
using CompanyManagment.App.Contracts.EmployeeBankInformation;
using Company.Domain.EmployeeDocumentItemAgg;
using Company.Domain.EmployeeDocumentsAdminSelectionAgg;
using Company.Domain.EmployeeDocumentsAgg;
using CompanyManagement.Infrastructure.Excel.SalaryAid;
using CompanyManagment.App.Contracts.EmployeeDocuments;
using CompanyManagment.App.Contracts.EmployeeDocumentsAdminSelection;
using Company.Domain.EmployeeClientTempAgg;
using Company.Domain.InstitutionPlanAgg;
using Company.Domain.LeftWorkTempAgg;
using Company.Domain.TemporaryClientRegistrationAgg;
using CompanyManagment.App.Contracts.EmployeeClientTemp;
using CompanyManagment.App.Contracts.InstitutionPlan;
using CompanyManagment.App.Contracts.LeftWorkTemp;
using CompanyManagment.App.Contracts.TemporaryClientRegistration;
using Company.Domain.ContactUsAgg;
using CompanyManagment.App.Contracts.ContactUs;
using Company.Domain.EmployeeAuthorizeTempAgg;
using Company.Domain.AdminMonthlyOverviewAgg;
using Company.Domain.AuthorizedBankDetailsAgg;
using Company.Domain.ContractingPartyBankAccountsAgg;
using Company.Domain.PaymentInstrumentAgg;
using Company.Domain.PaymentTransactionAgg;
using Company.Domain.FinancialInvoiceAgg;
using CompanyManagment.App.Contracts.AdminMonthlyOverview;
using CompanyManagment.App.Contracts.ContractingPartyBankAccounts;
using CompanyManagment.App.Contracts.PaymentInstrument;
using CompanyManagment.App.Contracts.PaymentTransaction;
using CompanyManagment.App.Contracts.AuthorizedPerson;
using Company.Domain.AuthorizedPersonAgg;
using Company.Domain.EmployeeFaceEmbeddingAgg;
using Company.Domain.InstitutionContractExtensionTempAgg;
using Company.Domain.LawAgg;
using CompanyManagement.Infrastructure.Mongo.EmployeeFaceEmbeddingRepo;
using CompanyManagement.Infrastructure.Mongo.InstitutionContractInsertTempRepo;
using CompanyManagment.App.Contracts.EmployeeFaceEmbedding;
using CompanyManagment.App.Contracts.Law;
using CompanyManagment.EFCore.Repository;
using CompanyManagment.App.Contracts.FinancialInvoice;
using _0_Framework.Application.FaceEmbedding;
using _0_Framework.Infrastructure;
using _0_Framework.InfraStructure;
using CompanyManagment.App.Contracts.PaymentCallback;
using CompanyManagment.App.Contracts.SepehrPaymentGateway;
using Company.Domain.CameraBugReportAgg;
using CompanyManagment.App.Contracts.CameraBugReport;
using CompanyManagement.Infrastructure.Mongo.CameraBugReportRepo;
using CameraBugReportRepository = CompanyManagement.Infrastructure.Mongo.CameraBugReportRepo.CameraBugReportRepository;
using Company.Domain._common;
using CompanyManagment.EFCore._common;
using CompanyManagment.EFCore.Services;
using Shared.Contracts.Holidays;
@@ -622,6 +484,8 @@ public class PersonalBootstrapper
services.AddTransient<IPaymentTransactionRepository, PaymentTransactionRepository>();
services.AddTransient<IPaymentTransactionApplication, PaymentTransactionApplication>();
services.AddTransient<IPaymentCallbackHandler, PaymentCallbackHandler>();
services.AddTransient<ISepehrPaymentGatewayService, SepehrPaymentGatewayService>();
services.AddTransient<IContractingPartyBankAccountsApplication, ContractingPartyBankAccountsApplication>();
services.AddTransient<IContractingPartyBankAccountsRepository, ContractingPartyBankAccountsRepository>();

View File

@@ -0,0 +1,52 @@
using System.Linq;
using GozareshgirProgramManager.Application._Common.Interfaces;
using GozareshgirProgramManager.Application._Common.Models;
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
using GozareshgirProgramManager.Domain.ProjectAgg.Enums;
using Microsoft.EntityFrameworkCore;
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.AutoUpdateDeployStatus;
public record AutoUpdateDeployStatusCommand : IBaseCommand;
public class AutoUpdateDeployStatusCommandHandler : IBaseCommandHandler<AutoUpdateDeployStatusCommand>
{
private readonly IProgramManagerDbContext _dbContext;
public AutoUpdateDeployStatusCommandHandler(IProgramManagerDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<OperationResult> Handle(AutoUpdateDeployStatusCommand request,
CancellationToken cancellationToken)
{
// Fetch all sections whose phase is still marked as not completed
var sections = await _dbContext.TaskSections
.Include(ts => ts.Task)
.ThenInclude(t => t.Phase)
.Where(ts => ts.Task.Phase.DeployStatus == ProjectDeployStatus.NotCompleted)
.ToListAsync(cancellationToken);
if (sections.Count == 0)
return OperationResult.Success();
var phasesToUpdate = sections
.GroupBy(ts => ts.Task.PhaseId)
.Where(g => g.All(s => s.Status == TaskSectionStatus.Completed))
.Select(g => g.First().Task.Phase)
.Distinct()
.ToList();
if (phasesToUpdate.Count == 0)
return OperationResult.Success();
foreach (var phase in phasesToUpdate)
{
phase.UpdateDeployStatus(ProjectDeployStatus.PendingDevDeploy);
}
await _dbContext.SaveChangesAsync(cancellationToken);
return OperationResult.Success();
}
}

View File

@@ -0,0 +1,44 @@
using GozareshgirProgramManager.Application._Common.Interfaces;
using GozareshgirProgramManager.Application._Common.Models;
using GozareshgirProgramManager.Domain._Common;
using GozareshgirProgramManager.Domain.ProjectAgg.Entities;
using GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
namespace GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeDeployStatusProject;
public record ChangeDeployStatusProjectCommand(Guid PhaseId, ProjectDeployStatus Status):IBaseCommand;
public class ChangeDeployStatusProjectCommandHandler : IBaseCommandHandler<ChangeDeployStatusProjectCommand>
{
private readonly IProjectRepository _projectRepository;
private readonly IProjectPhaseRepository _projectPhaseRepository;
private readonly IUnitOfWork _unitOfWork;
public ChangeDeployStatusProjectCommandHandler(IProjectRepository projectRepository, IUnitOfWork unitOfWork, IProjectPhaseRepository projectPhaseRepository)
{
_projectRepository = projectRepository;
_unitOfWork = unitOfWork;
_projectPhaseRepository = projectPhaseRepository;
}
public async Task<OperationResult> Handle(ChangeDeployStatusProjectCommand request, CancellationToken cancellationToken)
{
var project = await _projectPhaseRepository.GetByIdAsync(request.PhaseId, cancellationToken);
if (project == null)
return OperationResult.NotFound("بخش مورد نظر یافت نشد");
if (project.DeployStatus == ProjectDeployStatus.NotCompleted)
{
return OperationResult.Failure("وضعیت استقرار نمی‌تواند از حالت 'تایید نشده' تغییر کند.");
}
if (request.Status == ProjectDeployStatus.NotCompleted)
{
return OperationResult.Failure("وضعیت استقرار نمی‌تواند به حالت 'تایید نشده' تغییر کند.");
}
project.UpdateDeployStatus(request.Status);
await _unitOfWork.SaveChangesAsync(cancellationToken);
return OperationResult.Success();
}
}

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,113 @@
using System.Security.AccessControl;
using GozareshgirProgramManager.Application._Common.Interfaces;
using GozareshgirProgramManager.Application._Common.Models;
using Microsoft.EntityFrameworkCore;
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectDeployBoardDetail;
public record ProjectDeployBoardDetailsResponse(
ProjectDeployBoardDetailPhaseItem Phase,
List<ProjectDeployBoardDetailTaskItem> Tasks);
public record ProjectDeployBoardDetailPhaseItem(
string Name,
TimeSpan TotalTimeSpan,
TimeSpan DoneTimeSpan);
public record ProjectDeployBoardDetailTaskItem(
string Name,
TimeSpan TotalTimeSpan,
TimeSpan DoneTimeSpan,
List<ProjectDeployBoardDetailItemSkill> Skills)
: ProjectDeployBoardDetailPhaseItem(Name, TotalTimeSpan, DoneTimeSpan);
public record ProjectDeployBoardDetailItemSkill(string OriginalUserFullName, string SkillName, int TimePercentage);
public record ProjectDeployBoardDetailsQuery(Guid PhaseId) : IBaseQuery<ProjectDeployBoardDetailsResponse>;
public class
ProjectDeployBoardDetailsQueryHandler : IBaseQueryHandler<ProjectDeployBoardDetailsQuery,
ProjectDeployBoardDetailsResponse>
{
private readonly IProgramManagerDbContext _dbContext;
public ProjectDeployBoardDetailsQueryHandler(IProgramManagerDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<OperationResult<ProjectDeployBoardDetailsResponse>> Handle(ProjectDeployBoardDetailsQuery request,
CancellationToken cancellationToken)
{
var phase = await _dbContext.ProjectPhases
.Include(x => x.Tasks)
.ThenInclude(x => x.Sections)
.ThenInclude(x => x.Activities)
.Include(x => x.Tasks)
.ThenInclude(x => x.Sections)
.ThenInclude(x => x.AdditionalTimes)
.Include(x => x.Tasks)
.ThenInclude(x => x.Sections)
.ThenInclude(x => x.Skill)
.FirstOrDefaultAsync(x => x.Id == request.PhaseId, cancellationToken);
if (phase == null)
return OperationResult<ProjectDeployBoardDetailsResponse>.NotFound("بخش اصلی مورد نظر یافت نشد");
var userIds = phase.Tasks
.SelectMany(t => t.Sections)
.Select(s => s.OriginalAssignedUserId)
.Distinct()
.ToList();
var usersDict = await _dbContext.Users
.Where(x => userIds.Contains(x.Id))
.ToDictionaryAsync(x => x.Id, x => x.FullName, cancellationToken);
var tasksRes = phase.Tasks.Select(t =>
{
var totalTime = t.Sections.Select(s => s.FinalEstimatedHours)
.Aggregate(TimeSpan.Zero, (sum, next) => sum.Add(next));
var doneTime = t.Sections.Aggregate(TimeSpan.Zero,
(sum, next) => sum.Add(next.GetTotalTimeSpent()));
var skills = t.Sections
.Select(s =>
{
var originalUserFullName = usersDict.GetValueOrDefault(s.OriginalAssignedUserId,
"کاربر ناشناس");
var skillName = s.Skill?.Name ?? "بدون مهارت";
var totalTimeSpent = s.GetTotalTimeSpent();
var timePercentage = s.FinalEstimatedHours.Ticks > 0
? (int)((totalTimeSpent.Ticks / (double)s.FinalEstimatedHours.Ticks) * 100)
: 0;
return new ProjectDeployBoardDetailItemSkill(
originalUserFullName,
skillName,
timePercentage);
}).ToList();
return new ProjectDeployBoardDetailTaskItem(
t.Name,
totalTime,
doneTime,
skills);
}).ToList();
var totalTimeSpan = tasksRes.Aggregate(TimeSpan.Zero,
(sum, next) => sum.Add(next.TotalTimeSpan));
var doneTimeSpan = tasksRes.Aggregate(TimeSpan.Zero,
(sum, next) => sum.Add(next.DoneTimeSpan));
var phaseRes = new ProjectDeployBoardDetailPhaseItem(phase.Name, totalTimeSpan, doneTimeSpan);
var res = new ProjectDeployBoardDetailsResponse(phaseRes, tasksRes);
return OperationResult<ProjectDeployBoardDetailsResponse>.Success(res);
}
}

View File

@@ -0,0 +1,11 @@
using FluentValidation;
namespace GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectDeployBoardDetail;
public class ProjectDeployBoardDetailsQueryValidator:AbstractValidator<ProjectDeployBoardDetailsQuery>
{
public ProjectDeployBoardDetailsQueryValidator()
{
RuleFor(x=>x.PhaseId).NotNull().WithMessage("شناسه بخش اصلی نمی‌تواند خالی باشد");
}
}

View File

@@ -0,0 +1,74 @@
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 Guid Id { get; set; }
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 ProjectDeployStatus DeployStatus { 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.Activities)
.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
&& x.InitialEstimatedHours>TimeSpan.Zero))
.GroupBy(x=>x.Task.PhaseId).ToListAsync(cancellationToken: cancellationToken);
var list = query.Select(g => new ProjectDeployBoardListItem
{
Id = g.Key,
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.FromTicks(g.Sum(x => x.InitialEstimatedHours.Ticks)),
DoneTimeSpan = TimeSpan.FromTicks(g.Sum(x=>x.GetTotalTimeSpent().Ticks)),
DeployStatus = g.First().Task.Phase.DeployStatus
}).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,30 @@ public class ProjectPhase : ProjectHierarchyNode
}
#endregion
public void SetArchived()
{
IsArchived = true;
}
public void SetUnarchived()
{
IsArchived = false;
}
public void UpdateDeployStatus(ProjectDeployStatus status)
{
DeployStatus = status;
if (status == ProjectDeployStatus.Deployed)
{
IsArchived = true;
}
}
}
public enum ProjectDeployStatus
{
NotCompleted,
PendingDevDeploy,
DevDeployed,
PendingDeploy,
Deployed
}

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

@@ -5,7 +5,6 @@ namespace GozareshgirProgramManager.Domain.ProjectAgg.Repositories;
public interface ITaskSectionActivityRepository:IRepository<Guid,TaskSectionActivity>
{
Task<TaskSectionActivity?> GetByIdAsync(Guid id);
Task<List<TaskSectionActivity>> GetBySectionIdAsync(Guid sectionId);
Task<List<TaskSectionActivity>> GetByUserIdAsync(long userId);
Task<List<TaskSectionActivity>> GetActiveByUserAsync(long userId);

View File

@@ -5,7 +5,7 @@ namespace GozareshgirProgramManager.Domain._Common;
public interface IRepository<TKey, T> where T:class
{
T Get(TKey id);
Task<T?> GetByIdAsync(TKey id);
Task<T?> GetByIdAsync(TKey id, CancellationToken cancellationToken = default);
List<T> Get();
IQueryable<T> GetQueryable();
void Create(T entity);

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

@@ -43,9 +43,9 @@ public class RepositoryBase<TKey, T> : IRepository<TKey, T> where T : class
return _context.Find<T>(id);
}
public async Task<T?> GetByIdAsync(TKey id)
public async Task<T?> GetByIdAsync(TKey id, CancellationToken cancellationToken = default)
{
return await _context.Set<T>().FindAsync(id);
return await _context.Set<T>().FindAsync([id], cancellationToken);
}
public List<T> Get()

View File

@@ -2,6 +2,8 @@
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.AutoUpdateDeployStatus;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeDeployStatusProject;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.ChangeStatusSection;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.CreateProject;
using GozareshgirProgramManager.Application.Modules.Projects.Commands.DeleteProject;
@@ -12,6 +14,8 @@ 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.ProjectDeployBoardDetail;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectDeployBoardList;
using GozareshgirProgramManager.Application.Modules.Projects.Queries.ProjectSetTimeDetails;
using MediatR;
using Microsoft.AspNetCore.Mvc;
@@ -22,70 +26,75 @@ namespace ServiceHost.Areas.Admin.Controllers.ProgramManager;
public class ProjectController : ProgramManagerBaseController
{
private readonly IMediator _mediator;
public ProjectController(IMediator mediator)
{
_mediator = mediator;
}
[HttpGet]
public async Task<ActionResult<OperationResult<GetProjectsListResponse>>> Get([FromQuery]GetProjectsListQuery query)
public async Task<ActionResult<OperationResult<GetProjectsListResponse>>> Get(
[FromQuery] GetProjectsListQuery query)
{
var res=await _mediator.Send(query);
var res = await _mediator.Send(query);
return res;
}
[HttpPost]
public async Task<ActionResult<OperationResult>> Create([FromBody] CreateProjectCommand command)
{
var res=await _mediator.Send(command);
var res = await _mediator.Send(command);
return res;
}
[HttpPut]
public async Task<ActionResult<OperationResult>> Edit([FromBody] EditProjectCommand command)
{
var res=await _mediator.Send(command);
var res = await _mediator.Send(command);
return res;
}
[HttpDelete]
public async Task<ActionResult<OperationResult>> Delete([FromQuery] DeleteProjectCommand command)
{
var res=await _mediator.Send(command);
var res = await _mediator.Send(command);
return res;
}
[HttpGet("assign")]
public async Task<ActionResult<OperationResult<GetProjectAssignDetailsResponse>>> GetAssignableProjects(GetProjectAssignDetailsQuery query)
public async Task<ActionResult<OperationResult<GetProjectAssignDetailsResponse>>> GetAssignableProjects(
GetProjectAssignDetailsQuery query)
{
var res=await _mediator.Send(query);
var res = await _mediator.Send(query);
return res;
}
[HttpPost("assign")]
public async Task<ActionResult<OperationResult>> Assign(AssignProjectCommand command)
{
var res=await _mediator.Send(command);
var res = await _mediator.Send(command);
return res;
}
[HttpGet("set-time")]
public async Task<ActionResult<OperationResult<ProjectSetTimeResponse>>> GetSetTimeProjectDetails(ProjectSetTimeDetailsQuery query)
public async Task<ActionResult<OperationResult<ProjectSetTimeResponse>>> GetSetTimeProjectDetails(
ProjectSetTimeDetailsQuery query)
{
var res=await _mediator.Send(query);
var res = await _mediator.Send(query);
return res;
}
[HttpPost("set-time")]
public async Task<ActionResult<OperationResult>> SetTimeProject(SetTimeProjectCommand command)
{
var res=await _mediator.Send(command);
var res = await _mediator.Send(command);
return res;
}
[HttpPost("change-status")]
public async Task<ActionResult<OperationResult>> ChangeStatus(ChangeStatusSectionCommand command)
{
var res = await _mediator.Send(command);
var res = await _mediator.Send(command);
return res;
}
@@ -97,14 +106,16 @@ public class ProjectController : ProgramManagerBaseController
}
[HttpGet("board")]
public async Task<ActionResult<OperationResult<List<ProjectBoardListResponse>>>> GetProjectBoard([FromQuery] ProjectBoardListQuery query)
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;
}
[HttpGet("board/details")]
public async Task<ActionResult<OperationResult<ProjectBoardDetailResponse>>> GetProjectBoardDetails(Guid id)
{
@@ -112,4 +123,28 @@ public class ProjectController : ProgramManagerBaseController
var res = await _mediator.Send(query);
return res;
}
[HttpGet("deploy-board")]
public async Task<ActionResult<OperationResult<GetProjectsDeployBoardListResponse>>> GetProjectDeployBoard()
{
// قبل از دریافت دیتا، وضعیت دیپلوی را بر اساس تکمیل شدن تمام سکشن‌ها به‌روزرسانی می‌کنیم
await _mediator.Send(new AutoUpdateDeployStatusCommand());
var request = new GetProjectDeployBoardListQuery();
return await _mediator.Send(request);
}
[HttpGet("deploy-board/details")]
public async Task<ActionResult<OperationResult<ProjectDeployBoardDetailsResponse>>> GetProjectDeployBoardDetails(Guid id)
{
var query = new ProjectDeployBoardDetailsQuery(id);
var res = await _mediator.Send(query);
return res;
}
[HttpPost("deploy-board/change-status")]
public async Task<ActionResult<OperationResult>> ChangeDeployStatus(ChangeDeployStatusProjectCommand command)
{
var res = await _mediator.Send(command);
return res;
}
}

View File

@@ -40,16 +40,15 @@ public class institutionContractController : AdminBaseController
private readonly ITemporaryClientRegistrationApplication _clientRegistrationApplication;
private readonly IPaymentGateway _paymentGateway;
private static readonly ConcurrentDictionary<Guid, SemaphoreSlim> _locks
private static readonly ConcurrentDictionary<Guid, SemaphoreSlim> _locks
= new ConcurrentDictionary<Guid, SemaphoreSlim>();
public institutionContractController(IInstitutionContractApplication institutionContractApplication,
IPersonalContractingPartyApp contractingPartyApplication, IContactInfoApplication contactInfoApplication,
IAccountApplication accountApplication, IEmployerApplication employerApplication,
IWorkshopApplication workshopApplication, ITemporaryClientRegistrationApplication temporaryClientRegistration,
ITemporaryClientRegistrationApplication clientRegistrationApplication,IHttpClientFactory httpClientFactory)
ITemporaryClientRegistrationApplication clientRegistrationApplication, IHttpClientFactory httpClientFactory)
{
_institutionContractApplication = institutionContractApplication;
_contractingPartyApplication = contractingPartyApplication;
@@ -72,12 +71,13 @@ public class institutionContractController : AdminBaseController
{
return await _institutionContractApplication.GetList(searchModel);
}
[HttpGet("select-list")]
public async Task<ActionResult<List<InstitutionContractSelectListViewModel>>> GetContractingPartySelectList(string search,string selected)
public async Task<ActionResult<List<InstitutionContractSelectListViewModel>>> GetContractingPartySelectList(
string search, string selected)
{
var result = await _institutionContractApplication
.GetInstitutionContractSelectList(search,selected);
.GetInstitutionContractSelectList(search, selected);
return result;
}
@@ -225,9 +225,8 @@ public class institutionContractController : AdminBaseController
{
_institutionContractApplication.RemoveContract(id);
return new OperationResult().Succcedded();
}
[HttpPost("deActive/{id}")]
public ActionResult<OperationResult> DeActive(long id, string balance)
{
@@ -235,7 +234,8 @@ public class institutionContractController : AdminBaseController
if (balance == "0")
{
result = _institutionContractApplication.DeActive(id);
if (result.IsSuccedded) result = _institutionContractApplication.DeActiveAllConnections(id);
if (result.IsSuccedded)
result = _institutionContractApplication.DeActiveAllConnections(id);
}
else
{
@@ -332,24 +332,9 @@ public class institutionContractController : AdminBaseController
});
}
/// <summary>
/// دانلود اکسل
/// </summary>
/// <returns></returns>
[HttpGet("excel")]
public IActionResult OnGetDownloadExcel()
{
var institutionContractViewModels =
_institutionContractApplication.NewSearch(new() { IsActiveString = "both", TypeOfContract = "both" });
var bytes = InstitutionContractExcelGenerator.GenerateExcel(new List<InstitutionContractExcelViewModel>());
return File(bytes,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
$"قرارداد های مالی.xlsx");
}
[HttpPost("create/inquiry")]
public async Task<ActionResult<OperationResult<ContractingPartyTempViewModel>>> CreateInquiry(
[FromBody] CreateInquiryRequest request)
[FromBody] InstitutionContractCreationInquiryRequest request)
{
var res = await _temporaryClientRegistration.CreateContractingPartyTemp(request.NationalCode,
request.DateOfBirth,
@@ -358,7 +343,8 @@ public class institutionContractController : AdminBaseController
}
[HttpPost("workshop-service-calculator")]
public ActionResult<WorkshopServiceCalculatorResponse> WorkshopServiceCalculator([FromBody]CreateWorkshopTemp command)
public ActionResult<WorkshopServiceCalculatorResponse> WorkshopServiceCalculator(
[FromBody] CreateWorkshopTemp command)
{
var workshopTemp = new WorkshopTempViewModel
{
@@ -373,7 +359,7 @@ public class institutionContractController : AdminBaseController
};
var response = _temporaryClientRegistration.GetInstitutionPlanForWorkshop(workshopTemp);
var result = new WorkshopServiceCalculatorResponse
{
TotalAmount = response.OnlineAndInPersonSumAmountStr
@@ -385,7 +371,8 @@ public class institutionContractController : AdminBaseController
public async Task<ActionResult<InstitutionPlanCalculatorResponse>> InstitutionPlanCalculator(
[FromBody] InstitutionPlanCalculatorRequest request)
{
var res = await _temporaryClientRegistration.GetTotalPaymentAndWorkshopList(request.TotalAmountMonth,duration: request.Duration,request.HasInPersonContract);
var res = await _temporaryClientRegistration.GetTotalPaymentAndWorkshopList(request.TotalAmountMonth,
duration: request.Duration, request.HasInPersonContract);
var result = new InstitutionPlanCalculatorResponse()
{
TotalAmountWithTax = res.OneTimeTotalPaymentStr,
@@ -403,7 +390,6 @@ public class institutionContractController : AdminBaseController
Obligation = res.OneTimeTotalPaymentStr,
PaymentForOneMonth = res.SumOfWorkshopsPayment,
DiscountedAmountForOneMonth = res.DiscountedAmountForOneMonth
};
return result;
}
@@ -414,13 +400,13 @@ public class institutionContractController : AdminBaseController
/// <param name="command"></param>
/// <returns></returns>
[HttpPost]
public async Task<ActionResult<OperationResult>> Create([FromBody]CreateInstitutionContractRequest command)
public async Task<ActionResult<OperationResult>> Create([FromBody] CreateInstitutionContractRequest command)
{
var res =await _institutionContractApplication.CreateAsync(command);
if(!res.IsSuccedded)
var res = await _institutionContractApplication.CreateAsync(command);
if (!res.IsSuccedded)
throw new BadRequestException(res.Message);
return res;
}
@@ -448,22 +434,26 @@ public class institutionContractController : AdminBaseController
if (operationResult.IsSuccedded)
transaction.Complete();
return operationResult;
}
[HttpPost("create/set-discount")]
public ActionResult<InstitutionContractDiscountResponse> SetDiscountForInstitutionContract([FromBody]InstitutionContractSetDiscountRequest request)
public ActionResult<InstitutionContractDiscountResponse> SetDiscountForInstitutionContract(
[FromBody] InstitutionContractSetDiscountRequest request)
{
var res = _institutionContractApplication.CalculateDiscount(request);
return res;
}
[HttpPost("create/reset-discount")]
public ActionResult<InstitutionContractDiscountResponse> ResetDiscountForCreate([FromBody]InstitutionContractResetDiscountForCreateRequest request)
public ActionResult<InstitutionContractDiscountResponse> ResetDiscountForCreate(
[FromBody] InstitutionContractResetDiscountForCreateRequest request)
{
var res = _institutionContractApplication.ResetDiscountCreate(request);
return res;
}
/// <summary>
///
/// </summary>
@@ -484,15 +474,15 @@ public class institutionContractController : AdminBaseController
var paymentRedirectUrl = Url.Action("ProcessPayment", "institutionContract", null, Request.Scheme);
var callback = Url.Action("Verify", "General", null, Request.Scheme);
var res = await _institutionContractApplication.VerifyOtpAndMakeGateway(command.Id, command.Code, callback);
if (!res.IsSuccedded)
return new OperationResult<string>().Failed(res.Message);
var payUrl = _paymentGateway.GetStartPayUrl(res.Data);
// URL کامل برای redirect شامل paymentUrl به عنوان query parameter
var redirectUrl = $"{paymentRedirectUrl}?paymentUrl={Uri.EscapeDataString(payUrl)}";
return new OperationResult<string>().Succcedded(redirectUrl);
}
@@ -504,13 +494,12 @@ public class institutionContractController : AdminBaseController
{
return BadRequest("Payment URL is required");
}
// redirect به درگاه پرداخت
return Redirect(paymentUrl);
}
[HttpPost("/api/institutionContract/Verification/{id:guid}/send-otp")]
[AllowAnonymous]
public async Task<ActionResult<OperationResult<OtpResultViewModel>>> SendVerifyOtp(Guid id)
@@ -528,97 +517,177 @@ public class institutionContractController : AdminBaseController
}
}
#region Create
[HttpPost("creation/inquiry")]
public async Task<ActionResult<InstitutionContractCreationInquiryResult>> CreationInquiry(
InstitutionContractCreationInquiryRequest request)
{
var res = await _institutionContractApplication.CreationInquiry(request);
return res;
}
[HttpGet("creation/get-representative")]
public async Task<ActionResult<InstitutionContractCreationGetRepresentativeIdResponse>> GetRepresentatives(string nationalCode)
{
var res = await _contractingPartyApplication.GetRepresentativeIdByNationalCode(nationalCode);
return new InstitutionContractCreationGetRepresentativeIdResponse()
{
RepresentativeId = res
};
}
[HttpPost("creation/workshops")]
public async Task<ActionResult<InstitutionContractCreationWorkshopsResponse>> CreationWorkshops(
[FromBody] InstitutionContractCreationWorkshopsRequest request)
{
var res = await _institutionContractApplication.GetCreationWorkshops(request);
return res;
}
[HttpPost("creation/institution-plan")]
public async Task<ActionResult<InstitutionContractCreationPlanResponse>> CreationInstitutionPlan(
[FromBody] InstitutionContractCreationPlanRequest request)
{
var res = await _institutionContractApplication.GetCreationInstitutionPlan(request);
return res;
}
[HttpPost("creation/payment-method")]
public async Task<ActionResult<InstitutionContractCreationPaymentResponse>> GetCreationPaymentMethod(
[FromBody] InstitutionContractCreationPaymentRequest request)
{
var res = await _institutionContractApplication.GetCreationPaymentMethod(request);
return res;
}
[HttpPost("creation/set-discount")]
public async Task<ActionResult<InstitutionContractDiscountResponse>> SetDiscountForCreation(
[FromBody] InstitutionContractSetDiscountForCreationRequest request)
{
var res = await _institutionContractApplication.SetDiscountForCreation(request);
return res;
}
[HttpPost("creation/reset-discount")]
public async Task<ActionResult<InstitutionContractDiscountResponse>> ResetDiscountForCreation(
[FromBody] InstitutionContractResetDiscountForExtensionRequest request)
{
var res = await _institutionContractApplication.ResetDiscountForCreation(request);
return res;
}
[HttpPost("creation/complete")]
public async Task<ActionResult<OperationResult>> CreationComplete(
[FromBody] InstitutionContractExtensionCompleteRequest request)
{
var res = await _institutionContractApplication.CreationComplete(request);
return res;
}
#endregion
[HttpGet("extenstion/inquiry/{previousContractId}")]
public async Task<ActionResult<InstitutionContractExtensionInquiryResult>> ExtensionInquiry(long previousContractId)
{
var res= await _institutionContractApplication.GetExtensionInquiry(previousContractId);
var res = await _institutionContractApplication.GetExtensionInquiry(previousContractId);
return res;
}
[HttpPost("extenstion/workshops")]
public async Task<ActionResult<InstitutionContractExtensionWorkshopsResponse>> ExtensionWorkshops([FromBody] InstitutionContractExtensionWorkshopsRequest request)
public async Task<ActionResult<InstitutionContractExtensionWorkshopsResponse>> ExtensionWorkshops(
[FromBody] InstitutionContractExtensionWorkshopsRequest request)
{
var res =await _institutionContractApplication.GetExtensionWorkshops(request);
var res = await _institutionContractApplication.GetExtensionWorkshops(request);
return res;
}
[HttpPost("extenstion/institution-plan")]
public async Task<ActionResult<InstitutionContractExtensionPlanResponse>> ExtensionInstitutionPlan([FromBody]InstitutionContractExtensionPlanRequest request)
public async Task<ActionResult<InstitutionContractExtensionPlanResponse>> ExtensionInstitutionPlan(
[FromBody] InstitutionContractExtensionPlanRequest request)
{
var res =await _institutionContractApplication.GetExtensionInstitutionPlan(request);
var res = await _institutionContractApplication.GetExtensionInstitutionPlan(request);
return res;
}
[HttpPost("extenstion/payment-method")]
public async Task<ActionResult<InstitutionContractExtensionPaymentResponse>> GetExtensionPaymentMethod([FromBody]InstitutionContractExtensionPaymentRequest request)
public async Task<ActionResult<InstitutionContractExtensionPaymentResponse>> GetExtensionPaymentMethod(
[FromBody] InstitutionContractExtensionPaymentRequest request)
{
var res =await _institutionContractApplication.GetExtensionPaymentMethod(request);
var res = await _institutionContractApplication.GetExtensionPaymentMethod(request);
return res;
}
[HttpPost("extension/set-discount")]
public async Task<ActionResult<InstitutionContractDiscountResponse>> SetDiscountForExtension([FromBody]InstitutionContractSetDiscountForExtensionRequest request)
public async Task<ActionResult<InstitutionContractDiscountResponse>> SetDiscountForExtension(
[FromBody] InstitutionContractSetDiscountForExtensionRequest request)
{
var res =await _institutionContractApplication.SetDiscountForExtension(request);
var res = await _institutionContractApplication.SetDiscountForExtension(request);
return res;
}
[HttpPost("extension/reset-discount")]
public async Task<ActionResult<InstitutionContractDiscountResponse>> ResetDiscountForExtension([FromBody]InstitutionContractResetDiscountForExtensionRequest request)
public async Task<ActionResult<InstitutionContractDiscountResponse>> ResetDiscountForExtension(
[FromBody] InstitutionContractResetDiscountForExtensionRequest request)
{
var res =await _institutionContractApplication.ResetDiscountForExtension(request);
var res = await _institutionContractApplication.ResetDiscountForExtension(request);
return res;
}
[HttpPost("extenstion/complete")]
public async Task<ActionResult<OperationResult>> ExtensionComplete([FromBody]InstitutionContractExtensionCompleteRequest request)
public async Task<ActionResult<OperationResult>> ExtensionComplete(
[FromBody] InstitutionContractExtensionCompleteRequest request)
{
var res =await _institutionContractApplication.ExtensionComplete(request);
var res = await _institutionContractApplication.ExtensionComplete(request);
return res;
}
[HttpGet("amendment/workshops/{institutionContractId}")]
public async Task<ActionResult<InstitutionContractAmendmentWorkshopsResponse>> GetAmendmentWorkshops(long institutionContractId)
public async Task<ActionResult<InstitutionContractAmendmentWorkshopsResponse>> GetAmendmentWorkshops(
long institutionContractId)
{
var res =await _institutionContractApplication.GetAmendmentWorkshops(institutionContractId);
var res = await _institutionContractApplication.GetAmendmentWorkshops(institutionContractId);
return res;
}
[HttpPost("resend-verify-link/{institutionContractId}")]
public async Task<OperationResult> ResendVerifyLink(long institutionContractId)
{
var res = await _institutionContractApplication.ResendVerifyLink(institutionContractId);
return res;
}
[HttpPost("amendment/insert-temp-workshops")]
public async Task<ActionResult<InsertAmendmentTempWorkshopResponse>> InsertAmendmentTempWorkshops([FromBody]InstitutionContractAmendmentTempWorkshopViewModel request)
public async Task<ActionResult<InsertAmendmentTempWorkshopResponse>> InsertAmendmentTempWorkshops(
[FromBody] InstitutionContractAmendmentTempWorkshopViewModel request)
{
var res =await _institutionContractApplication.InsertAmendmentTempWorkshops(request);
var res = await _institutionContractApplication.InsertAmendmentTempWorkshops(request);
return res;
}
[HttpDelete("amendment/remove-temp-workshops/{workshopTempId:guid}")]
public async Task<ActionResult> RemoveAmendmentWorkshops(Guid workshopTempId)
{
{
await _institutionContractApplication.RemoveAmendmentWorkshops(workshopTempId);
return Ok();
}
[HttpPost("amendment/payment-details")]
public async Task<ActionResult<InsitutionContractAmendmentPaymentResponse>> GetAmendmentPaymentDetails([FromBody]InsitutionContractAmendmentPaymentRequest request)
public async Task<ActionResult<InsitutionContractAmendmentPaymentResponse>> GetAmendmentPaymentDetails(
[FromBody] InsitutionContractAmendmentPaymentRequest request)
{
var res =await _institutionContractApplication.GetAmendmentPaymentDetails(request);
var res = await _institutionContractApplication.GetAmendmentPaymentDetails(request);
return res;
}
[HttpGet("edit-old/{id}")]
public ActionResult<EditInstitutionContract> GetEditOldDetails(long id)
public ActionResult<EditInstitutionContract> GetEditOldDetails(long id)
{
var representativList = new List<RepresentativeViewModel>();
var contractingPartyList = new List<PersonalContractingPartyViewModel>();
var res = _institutionContractApplication.GetDetails(id);
var representative = new RepresentativeViewModel
{
Id = res.RepresentativeId,
@@ -683,13 +752,14 @@ public class institutionContractController : AdminBaseController
res.ContractAmountOAlone = res.ContractAmountString;
res.ValueAddedTaxStr = "0";
}
return res;
}
[HttpPost("edit-old")]
public ActionResult<OperationResult> EditOld([FromBody] EditInstitutionContract command)
{
var op = new OperationResult();
var op = new OperationResult();
var phoneNumber = command.ContactInformationList.FirstOrDefault(x =>
x.SendSmsString == "true" && x.Position == "طرف قرارداد" && x.PhoneType == "شماره همراه");
var conractingParty = _contractingPartyApplication.GetDetails(command.ContractingPartyId);
@@ -703,57 +773,58 @@ public class institutionContractController : AdminBaseController
//if (string.IsNullOrWhiteSpace(command.HasValueAddedTax))
// command.HasValueAddedTax = "false";
var result = _institutionContractApplication.Edit(command);
var contractingPartyId = _institutionContractApplication.GetDetails(result.SendId);
var counter = command.ContactInformationList.Count;
var getOldContarct = _institutionContractApplication.NewSearch(new InstitutionContractSearchModel()
{ ContractingPartyId = contractingPartyId.ContractingPartyId, IsActiveString = "both" }).Where(x=>x.IsActiveString == "false" || x.IsActiveString == "blue").ToList();
if (result.IsSuccedded && counter > 0)
{
if (getOldContarct.Count > 0)
{
foreach (var item in getOldContarct)
{
_contactInfoApplication.RemoveContactInfo(item.Id);
foreach (var phone in command.ContactInformationList)
{
if (phone.PhoneNumber != null)
{
var contactinfo = new CreateContactInfo
{
InstitutionContractId = item.Id,
PhoneType = phone.PhoneType,
Position = phone.Position,
PhoneNumber = phone.PhoneNumber,
FnameLname = phone.FnameLname,
SendSms = phone.SendSmsString == "true" ? true : false
};
_contactInfoApplication.Create(contactinfo);
}
var contractingPartyId = _institutionContractApplication.GetDetails(result.SendId);
var counter = command.ContactInformationList.Count;
var getOldContarct = _institutionContractApplication.NewSearch(new InstitutionContractSearchModel()
{ ContractingPartyId = contractingPartyId.ContractingPartyId, IsActiveString = "both" })
.Where(x => x.IsActiveString == "false" || x.IsActiveString == "blue").ToList();
if (result.IsSuccedded && counter > 0)
{
if (getOldContarct.Count > 0)
{
foreach (var item in getOldContarct)
{
_contactInfoApplication.RemoveContactInfo(item.Id);
foreach (var phone in command.ContactInformationList)
{
if (phone.PhoneNumber != null)
{
var contactinfo = new CreateContactInfo
{
InstitutionContractId = item.Id,
PhoneType = phone.PhoneType,
Position = phone.Position,
PhoneNumber = phone.PhoneNumber,
FnameLname = phone.FnameLname,
SendSms = phone.SendSmsString == "true" ? true : false
};
_contactInfoApplication.Create(contactinfo);
}
Thread.Sleep(500);
}
}
}
_contactInfoApplication.RemoveContactInfo(command.Id);
foreach (var item in command.ContactInformationList)
{
if (item.PhoneNumber != null)
{
var contactinfo = new CreateContactInfo
{
InstitutionContractId = result.SendId,
PhoneType = item.PhoneType,
Position = item.Position,
PhoneNumber = item.PhoneNumber,
FnameLname = item.FnameLname,
SendSms = item.SendSmsString == "true" ? true : false
};
_contactInfoApplication.Create(contactinfo);
}
Thread.Sleep(500);
}
}
}
Thread.Sleep(500);
}
_contactInfoApplication.RemoveContactInfo(command.Id);
foreach (var item in command.ContactInformationList)
{
if (item.PhoneNumber != null)
{
var contactinfo = new CreateContactInfo
{
InstitutionContractId = result.SendId,
PhoneType = item.PhoneType,
Position = item.Position,
PhoneNumber = item.PhoneNumber,
FnameLname = item.FnameLname,
SendSms = item.SendSmsString == "true" ? true : false
};
_contactInfoApplication.Create(contactinfo);
}
Thread.Sleep(500);
}
//ساخت اکانت کلاینت
@@ -763,7 +834,6 @@ public class institutionContractController : AdminBaseController
var checkExistAccount = _accountApplication.CheckExistClientAccount(userPass);
if (!checkExistAccount)
{
var createAcc = new RegisterAccount
{
Fullname = conractingParty.LName,
@@ -774,69 +844,72 @@ public class institutionContractController : AdminBaseController
};
var res = _accountApplication.RegisterClient(createAcc);
if (res.IsSuccedded)
_institutionContractApplication.CreateContractingPartyAccount(command.ContractingPartyId, res.SendId);
_institutionContractApplication.CreateContractingPartyAccount(command.ContractingPartyId,
res.SendId);
}
}
//Thread.Sleep(500);
//for (int i = 0; i <= counter - 1; i++)
//{
// if (command.ContactInformationList[i].PhoneNumber != null)
// {
//Thread.Sleep(500);
//for (int i = 0; i <= counter - 1; i++)
//{
// if (command.ContactInformationList[i].PhoneNumber != null)
// {
// var contactinfo = new CreateContactInfo()
// {
// InstitutionContractId = result.SendId,
// PhoneType = command.ContactInformationList[i].PhoneType,
// Position = command.ContactInformationList[i].Position,
// PhoneNumber = command.ContactInformationList[i].PhoneNumber,
// FnameLname = command.ContactInformationList[i].FnameLname,
// SendSms = command.ContactInformationList[i].SendSmsString == "true" ? true : false
// };
// _contactInfoApplication.Create(contactinfo);
// var contactinfo = new CreateContactInfo()
// {
// InstitutionContractId = result.SendId,
// PhoneType = command.ContactInformationList[i].PhoneType,
// Position = command.ContactInformationList[i].Position,
// PhoneNumber = command.ContactInformationList[i].PhoneNumber,
// FnameLname = command.ContactInformationList[i].FnameLname,
// SendSms = command.ContactInformationList[i].SendSmsString == "true" ? true : false
// };
// _contactInfoApplication.Create(contactinfo);
// }
// Thread.Sleep(500);
//}
// }
// Thread.Sleep(500);
//}
return result;
return result;
}
[HttpGet("print/{id}")]
public async Task<ActionResult<InstitutionContractPrintViewModel>> PrintOne(long id)
{
var res =await _institutionContractApplication.PrintOneAsync(id);
var res = await _institutionContractApplication.PrintOneAsync(id);
return res;
}
[HttpPost("mannual-verify/{id}")]
public async Task<ActionResult<OperationResult>> VerifyInstitutionContractManually(long id)
{
var res= await _institutionContractApplication.VerifyInstitutionContractManually(id);
var res = await _institutionContractApplication.VerifyInstitutionContractManually(id);
return res;
}
[HttpGet("excel-download")]
public async Task<IActionResult> ExcelDownload()
{
var searchModel = new InstitutionContractListSearchModel();
var dataVm=new List<InstitutionContractExcelViewModel>();
var dataVm = new List<InstitutionContractExcelViewModel>();
foreach (var name in typeof(InstitutionContractListStatus).GetEnumNames())
{
var @enum = Enum.Parse<InstitutionContractListStatus>(name);
searchModel.Status = @enum;
searchModel.PageSize = 99999;
var data =( await(_institutionContractApplication.GetList(searchModel))).List;
dataVm.Add(new InstitutionContractExcelViewModel(){Tab = @enum, GetInstitutionContractListItemsViewModels = data});
var data = (await (_institutionContractApplication.GetList(searchModel))).List;
dataVm.Add(new InstitutionContractExcelViewModel()
{ Tab = @enum, GetInstitutionContractListItemsViewModels = data });
}
searchModel.Status = null;
var nullData = ( await(_institutionContractApplication.GetList(searchModel))).List;
dataVm.Add(new InstitutionContractExcelViewModel(){Tab = null, GetInstitutionContractListItemsViewModels = nullData});
var nullData = (await (_institutionContractApplication.GetList(searchModel))).List;
dataVm.Add(new InstitutionContractExcelViewModel()
{ Tab = null, GetInstitutionContractListItemsViewModels = nullData });
var bytes = InstitutionContractExcelGenerator.GenerateExcel(dataVm);
return File(bytes,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
@@ -844,6 +917,10 @@ public class institutionContractController : AdminBaseController
}
}
public class InstitutionContractCreationGetRepresentativeIdResponse
{
public long RepresentativeId { get; set; }
}
public class VerifyOtpRequest
{
@@ -882,16 +959,11 @@ public class WorkshopServiceCalculatorResponse
public string TotalAmount { get; set; }
}
public record InstitutionPlanCalculatorRequest(double TotalAmountMonth,bool HasInPersonContract,
public record InstitutionPlanCalculatorRequest(
double TotalAmountMonth,
bool HasInPersonContract,
InstitutionContractDuration Duration = InstitutionContractDuration.TwelveMonths);
public class CreateInquiryRequest
{
public string NationalCode { get; set; }
public string DateOfBirth { get; set; }
public string Mobile { get; set; }
}
public class VerifyCodeRequest
{
public long ContractingPartyId { get; set; }

View File

@@ -268,10 +268,10 @@
href="#showmodal=@Url.Page("./Index", "Edit", new { Id = item.Id })">
<i class="fa fa-edit faSize"></i>
</a>
<a class="btn btn-success pull-right m-rl-5 red"
href="#showmodal=@Url.Page("./Index", "AccountWorkshop", new { item.Id })">
<i class="fa fa-edit faSize"></i>
</a>
@* <a class="btn btn-success pull-right m-rl-5 red" *@
@* href="#showmodal=@Url.Page("./Index", "AccountWorkshop", new { item.Id })"> *@
@* <i class="fa fa-edit faSize"></i> *@
@* </a> *@
@if (item.IsActiveString == "true" && item.Role != "مدیر سیستم")
{
<a onclick="deActive(@item.Id,'@item.Fullname')" class="btn btn-danger pull-right m-rl-5 red"> <i class="fa faSize fa-trash"></i></a>

View File

@@ -316,14 +316,14 @@ public class IndexModel : PageModel
});
}
public IActionResult OnGetAccountWorkshop(long id)
{
var res = _accountApplication.WorkshopList(id);
return Partial("AccountLeftWork", res);
}
// public IActionResult OnGetAccountWorkshop(long id)
// {
// var res = _accountApplication.WorkshopList(id);
//
//
//
// return Partial("AccountLeftWork", res);
// }
public IActionResult OnPostCreateAccountLeftWork(
List<WorkshopAccountlistViewModel> workshopAccountlistViewModel,

View File

@@ -1,8 +1,10 @@
using _0_Framework.Application;
using _0_Framework.Application.PaymentGateway;
using CompanyManagment.App.Contracts.FinancialInvoice;
using CompanyManagment.App.Contracts.FinancialStatment;
using CompanyManagment.App.Contracts.FinancilTransaction;
using CompanyManagment.App.Contracts.PaymentTransaction;
using CompanyManagment.App.Contracts.SepehrPaymentGateway;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
@@ -10,20 +12,19 @@ using ServiceHost.BaseControllers;
namespace ServiceHost.Areas.Client.Controllers;
public record CreateFinancialPayRequest(long Id, string BaseUrl);
public class FinancialController : ClientBaseController
{
private readonly IFinancialStatmentApplication _financialStatementApplication;
private readonly IAuthHelper _authHelper;
private readonly IPaymentGateway _paymentGateway;
private readonly IPaymentTransactionApplication _paymentTransactionApplication;
private readonly ISepehrPaymentGatewayService _sepehrPaymentGatewayService;
private readonly IFinancialInvoiceApplication _financialInvoiceApplication;
public FinancialController(IFinancialStatmentApplication financialStatementApplication, IAuthHelper authHelper,IHttpClientFactory httpClientFactory, IPaymentTransactionApplication paymentTransactionApplication,IOptions<AppSettingConfiguration> appSetting)
public FinancialController(IFinancialStatmentApplication financialStatementApplication, IAuthHelper authHelper, ISepehrPaymentGatewayService sepehrPaymentGatewayService, IFinancialInvoiceApplication financialInvoiceApplication)
{
_financialStatementApplication = financialStatementApplication;
_authHelper = authHelper;
_paymentTransactionApplication = paymentTransactionApplication;
_paymentGateway = new AqayePardakhtPaymentGateway(httpClientFactory, appSetting);
_sepehrPaymentGatewayService = sepehrPaymentGatewayService;
_financialInvoiceApplication = financialInvoiceApplication;
}
[HttpGet]
@@ -45,64 +46,28 @@ public class FinancialController : ClientBaseController
return result;
}
/// <summary>
/// ساخت
/// ساخت درگاه پرداخت برای موجودی حساب کلاینت
/// </summary>
/// <param name="id"></param>
/// <param name="baseUrl"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
[HttpPost("CreatePay")]
[AllowAnonymous]
public async Task<ActionResult<OperationResult<string>>> CreatePay([FromForm] CreateFinancialPayRequest request, CancellationToken cancellationToken)
public async Task<ActionResult<OperationResult<string>>> CreatePay([FromForm] CreateFinancialPayRequest request)
{
var op = new OperationResult<string>();
var balanceAmount = await _financialStatementApplication.GetBalanceAmount(request.Id);
if (balanceAmount.Amount<=0)
{
return op.Failed("موجودی حساب شما صفر است");
}
var callbackUrl = Url.Action(
action: "OnGetCallBack",
var gateWayCallBackUrl = Url.Action(
action: "Verify",
controller: "General", // نام کنترلر بدون کلمه‌ی "Controller"
values: null,
protocol: Request.Scheme); // http یا https
// گام 2: ایجاد درگاه پرداخت سپهر
var transactionCommand = new CreatePaymentTransaction()
var gatewayResult = await _financialStatementApplication.CreatePaymentGateWayAndCreateInvoice(request, gateWayCallBackUrl);
if (!gatewayResult.IsSuccedded)
{
Amount = balanceAmount.Amount,
ContractingPartyId = balanceAmount.ContractingPartyId,
CallBackUrl = request.BaseUrl
};
var transaction = await _paymentTransactionApplication.Create(transactionCommand);
if (!transaction.IsSuccedded)
{
return op.Failed(transaction.Message);
return op.Failed(gatewayResult.Message);
}
var command = new CreatePaymentGatewayRequest()
{
CallBackUrl = callbackUrl,
Amount = balanceAmount.Amount/10,
TransactionId = transaction.SendId.ToString(),
};
var gatewayResponse = await _paymentGateway.Create(command, cancellationToken);
if (gatewayResponse.IsSuccess)
{
_ = await _paymentTransactionApplication.SetTransactionId(transaction.SendId, gatewayResponse.Token);
return Redirect(_paymentGateway.GetStartPayUrl(gatewayResponse.Token));
}
if (gatewayResponse.ErrorCode.HasValue)
{
return op.Failed($"خطا در ایجاد درگاه پرداخت: {gatewayResponse.ErrorCode.Value}");
}
return op.Failed("خطا در ایجاد درگاه پرداخت");
// گام 3: بازگشتی به درگاه پرداخت
return Redirect(gatewayResult.Data.PaymentUrl);
}
}

View File

@@ -1,49 +1,25 @@
using _0_Framework.Application;
using _0_Framework.Application.PaymentGateway;
using Company.Domain.BankAgg;
using Company.Domain.PaymentTransactionAgg;
using CompanyManagment.App.Contracts.FinancialStatment;
using CompanyManagment.App.Contracts.FinancilTransaction;
using CompanyManagment.App.Contracts.PaymentCallback;
using CompanyManagment.App.Contracts.PaymentTransaction;
using CompanyManagment.App.Contracts.Workshop;
using CompanyManagment.EFCore.Migrations;
using Microsoft.AspNetCore.Authorization;
using GozareshgirProgramManager.Application._Common.Constants;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using NuGet.Protocol;
using Parbad;
using ServiceHost.BaseControllers;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Net.Http;
using System.Security.Cryptography;
using System.Threading;
using CompanyManagment.App.Contracts.FinancialInvoice;
using CompanyManagment.App.Contracts.InstitutionContract;
using GozareshgirProgramManager.Application._Common.Constants;
using GozareshgirProgramManager.Infrastructure.Persistence.Context;
namespace ServiceHost.Controllers;
public class GeneralController : GeneralBaseController
{
private readonly IPaymentTransactionApplication _paymentTransactionApplication;
private readonly IPaymentGateway _paymentGateway;
private readonly IFinancialStatmentApplication _financialStatmentApplication;
private readonly IFinancialInvoiceApplication _financialInvoiceApplication;
private readonly IInstitutionContractApplication _institutionContractApplication;
private readonly IPaymentCallbackHandler _paymentCallbackHandler;
public GeneralController(IPaymentTransactionApplication paymentTransactionApplication,
IHttpClientFactory clientFactory, IFinancialStatmentApplication financialStatmentApplication,
IFinancialInvoiceApplication financialInvoiceApplication,
IInstitutionContractApplication institutionContractApplication)
IPaymentCallbackHandler paymentCallbackHandler)
{
_paymentTransactionApplication = paymentTransactionApplication;
_paymentGateway = new SepehrPaymentGateway(clientFactory);
_financialStatmentApplication = financialStatmentApplication;
_financialInvoiceApplication = financialInvoiceApplication;
_institutionContractApplication = institutionContractApplication;
_paymentCallbackHandler = paymentCallbackHandler;
}
/// <summary>
@@ -67,15 +43,15 @@ public class GeneralController : GeneralBaseController
});
}
[HttpGet("pm-permissions")]
public IActionResult GetPMPermissions()
{
var permissions = ProgramManagerPermissionCode.GetAllCodes();
return new JsonResult(permissions);
}
// [HttpGet("pm-permissions")]
// public IActionResult GetPMPermissions()
// {
// var permissions = ProgramManagerPermissionCode.GetAllCodes();
// return new JsonResult(permissions);
// }
[HttpGet("/api/callback"), HttpPost("/api/callback")]
public async Task<IActionResult> Verify([FromForm]SepehrGatewayPayResponse payResponse)
public async Task<IActionResult> Verify([FromForm] SepehrGatewayPayResponse payResponse)
{
if (!long.TryParse(payResponse.invoiceid, out var paymentTransactionId))
{
@@ -89,215 +65,29 @@ public class GeneralController : GeneralBaseController
return NotFound("Transaction not found");
}
if (transaction.Status != PaymentTransactionStatus.Pending)
// ایجاد command برای ارسال به PaymentCallbackHandler
var command = new VerifyPaymentCallbackCommand
{
return BadRequest("این تراکنش قبلا پرداخت شده است");
}
if (payResponse.respcode != 0)
{
return await HandleFailedTransaction(transaction);
}
var extraData = JsonConvert.DeserializeObject<IDictionary<string, object>>(payResponse.payload);
extraData.TryGetValue("financialInvoiceId", out var financialInvoiceIdObj);
if (financialInvoiceIdObj == null ||
!long.TryParse(financialInvoiceIdObj.ToString(), out var financialInvoiceId))
{
return BadRequest("فاکتور مالی نامعتبر است");
}
var financialInvoice = _financialInvoiceApplication.GetDetails(financialInvoiceId);
if (financialInvoice == null)
{
return BadRequest("فاکتور مالی نامعتبر است");
}
if (financialInvoice.Status != FinancialInvoiceStatus.Unpaid)
{
return BadRequest("فاکتور مالی نامعتبر است");
}
if (financialInvoice.Amount != transaction.Amount)
{
return await HandleFailedTransaction(transaction);
}
var verifyCommand = new VerifyPaymentGateWayRequest()
{
Amount = transaction.Amount,
TransactionId = payResponse.invoiceid,
DigitalReceipt = payResponse.digitalreceipt
ResponseCode = payResponse.respcode,
InvoiceId = paymentTransactionId,
Payload = payResponse.payload,
Amount = payResponse.amount,
TraceNumber = payResponse.tracenumber,
Rrn = payResponse.rrn,
DigitalReceipt = payResponse.digitalreceipt,
IssuerBank = payResponse.issuerbank,
CardNumber = payResponse.cardnumber
};
var verifyRes = await _paymentGateway.Verify(verifyCommand, CancellationToken.None);
#if DEBUG
verifyRes.IsSuccess = true;
#endif
// پردازش callback در Application Layer
var result = await _paymentCallbackHandler.VerifySepehrPaymentCallback(command, CancellationToken.None);
_financialInvoiceApplication.SetPaid(financialInvoiceId, DateTime.Now);
if (verifyRes.IsSuccess)
if (result.IsSuccedded)
{
var command = new CreateFinancialStatment()
{
ContractingPartyId = transaction.ContractingPartyId,
Deptor = 0,
Creditor = transaction.Amount,
DeptorString = "0",
TypeOfTransaction = "credit",
DescriptionOption = financialInvoice.Description + "شماره فاکتور" + financialInvoice.InvoiceNumber,
Description = "درگاه بانکی",
};
var statementResult = _financialStatmentApplication.CreateFromBankGateway(command);
if (!statementResult.IsSuccedded)
{
return new JsonResult(statementResult);
}
var setSuccessResult = _paymentTransactionApplication.SetSuccess(paymentTransactionId,
payResponse.cardnumber, payResponse.issuerbank, payResponse.rrn.ToString(),
payResponse.digitalreceipt);
if (financialInvoice.Items?.Any(x =>
x.Type is FinancialInvoiceItemType.BuyInstitutionContract
or FinancialInvoiceItemType.BuyInstitutionContractInstallment) ?? false)
{
var financialItems = financialInvoice.Items
.Where(x => x.Type == FinancialInvoiceItemType.BuyInstitutionContract);
foreach (var editFinancialInvoiceItem in financialItems)
{
await _institutionContractApplication.SetPendingWorkflow(editFinancialInvoiceItem.EntityId,
InstitutionContractSigningType.OtpBased);
}
var financialInstallmentItems = financialInvoice.Items
.Where(x => x.Type == FinancialInvoiceItemType.BuyInstitutionContractInstallment);
foreach (var editFinancialInvoiceItem in financialInstallmentItems)
{
var institutionContractId =
await _institutionContractApplication.GetIdByInstallmentId(
editFinancialInvoiceItem.EntityId);
await _institutionContractApplication.SetPendingWorkflow(institutionContractId,
InstitutionContractSigningType.OtpBased);
}
}
if (!setSuccessResult.IsSuccedded)
{
return await HandleFailedTransaction(transaction);
}
return Redirect(BuildCallbackUrl(transaction.CallBackUrl, true, transaction.Id));
}
// در غیر این صورت تراکنش ناموفق است
return await HandleFailedTransaction(transaction);
//var data = JsonConvert.SerializeObject(invoice.AdditionalData);
//var statics =
//JsonConvert.SerializeObject(res);
//await _onlinePayment.CancelAsync(invoice);
//return new JsonResult(new
//{
// data,
// statics
//});
//// Check if the invoice is new, or it's already processed before.
//if (invoice.Status != PaymentFetchResultStatus.ReadyForVerifying)
//{
// // You can also see if the invoice is already verified before.
// var isAlreadyVerified = invoice.IsAlreadyVerified;
// return Content("The payment was not successful.");
//}
//// Note: Save the verifyResult.TransactionCode in your database.
}
[HttpPost("/api/callback3232")]
public async Task<IActionResult> OnGetCallBack(string? transid, string? cardnumber, string? tracking_number,
string bank, string invoice_id, string? status, CancellationToken cancellationToken)
{
if (!long.TryParse(invoice_id, out var paymentTransactionId))
{
return BadRequest("Invalid invoice_id");
}
var transaction = await _paymentTransactionApplication.GetDetails(paymentTransactionId);
if (transaction == null)
{
return NotFound("Transaction not found");
}
if (transaction.Status != PaymentTransactionStatus.Pending)
{
return BadRequest("این تراکنش قبلا پرداخت شده است");
}
// اگر شماره کارت یا شماره پیگیری خالی باشد، تراکنش ناموفق است
if (string.IsNullOrWhiteSpace(cardnumber) || string.IsNullOrWhiteSpace(tracking_number))
{
return await HandleFailedTransaction(transaction);
}
var verifyCommand = new VerifyPaymentGateWayRequest()
{
Amount = transaction.Amount / 10,
TransactionId = transid
};
var verifyRes = await _paymentGateway.Verify(verifyCommand, cancellationToken);
// اگر استاتوس 1 باشد، تراکنش موفق است
if (verifyRes.IsSuccess)
{
var command = new CreateFinancialStatment()
{
ContractingPartyId = transaction.ContractingPartyId,
Deptor = 0,
Creditor = transaction.Amount,
DeptorString = "0",
TypeOfTransaction = "credit",
DescriptionOption = "بابت قرارداد مابین (روابط کار)",
Description = "درگاه بانکی",
};
var statementResult = _financialStatmentApplication.CreateFromBankGateway(command);
if (!statementResult.IsSuccedded)
{
return await HandleFailedTransaction(transaction);
}
var setSuccessResult =
_paymentTransactionApplication.SetSuccess(paymentTransactionId, cardnumber, bank, null, null);
if (!setSuccessResult.IsSuccedded)
{
return new JsonResult(setSuccessResult);
}
return Redirect(BuildCallbackUrl(transaction.CallBackUrl, true, transaction.Id));
}
// در غیر این صورت تراکنش ناموفق است
return await HandleFailedTransaction(transaction);
}
private async Task<IActionResult> HandleFailedTransaction(PaymentTransactionDetailsViewModel transaction)
{
var result = _paymentTransactionApplication.SetFailed(transaction.Id);
if (!result.IsSuccedded)
{
return new JsonResult(result);
}
// در صورت ناموفق بودن
return Redirect(BuildCallbackUrl(transaction.CallBackUrl, false, transaction.Id));
}

View File

@@ -415,7 +415,6 @@ if (app.Environment.IsDevelopment())
}
#endregion
//Create Http Pipeline
#region Create Http Pipeline

View File

@@ -11,7 +11,7 @@
},
"ServiceHost": {
"commandName": "Project",
"launchBrowser": false,
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"