diff --git a/0_Framework/Application/PaymentGateway/SepehrPaymentGateway.cs b/0_Framework/Application/PaymentGateway/SepehrPaymentGateway.cs index 792df36b..9a6cf10e 100644 --- a/0_Framework/Application/PaymentGateway/SepehrPaymentGateway.cs +++ b/0_Framework/Application/PaymentGateway/SepehrPaymentGateway.cs @@ -4,6 +4,7 @@ using System.Net.Http; using System.Net.Http.Json; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; namespace _0_Framework.Application.PaymentGateway; @@ -12,18 +13,24 @@ public class SepehrPaymentGateway:IPaymentGateway { private readonly HttpClient _httpClient; private const long TerminalId = 99213700; + private readonly ILogger _logger; - public SepehrPaymentGateway(IHttpClientFactory httpClient) + public SepehrPaymentGateway(IHttpClientFactory httpClient, ILogger logger) { + _logger = logger; _httpClient = httpClient.CreateClient(); _httpClient.BaseAddress = new Uri("https://sepehr.shaparak.ir/Rest/V1/PeymentApi/"); } public async Task Create(CreatePaymentGatewayRequest command, CancellationToken cancellationToken = default) { + _logger.LogInformation("Create payment started. TransactionId: {TransactionId}, Amount: {Amount}", command.TransactionId, command.Amount); command.ExtraData ??= new Dictionary(); + _logger.LogInformation("Initializing extra data with FinancialInvoiceId: {FinancialInvoiceId}", command.FinancialInvoiceId); command.ExtraData.Add("financialInvoiceId", command.FinancialInvoiceId); var extraData = JsonConvert.SerializeObject(command.ExtraData); + _logger.LogInformation("Serialized extra data payload: {Payload}", extraData); + var res = await _httpClient.PostAsJsonAsync("GetToken", new { TerminalID = TerminalId, @@ -32,21 +39,25 @@ public class SepehrPaymentGateway:IPaymentGateway callbackURL = command.CallBackUrl, payload = extraData }, cancellationToken: cancellationToken); + _logger.LogInformation("Create payment request sent. StatusCode: {StatusCode}", res.StatusCode); // خواندن محتوای پاسخ var content = await res.Content.ReadAsStringAsync(cancellationToken); - + _logger.LogInformation("Create payment response content: {Content}", content); + // تبدیل پاسخ JSON به آبجکت دات‌نت var json = System.Text.Json.JsonDocument.Parse(content); + _logger.LogInformation("Create payment JSON parsed successfully."); // گرفتن مقدار AccessToken var accessToken = json.RootElement.GetProperty("Accesstoken").ToString(); var status = json.RootElement.GetProperty("Status").ToString(); - + _logger.LogInformation("Create payment parsed values. Status: {Status}, AccessToken: {AccessToken}", status, accessToken); + return new PaymentGatewayResponse { Status = status, IsSuccess = status == "0", - Token = accessToken + Token = accessToken, }; } @@ -55,21 +66,24 @@ public class SepehrPaymentGateway:IPaymentGateway public async Task Verify(VerifyPaymentGateWayRequest command, CancellationToken cancellationToken = default) { + _logger.LogInformation("Verify payment started. DigitalReceipt: {DigitalReceipt}", command.DigitalReceipt); var res = await _httpClient.PostAsJsonAsync("Advice", new { digitalreceipt = command.DigitalReceipt, Tid = TerminalId, }, cancellationToken: cancellationToken); - + _logger.LogInformation("Verify payment request sent. StatusCode: {StatusCode}", res.StatusCode); // خواندن محتوای پاسخ var content = await res.Content.ReadAsStringAsync(cancellationToken); - + _logger.LogInformation("Verify payment response content: {Content}", content); + // تبدیل پاسخ JSON به آبجکت دات‌نت var json = System.Text.Json.JsonDocument.Parse(content); - - + _logger.LogInformation("Verify payment JSON parsed successfully."); + var message = json.RootElement.GetProperty("Message").GetString(); var status = json.RootElement.GetProperty("Status").GetString(); + _logger.LogInformation("Verify payment parsed values. Status: {Status}, Message: {Message}", status, message); return new PaymentGatewayResponse { Status = status, diff --git a/0_Framework/Application/Sms/ISmsService.cs b/0_Framework/Application/Sms/ISmsService.cs index 94e31299..9590bf27 100644 --- a/0_Framework/Application/Sms/ISmsService.cs +++ b/0_Framework/Application/Sms/ISmsService.cs @@ -64,6 +64,7 @@ public interface ISmsService /// /// پیامک مسدودی طرف حساب + /// قراردادهای قدیم /// /// /// @@ -74,6 +75,19 @@ public interface ISmsService /// Task<(byte status, string message, int messaeId, bool isSucceded)> BlockMessage(string number, string fullname, string amount, string accountType, string id, string aprove); + /// + /// پیامک مسدودی طرف حساب + /// قرارداد های جدید + /// + /// + /// + /// + /// + /// + /// + Task<(byte status, string message, int messaeId, bool isSucceded)> BlockMessageForElectronicContract(string number, + string fullname, + string amount, string code1, string code2); #endregion #region AlarmMessage diff --git a/AccountManagement.Application.Contracts/Account/IAccountApplication.cs b/AccountManagement.Application.Contracts/Account/IAccountApplication.cs index 5f82611c..fbd86441 100644 --- a/AccountManagement.Application.Contracts/Account/IAccountApplication.cs +++ b/AccountManagement.Application.Contracts/Account/IAccountApplication.cs @@ -75,7 +75,6 @@ public interface IAccountApplication void CameraLogin(CameraLoginRequest request); Task GetPmUserAsync(long accountId); - } public class CameraLoginRequest diff --git a/AccountManagement.Application/AccountApplication.cs b/AccountManagement.Application/AccountApplication.cs index 7171f36d..912cd863 100644 --- a/AccountManagement.Application/AccountApplication.cs +++ b/AccountManagement.Application/AccountApplication.cs @@ -1024,4 +1024,5 @@ public class AccountApplication : IAccountApplication { return await _pmUserQueryService.GetPmUserDataByAccountId(accountId); } + } \ No newline at end of file diff --git a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs index b4a0c823..f368cb3e 100644 --- a/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs +++ b/BackgroundInstitutionContract/BackgroundInstitutionContract.Task/Jobs/JobSchedulerRegistrator.cs @@ -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(); } + /// + /// ارسال پیامک هشدار + /// + /// + [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(); + } + } \ No newline at end of file diff --git a/Company.Domain/ContarctingPartyAgg/IPersonalContractingPartyRepository.cs b/Company.Domain/ContarctingPartyAgg/IPersonalContractingPartyRepository.cs index 068625ad..25178955 100644 --- a/Company.Domain/ContarctingPartyAgg/IPersonalContractingPartyRepository.cs +++ b/Company.Domain/ContarctingPartyAgg/IPersonalContractingPartyRepository.cs @@ -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 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 GetByNationalCode(string nationalCode); Task GetByNationalId(string registerId); + + Task DeActiveAllAsync(long id); + Task ActiveAllAsync(long id); + + } \ No newline at end of file diff --git a/Company.Domain/FinancialInvoiceAgg/IFinancialInvoiceRepository.cs b/Company.Domain/FinancialInvoiceAgg/IFinancialInvoiceRepository.cs index 96edcc14..6f1812eb 100644 --- a/Company.Domain/FinancialInvoiceAgg/IFinancialInvoiceRepository.cs +++ b/Company.Domain/FinancialInvoiceAgg/IFinancialInvoiceRepository.cs @@ -10,4 +10,6 @@ public interface IFinancialInvoiceRepository : IRepository Search(FinancialInvoiceSearchModel searchModel); Task GetUnPaidByEntityId(long entityId, FinancialInvoiceItemType financialInvoiceItemType); + Task GetUnPaidFinancialInvoiceByContractingPartyIdAndAmount(long contractingPartyId, + double amount); } \ No newline at end of file diff --git a/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs b/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs index bef58015..7e880ff9 100644 --- a/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs +++ b/Company.Domain/InstitutionContractAgg/IInstitutionContractRepository.cs @@ -12,7 +12,7 @@ namespace Company.Domain.InstitutionContractAgg; public interface IInstitutionContractRepository : IRepository { - + EditInstitutionContract GetDetails(long id); EditInstitutionContract GetFirstContract(long contractingPartyId, string typeOfContract); List InstitutionContractsWithoutAccount(); @@ -55,12 +55,12 @@ public interface IInstitutionContractRepository : IRepository GetVerificationDetails(Guid id); Task 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 @@ -72,19 +72,19 @@ public interface IInstitutionContractRepository : IRepository SetDiscountForExtension( InstitutionContractSetDiscountForExtensionRequest request); Task ResetDiscountForExtension(InstitutionContractResetDiscountForExtensionRequest request); - + Task ExtensionComplete(InstitutionContractExtensionCompleteRequest request); #endregion #region Upgrade(Amendment) - Task GetAmendmentWorkshops(long institutionContractId); - Task GetAmendmentPaymentDetails(InsitutionContractAmendmentPaymentRequest request); + Task GetAmendmentWorkshops(long institutionContractId); + Task GetAmendmentPaymentDetails(InsitutionContractAmendmentPaymentRequest request); - Task InsertAmendmentTempWorkshops(InstitutionContractAmendmentTempWorkshopViewModel request); - Task RemoveAmendmentWorkshops(Guid workshopTempId); - #endregion + Task InsertAmendmentTempWorkshops(InstitutionContractAmendmentTempWorkshopViewModel request); + Task RemoveAmendmentWorkshops(Guid workshopTempId); + #endregion Task> GetInstitutionContractSelectList(string search, string selected); Task> PrintAllAsync(List ids); @@ -162,6 +162,25 @@ public interface IInstitutionContractRepository : IRepository + /// پیامک های هشدار + /// + /// + Task SendWarningSmsTask(); + + #endregion + + + #region legalAction + /// + /// پیامک اقدام قضائی + /// + /// + Task SendLegalActionSmsTask(); + #endregion Task GetIdByInstallmentId(long installmentId); @@ -173,4 +192,5 @@ public interface IInstitutionContractRepository : IRepository SetDiscountForCreation(InstitutionContractSetDiscountForCreationRequest request); Task ResetDiscountForCreation(InstitutionContractResetDiscountForExtensionRequest request); Task CreationComplete(InstitutionContractExtensionCompleteRequest request); + Task GetIncludeInstallments(long id); } \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/FinancialInvoice/CreateFinancialInvoice.cs b/CompanyManagment.App.Contracts/FinancialInvoice/CreateFinancialInvoice.cs index 0ce5a82b..6c28c66e 100644 --- a/CompanyManagment.App.Contracts/FinancialInvoice/CreateFinancialInvoice.cs +++ b/CompanyManagment.App.Contracts/FinancialInvoice/CreateFinancialInvoice.cs @@ -8,7 +8,7 @@ public class CreateFinancialInvoice public double Amount { get; set; } public long ContractingPartyId { get; set; } public string Description { get; set; } - public List? Items { get; set; } + public List Items { get; set; } } public class CreateFinancialInvoiceItem diff --git a/CompanyManagment.App.Contracts/FinancialInvoice/EditFinancialInvoice.cs b/CompanyManagment.App.Contracts/FinancialInvoice/EditFinancialInvoice.cs index 1975c32a..a24b49f3 100644 --- a/CompanyManagment.App.Contracts/FinancialInvoice/EditFinancialInvoice.cs +++ b/CompanyManagment.App.Contracts/FinancialInvoice/EditFinancialInvoice.cs @@ -10,7 +10,8 @@ public class EditFinancialInvoice public double Amount { get; set; } public FinancialInvoiceStatus Status { get; set; } - public List? Items { get; set; } + public List Items { get; set; } + public long ContractingPartyId { get; set; } } public class EditFinancialInvoiceItem diff --git a/CompanyManagment.App.Contracts/FinancialStatment/IFinancialStatmentApplication.cs b/CompanyManagment.App.Contracts/FinancialStatment/IFinancialStatmentApplication.cs index 749a38a8..4cd5fd77 100644 --- a/CompanyManagment.App.Contracts/FinancialStatment/IFinancialStatmentApplication.cs +++ b/CompanyManagment.App.Contracts/FinancialStatment/IFinancialStatmentApplication.cs @@ -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 /// Task GetDetailsByContractingParty(long contractingPartyId, FinancialStatementSearchModel searchModel); + + /// + /// پردازش شارژ حساب از طریق درگاه پرداخت سپهر + /// + /// + /// مسیر برگشت درگاه پرداخت + /// + Task> CreatePaymentGateWayAndCreateInvoice( + CreateFinancialPayRequest request, string gateWayCallBackUrl); } +public record CreateFinancialPayRequest(long Id, string BaseUrl); public class FinancialStatmentDetailsByContractingPartyViewModel { diff --git a/CompanyManagment.App.Contracts/InstitutionContract/SmsListData.cs b/CompanyManagment.App.Contracts/InstitutionContract/SmsListData.cs index 35a89e68..e81a8ecf 100644 --- a/CompanyManagment.App.Contracts/InstitutionContract/SmsListData.cs +++ b/CompanyManagment.App.Contracts/InstitutionContract/SmsListData.cs @@ -94,4 +94,29 @@ public class BlockSmsListData /// آی دی صورت حساب مالی /// public string AproveId { get; set; } + + /// + /// آیا قرداد مالی قدیمی است + /// + public bool IsElectronicContract { get; set; } + + /// + /// پابلیک آی دی بخش یک + /// + public string Code1 { get; set; } + + /// + /// پابلیک آی دی بخش دو + /// + public string Code2 { get; set; } +} + + +/// +/// لیست قراداد های آبی +/// جهت ارسال هشدار یا اقدام قضائی +/// +public class BlueWarningSmsData +{ + } \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/PaymentCallback/IPaymentCallbackHandler.cs b/CompanyManagment.App.Contracts/PaymentCallback/IPaymentCallbackHandler.cs new file mode 100644 index 00000000..c435cf5f --- /dev/null +++ b/CompanyManagment.App.Contracts/PaymentCallback/IPaymentCallbackHandler.cs @@ -0,0 +1,21 @@ +using _0_Framework.Application; +using System.Threading; +using System.Threading.Tasks; + +namespace CompanyManagment.App.Contracts.PaymentCallback; + +/// +/// رابط برای مدیریت Callback درگاه‌های پرداخت +/// +public interface IPaymentCallbackHandler +{ + /// + /// تأیید و پردازش callback درگاه پرداخت سپهر + /// + /// داده‌های callback درگاه + /// توکن لغو عملیات + /// نتیجه عملیات + Task VerifySepehrPaymentCallback(VerifyPaymentCallbackCommand command, + CancellationToken cancellationToken = default); +} + diff --git a/CompanyManagment.App.Contracts/PaymentCallback/VerifyPaymentCallbackCommand.cs b/CompanyManagment.App.Contracts/PaymentCallback/VerifyPaymentCallbackCommand.cs new file mode 100644 index 00000000..9dbe583c --- /dev/null +++ b/CompanyManagment.App.Contracts/PaymentCallback/VerifyPaymentCallbackCommand.cs @@ -0,0 +1,53 @@ +namespace CompanyManagment.App.Contracts.PaymentCallback; + +/// +/// دستور تأیید callback درگاه پرداخت +/// +public class VerifyPaymentCallbackCommand +{ + /// + /// کد پاسخ درگاه (0 = موفق) + /// + public int ResponseCode { get; set; } + + /// + /// شناسه فاکتور/تراکنش + /// + public long InvoiceId { get; set; } + + /// + /// داده‌های اضافی JSON + /// + public string Payload { get; set; } + + /// + /// مبلغ تراکنش + /// + public long Amount { get; set; } + + /// + /// شماره پیگیری درگاه + /// + public long TraceNumber { get; set; } + + /// + /// شماره سند بانکی (RRN) + /// + public long Rrn { get; set; } + + /// + /// رسید دیجیتال + /// + public string DigitalReceipt { get; set; } + + /// + /// بانک صادر کننده کارت + /// + public string IssuerBank { get; set; } + + /// + /// شماره کارت + /// + public string CardNumber { get; set; } +} + diff --git a/CompanyManagment.App.Contracts/SepehrPaymentGateway/CreateSepehrPaymentGatewayResponse.cs b/CompanyManagment.App.Contracts/SepehrPaymentGateway/CreateSepehrPaymentGatewayResponse.cs new file mode 100644 index 00000000..8e44123f --- /dev/null +++ b/CompanyManagment.App.Contracts/SepehrPaymentGateway/CreateSepehrPaymentGatewayResponse.cs @@ -0,0 +1,22 @@ +namespace CompanyManagment.App.Contracts.SepehrPaymentGateway; + +/// +/// پاسخ ایجاد درگاه پرداخت سپهر +/// +public class CreateSepehrPaymentGatewayResponse +{ + /// + /// توکن درگاه + /// + public string Token { get; set; } + + /// + /// شناسه تراکنش + /// + public long TransactionId { get; set; } + + /// + /// URL درگاه پرداخت + /// + public string PaymentUrl { get; set; } +} \ No newline at end of file diff --git a/CompanyManagment.App.Contracts/SepehrPaymentGateway/ISepehrPaymentGatewayService.cs b/CompanyManagment.App.Contracts/SepehrPaymentGateway/ISepehrPaymentGatewayService.cs new file mode 100644 index 00000000..b5af2f4e --- /dev/null +++ b/CompanyManagment.App.Contracts/SepehrPaymentGateway/ISepehrPaymentGatewayService.cs @@ -0,0 +1,32 @@ +using _0_Framework.Application; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace CompanyManagment.App.Contracts.SepehrPaymentGateway; + +/// +/// رابط برای سرویس مشترک ایجاد درگاه پرداخت سپهر +/// +public interface ISepehrPaymentGatewayService +{ + /// + /// ایجاد درگاه پرداخت سپهر برای یک تراکنش + /// + /// مبلغ + /// شناسه طرف قرارداد + /// آدرس بازگشتی به فرانت برای نمایش نتیجه + /// آدرس بازگشتی درگاه پرداخت + /// شناسه فاکتور مالی (اختیاری) - این پارامتر مستقیماً به درگاه فرستاده می‌شود + /// داده‌های اضافی سفارشی برای payload (اختیاری) + /// توکن لغو + /// شامل Token درگاه یا OperationResult با خطا + Task> CreateSepehrPaymentGateway( + double amount, + long contractingPartyId, + long financialInvoiceId, + string gatewayCallbackUrl, + string frontCallbackUrl="https://client.gozareshgir.ir", + Dictionary extraData = null, + CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/CompanyManagment.Application/FinancialInvoiceApplication.cs b/CompanyManagment.Application/FinancialInvoiceApplication.cs index 59a7fdd9..c2b6ffbf 100644 --- a/CompanyManagment.Application/FinancialInvoiceApplication.cs +++ b/CompanyManagment.Application/FinancialInvoiceApplication.cs @@ -9,15 +9,13 @@ using CompanyManagment.EFCore; namespace CompanyManagment.Application; -public class FinancialInvoiceApplication : RepositoryBase, 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 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 Search(FinancialStatmentSearchModel searchModel) { @@ -203,6 +200,45 @@ public class FinancialStatmentApplication : IFinancialStatmentApplication public async Task GetDetailsByContractingParty( long contractingPartyId, FinancialStatementSearchModel searchModel) { - return await _financialStatmentRepository.GetDetailsByContractingParty(contractingPartyId,searchModel); + return await _financialStatmentRepository.GetDetailsByContractingParty(contractingPartyId, searchModel); + } + + public async Task> CreatePaymentGateWayAndCreateInvoice( + CreateFinancialPayRequest request, string gateWayCallBackUrl) + { + var op = new OperationResult(); + // گام 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; } } \ No newline at end of file diff --git a/CompanyManagment.Application/InstitutionContractApplication.cs b/CompanyManagment.Application/InstitutionContractApplication.cs index ee5099e5..fa925516 100644 --- a/CompanyManagment.Application/InstitutionContractApplication.cs +++ b/CompanyManagment.Application/InstitutionContractApplication.cs @@ -1,40 +1,32 @@ 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 Microsoft.Extensions.Logging; using PersianTools.Core; using ConnectedPersonnelViewModel = CompanyManagment.App.Contracts.Workshop.ConnectedPersonnelViewModel; using FinancialStatment = Company.Domain.FinancialStatmentAgg.FinancialStatment; @@ -49,49 +41,45 @@ 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,ILogger sepehrGatewayLogger) { _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; - _paymentGateway = new SepehrPaymentGateway(httpClientFactory); + _sepehrPaymentGatewayService = sepehrPaymentGatewayService; + _paymentGateway = new SepehrPaymentGateway(httpClientFactory,sepehrGatewayLogger); } public OperationResult Create(CreateInstitutionContract command) @@ -817,20 +805,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 +826,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 +1263,87 @@ 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) + { + 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) + { + 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 GetWorkshopInitialDetails(long workshopDetailsId) diff --git a/CompanyManagment.Application/PaymentCallbackHandler.cs b/CompanyManagment.Application/PaymentCallbackHandler.cs new file mode 100644 index 00000000..7a5185b4 --- /dev/null +++ b/CompanyManagment.Application/PaymentCallbackHandler.cs @@ -0,0 +1,239 @@ +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; +using Microsoft.Extensions.Logging; + +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, + ILogger sepehrGatewayLogger) + { + _paymentTransactionApplication = paymentTransactionApplication; + _financialStatmentApplication = financialStatmentApplication; + _financialInvoiceApplication = financialInvoiceApplication; + _institutionContractApplication = institutionContractApplication; + _institutionContractRepository = institutionContractRepository; + _financialStatmentRepository = financialStatmentRepository; + _paymentGateway = new SepehrPaymentGateway(httpClientFactory, sepehrGatewayLogger); + } + + /// + /// تأیید و پردازش callback درگاه پرداخت سپهر + /// + public async Task 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>(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}"); + } + } + + /// + /// مدیریت آپدیت قرارداد‌های نهادی + /// + 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(); + } +} \ No newline at end of file diff --git a/CompanyManagment.Application/SepehrPaymentGatewayService.cs b/CompanyManagment.Application/SepehrPaymentGatewayService.cs new file mode 100644 index 00000000..9790f66b --- /dev/null +++ b/CompanyManagment.Application/SepehrPaymentGatewayService.cs @@ -0,0 +1,119 @@ +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; +using Microsoft.Extensions.Logging; + +namespace CompanyManagment.Application; + +/// +/// سرویس مشترک برای ایجاد درگاه پرداخت سپهر +/// +public class SepehrPaymentGatewayService : ISepehrPaymentGatewayService +{ + private readonly IPaymentGateway _paymentGateway; + private readonly IPaymentTransactionApplication _paymentTransactionApplication; + + public SepehrPaymentGatewayService( + IPaymentTransactionApplication paymentTransactionApplication, + IHttpClientFactory httpClientFactory, + ILogger sepehrGatewayLogger) + { + _paymentGateway = new SepehrPaymentGateway(httpClientFactory, sepehrGatewayLogger); + _paymentTransactionApplication = paymentTransactionApplication; + } + + /// + /// ایجاد درگاه پرداخت سپهر برای یک تراکنش + /// + /// مبلغ + /// شناسه طرف قرارداد + /// آدرس بازگشتی به فرانت برای نمایش نتیجه + /// آدرس بازگشتی درگاه پرداخت + /// شناسه فاکتور مالی (اختیاری) + /// داده‌های اضافی (اختیاری) + /// توکن لغو + /// شامل Token درگاه یا OperationResult با خطا + public async Task> CreateSepehrPaymentGateway( + double amount, + long contractingPartyId, + long financialInvoiceId, + string gatewayCallbackUrl, + string frontCallbackUrl="https://client.gozareshgir.ir", + Dictionary extraData = null, + CancellationToken cancellationToken = default) + { + var op = new OperationResult(); + + 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(); + + 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}"); + } + } +} \ No newline at end of file diff --git a/CompanyManagment.EFCore/Repository/FinancialInvoiceRepository.cs b/CompanyManagment.EFCore/Repository/FinancialInvoiceRepository.cs index 66b05f02..a5e65908 100644 --- a/CompanyManagment.EFCore/Repository/FinancialInvoiceRepository.cs +++ b/CompanyManagment.EFCore/Repository/FinancialInvoiceRepository.cs @@ -34,6 +34,7 @@ public class FinancialInvoiceRepository : RepositoryBase 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 .Where(x => x.Status == FinancialInvoiceStatus.Unpaid).FirstOrDefaultAsync(x => x.Items .Any(y => y.Type == financialInvoiceItemType && y.EntityId == entityId)); } + + public async Task GetUnPaidFinancialInvoiceByContractingPartyIdAndAmount(long contractingPartyId, + double amount) + { + return await _context.FinancialInvoices.FirstOrDefaultAsync(x=>x.ContractingPartyId == contractingPartyId && + x.Amount == amount && + x.Status == FinancialInvoiceStatus.Unpaid); + } } \ No newline at end of file diff --git a/CompanyManagment.EFCore/Repository/FinancialStatmentRepository.cs b/CompanyManagment.EFCore/Repository/FinancialStatmentRepository.cs index fbf7ef74..c25ecca1 100644 --- a/CompanyManagment.EFCore/Repository/FinancialStatmentRepository.cs +++ b/CompanyManagment.EFCore/Repository/FinancialStatmentRepository.cs @@ -210,6 +210,7 @@ public class FinancialStatmentRepository : RepositoryBase new EditInstitutionContract() - { - Id = x.id, - ContractNo = x.ContractNo, - ContractStartGr = x.ContractStartGr, - ContractStartFa = x.ContractStartFa, - ContractEndGr = x.ContractEndGr, - ContractEndFa = x.ContractEndFa, - RepresentativeName = x.RepresentativeName, - ContractingPartyName = x.ContractingPartyName, - RepresentativeId = x.RepresentativeId, - ContractingPartyId = x.ContractingPartyId, - ContractDateFa = x.ContractDateFa, - State = x.State, - City = x.City, - Address = x.Address, - Description = x.Description, - WorkshopManualCount = x.WorkshopManualCount, - EmployeeManualCount = x.EmployeeManualCount, - ContractAmountString = x.ContractAmount.ToMoney(), - ContractAmount = x.ContractAmount, - DailyCompenseationString = x.DailyCompenseation.ToMoney(), - ObligationString = x.Obligation.ToMoney(), - TotalAmountString = x.TotalAmount.ToMoney(), - ExtensionNo = x.ExtensionNo, - OfficialCompany = x.OfficialCompany, - TypeOfContract = x.TypeOfContract, - Signature = x.Signature, - HasValueAddedTax = x.HasValueAddedTax, - ValueAddedTax = x.ValueAddedTax, - }) + { + Id = x.id, + ContractNo = x.ContractNo, + ContractStartGr = x.ContractStartGr, + ContractStartFa = x.ContractStartFa, + ContractEndGr = x.ContractEndGr, + ContractEndFa = x.ContractEndFa, + RepresentativeName = x.RepresentativeName, + ContractingPartyName = x.ContractingPartyName, + RepresentativeId = x.RepresentativeId, + ContractingPartyId = x.ContractingPartyId, + ContractDateFa = x.ContractDateFa, + State = x.State, + City = x.City, + Address = x.Address, + Description = x.Description, + WorkshopManualCount = x.WorkshopManualCount, + EmployeeManualCount = x.EmployeeManualCount, + ContractAmountString = x.ContractAmount.ToMoney(), + ContractAmount = x.ContractAmount, + DailyCompenseationString = x.DailyCompenseation.ToMoney(), + ObligationString = x.Obligation.ToMoney(), + TotalAmountString = x.TotalAmount.ToMoney(), + ExtensionNo = x.ExtensionNo, + OfficialCompany = x.OfficialCompany, + TypeOfContract = x.TypeOfContract, + Signature = x.Signature, + HasValueAddedTax = x.HasValueAddedTax, + ValueAddedTax = x.ValueAddedTax, + }) .FirstOrDefault(x => x.Id == id); } public EditInstitutionContract GetFirstContract(long contractingPartyId, string typeOfContract) { return _context.InstitutionContractSet.Select(x => new EditInstitutionContract() - { - Id = x.id, - ContractNo = x.ContractNo, - ContractStartGr = x.ContractStartGr, - ContractStartFa = x.ContractStartFa, - ContractEndGr = x.ContractEndGr, - ContractEndFa = x.ContractEndFa, - RepresentativeName = x.RepresentativeName, - ContractingPartyName = x.ContractingPartyName, - RepresentativeId = x.RepresentativeId, - ContractingPartyId = x.ContractingPartyId, - ContractDateFa = x.ContractDateFa, - State = x.State, - City = x.City, - Address = x.Address, - Description = x.Description, - WorkshopManualCount = x.WorkshopManualCount, - EmployeeManualCount = x.EmployeeManualCount, - ContractAmountString = x.ContractAmount.ToMoney(), - DailyCompenseationString = x.DailyCompenseation.ToMoney(), - ObligationString = x.Obligation.ToMoney(), - TotalAmountString = x.TotalAmount.ToMoney(), - ExtensionNo = x.ExtensionNo, - OfficialCompany = x.OfficialCompany, - TypeOfContract = x.TypeOfContract, - Signature = x.Signature - }) + { + Id = x.id, + ContractNo = x.ContractNo, + ContractStartGr = x.ContractStartGr, + ContractStartFa = x.ContractStartFa, + ContractEndGr = x.ContractEndGr, + ContractEndFa = x.ContractEndFa, + RepresentativeName = x.RepresentativeName, + ContractingPartyName = x.ContractingPartyName, + RepresentativeId = x.RepresentativeId, + ContractingPartyId = x.ContractingPartyId, + ContractDateFa = x.ContractDateFa, + State = x.State, + City = x.City, + Address = x.Address, + Description = x.Description, + WorkshopManualCount = x.WorkshopManualCount, + EmployeeManualCount = x.EmployeeManualCount, + ContractAmountString = x.ContractAmount.ToMoney(), + DailyCompenseationString = x.DailyCompenseation.ToMoney(), + ObligationString = x.Obligation.ToMoney(), + TotalAmountString = x.TotalAmount.ToMoney(), + ExtensionNo = x.ExtensionNo, + OfficialCompany = x.OfficialCompany, + TypeOfContract = x.TypeOfContract, + Signature = x.Signature + }) .Where(x => x.ContractingPartyId == contractingPartyId && x.TypeOfContract == typeOfContract) .OrderBy(x => x.ExtensionNo).FirstOrDefault(); } @@ -597,40 +599,40 @@ public class InstitutionContractRepository : RepositoryBase new InstitutionContractViewModel() - { - Id = x.Id, - ContractNo = x.ContractNo, - ContractStartGr = x.ContractStartGr, - ContractStartFa = x.ContractStartFa, - ContractEndGr = x.ContractEndGr, - ContractEndFa = x.ContractEndFa, - RepresentativeId = x.RepresentativeId, - RepresentativeName = x.RepresentativeName, - ContractingPartyName = x.ContractingPartyName, - ContractingPartyId = x.ContractingPartyId, - ContractAmount = x.ContractAmount, - TotalAmount = x.TotalAmount, - SearchAmount = x.SearchAmount, - IsActiveString = x.IsActiveString, - OfficialCompany = x.OfficialCompany, - TypeOfContract = x.TypeOfContract, - Signature = x.Signature, - ExpireColor = x.ExpireColor, - IsExpier = x.IsExpier, - BalanceDouble = x.BalanceDouble, - BalanceStr = x.BalanceStr, - EmployerViewModels = x.EmployerViewModels, - EmployerNo = x.EmployerNo, - EmployerName = x.EmployerViewModels.Select(n => n.FullName).FirstOrDefault(), - WorkshopViewModels = x.WorkshopViewModels, - WorkshopCount = x.WorkshopCount, - IsContractingPartyBlock = x.IsContractingPartyBlock, - BlockTimes = x.BlockTimes, - EmployeeCount = + { + Id = x.Id, + ContractNo = x.ContractNo, + ContractStartGr = x.ContractStartGr, + ContractStartFa = x.ContractStartFa, + ContractEndGr = x.ContractEndGr, + ContractEndFa = x.ContractEndFa, + RepresentativeId = x.RepresentativeId, + RepresentativeName = x.RepresentativeName, + ContractingPartyName = x.ContractingPartyName, + ContractingPartyId = x.ContractingPartyId, + ContractAmount = x.ContractAmount, + TotalAmount = x.TotalAmount, + SearchAmount = x.SearchAmount, + IsActiveString = x.IsActiveString, + OfficialCompany = x.OfficialCompany, + TypeOfContract = x.TypeOfContract, + Signature = x.Signature, + ExpireColor = x.ExpireColor, + IsExpier = x.IsExpier, + BalanceDouble = x.BalanceDouble, + BalanceStr = x.BalanceStr, + EmployerViewModels = x.EmployerViewModels, + EmployerNo = x.EmployerNo, + EmployerName = x.EmployerViewModels.Select(n => n.FullName).FirstOrDefault(), + WorkshopViewModels = x.WorkshopViewModels, + WorkshopCount = x.WorkshopCount, + IsContractingPartyBlock = x.IsContractingPartyBlock, + BlockTimes = x.BlockTimes, + EmployeeCount = ((x.WorkshopViewModels.Sum(w => w.LeftWorkIds.Count)) + (x.WorkshopViewModels.Sum(w => w.InsuranceLeftWorkIds.Count(c => !w.LeftWorkIds.Contains(c))))).ToString(), - ArchiveCode = x.WorkshopViewModels.Count > 0 ? ArchiveCodeFinder(x.WorkshopViewModels) : 0, - }).OrderBy(x => x.WorkshopCount != "0" && string.IsNullOrWhiteSpace(x.ExpireColor)) + ArchiveCode = x.WorkshopViewModels.Count > 0 ? ArchiveCodeFinder(x.WorkshopViewModels) : 0, + }).OrderBy(x => x.WorkshopCount != "0" && string.IsNullOrWhiteSpace(x.ExpireColor)) .ThenBy(x => x.WorkshopCount == "0" && string.IsNullOrWhiteSpace(x.ExpireColor)) .ThenBy(x => x.IsExpier == "true") .ThenBy(x => x.ExpireColor == "purple") @@ -3406,7 +3408,7 @@ public class InstitutionContractRepository : RepositoryBase new GetInstitutionVerificationDetailsWorkshopsViewModel() { Name = x.WorkshopName, @@ -3799,7 +3801,7 @@ public class InstitutionContractRepository : RepositoryBase @@ -3810,7 +3812,7 @@ public class InstitutionContractRepository : RepositoryBase SendReminderSmsForBackgroundTask() { var now = DateTime.Now; - _logger.LogInformation("================>> SendReminderSmsForBackgroundTask job run"); + // تبدیل تاریخ میلادی به شمسی var persianNow = now.ToFarsi(); @@ -3866,8 +3868,9 @@ public class InstitutionContractRepository : RepositoryBase @@ -3889,6 +3892,7 @@ public class InstitutionContractRepository : RepositoryBase @@ -3956,7 +3960,9 @@ public class InstitutionContractRepository : RepositoryBase(); - var institutionContracts = await _context.InstitutionContractSet.Select(x => new InstitutionContractViewModel + var institutionContracts = await _context.InstitutionContractSet + .Include(x => x.Installments) + .Select(x => new InstitutionContractViewModel { Id = x.id, ContractingPartyId = x.ContractingPartyId, @@ -3967,11 +3973,24 @@ public class InstitutionContractRepository : RepositoryBase new InstitutionContractInstallmentViewModel + { AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr }) + .OrderBy(ins => ins.InstallmentDateGr).Skip(1).ToList(), }).Where(x => x.ContractStartGr < checkDate && x.ContractEndGr >= checkDate && - x.ContractAmountDouble > 0).GroupBy(x => x.ContractingPartyId).Select(x => x.First()) + x.ContractAmountDouble > 0 && x.VerificationStatus != InstitutionContractVerificationStatus.PendingForVerify).GroupBy(x => x.ContractingPartyId).Select(x => x.First()) .ToListAsync(); + // قرارداد هایی که بطور یکجا پرداخت شده اند + var paidInFull = institutionContracts.Where(x => + x.SigningType != InstitutionContractSigningType.Legacy && x.IsInstallment == false && x.SigningType != null).ToList(); + + //حذف قراداد هایی که یکجا پرداخت شده اند از لیست ایجاد سند ماهانه + institutionContracts = institutionContracts.Except(paidInFull).ToList(); var contractingPartyList = await _context.PersonalContractingParties .Where(x => institutionContracts.Select(ins => ins.ContractingPartyId).Contains(x.id)).ToListAsync(); @@ -3984,8 +4003,9 @@ public class InstitutionContractRepository : RepositoryBase institutionContracts.Select(ins => ins.Id).Contains(x.InstitutionContractId)) .Where(x => x.SendSms && x.PhoneType == "شماره همراه" && !string.IsNullOrWhiteSpace(x.PhoneNumber) && x.PhoneNumber.Length == 11).ToListAsync(); - - foreach (var item in institutionContracts) + var oldInstitutionContract = institutionContracts.Where(x => x.IsInstallment == false).ToList(); + var electronicInstitutionContract = institutionContracts.Where(x => x.IsInstallment == true).ToList(); + foreach (var item in oldInstitutionContract) { try { @@ -4069,7 +4089,11 @@ public class InstitutionContractRepository : RepositoryBase x.id == item.ContractingPartyId); + if (contractingParty != null && contractingParty.IsBlock == "true") + { + var partyName = contractingParty.IsLegal == "حقیقی" + ? $"{contractingParty.FName} {contractingParty.LName}" + : $"{contractingParty.LName}"; + if (!string.IsNullOrWhiteSpace(contractingParty.SureName)) + partyName = $"{partyName} ({contractingParty.SureName})"; + if (partyName.Length > 25) partyName = $"{partyName.Substring(0, 25)}"; + + var isLegal = contractingParty.IsLegal == "حقوقی" ? true : false; + + var hasFinancialStatment = + financialStatmentList.Any(x => + x.ContractingPartyId == item.ContractingPartyId & x.FinancialTransactionList.Count > 0); + + + var hasPhonNumber = phoneNumberList.Any(x => x.InstitutionContractId == item.Id); + + + if (hasFinancialStatment && hasPhonNumber) + { + var transactions = + financialStatmentList.FirstOrDefault(x => x.ContractingPartyId == item.ContractingPartyId); + + var debtor = transactions.FinancialTransactionList.Sum(x => x.Deptor); + var creditor = transactions.FinancialTransactionList.Sum(x => x.Creditor); + + + var id = $"{item.ContractingPartyId}"; + var aprove = $"{transactions.id}"; + var balance = debtor - creditor; + if (balance > 0) + { + + var instalment = item.InstallmentList + .FirstOrDefault().AmountDouble; + + var sumOfAmounts = instalment * 2; + if (balance >= sumOfAmounts) + { + var phoneNumbers = new List(); + phoneNumbers = phoneNumberList.Where(x => x.InstitutionContractId == item.Id) + .Select(x => new CreateContactInfo + { + PhoneType = x.PhoneType, + PhoneNumber = x.PhoneNumber, + + InstitutionContractId = x.InstitutionContractId, + SendSms = x.SendSms + }).Where(x => x.PhoneNumber.Length == 11).ToList(); + + + var accountType = item.OfficialCompany == "Official" ? "ol" : "nol"; + + var balanceToMoney = balance.ToMoney(); + var amount = balanceToMoney + " " + "ریال" + " "; + string publicId = transactions.PublicIdStr; + string code1 = publicId.Substring(0, 25); + string code2 = publicId.Substring(25); + foreach (var number in phoneNumbers) + { + + smsList.Add(new BlockSmsListData() + { + PhoneNumber = number.PhoneNumber, + PartyName = partyName, + AccountType = accountType, + Amount = amount, + ContractingPartyId = contractingParty.id, + InstitutionContractId = item.Id, + AproveId = aprove, + IsElectronicContract = true, + Code1 = code1, + Code2 = code2 + }); + } + } + } + } + } + } + catch (Exception e) + { + string name = item.ContractingPartyName.Length > 18 + ? item.ContractingPartyName.Substring(0, 18) + : item.ContractingPartyName; + string errMess = $"{name}-خطا"; + await _smsService.Alarm("09114221321", errMess); + } + } return smsList; } + public async Task SendBlockSmsToContractingParties(List smsListData, string typeOfSms, + string sendMessStart, string sendMessEnd) + { + if (smsListData.Any()) + { + await _smsService.Alarm("09114221321", sendMessStart); + Thread.Sleep(1000); + await _smsService.Alarm("09111485044", sendMessStart); + Thread.Sleep(1000); + int successProcess = 1; + int countList = smsListData.Count; + foreach (var item in smsListData) + { + try + { + if (item.IsElectronicContract) + { + var smsResult = await _smsService.BlockMessageForElectronicContract(item.PhoneNumber, item.PartyName, + item.Amount, item.Code1, $"{item.Code2}"); + Thread.Sleep(1000); + var createSmsResult = new Company.Domain.SmsResultAgg.SmsResult(smsResult.messaeId, + smsResult.message, typeOfSms, + item.PartyName, item.PhoneNumber, item.ContractingPartyId, item.InstitutionContractId); + await _smsResultRepository.CreateAsync(createSmsResult); + await _smsResultRepository.SaveChangesAsync(); + } + else + { + var smsResult = await _smsService.BlockMessage(item.PhoneNumber, item.PartyName, + item.Amount, item.AccountType, $"{item.ContractingPartyId}", item.AproveId); + Thread.Sleep(1000); + var createSmsResult = new Company.Domain.SmsResultAgg.SmsResult(smsResult.messaeId, + smsResult.message, typeOfSms, + item.PartyName, item.PhoneNumber, item.ContractingPartyId, item.InstitutionContractId); + await _smsResultRepository.CreateAsync(createSmsResult); + await _smsResultRepository.SaveChangesAsync(); + } + + } + catch (Exception e) + { + string name = item.PartyName.Length > 18 ? item.PartyName.Substring(0, 18) : item.PartyName; + string errMess = $"{name}-خطا"; + await _smsService.Alarm("09114221321", errMess); + } + + Thread.Sleep(600); + var percent = (successProcess / (double)countList) * 100; + await _hubContext.Clients.Group(SendSmsHub.GetGroupName(10)) + .SendAsync("showStatus", (int)percent); + + successProcess += 1; + } + + + await _smsService.Alarm("09114221321", sendMessEnd); + Thread.Sleep(1000); + await _smsService.Alarm("09111485044", sendMessEnd); + } + } #endregion + //دریافت لیست بدهکاران و ارسال پیامک + #region GetListAndSendSmsMethods /// ///دریافت لیست بدهکارن @@ -4113,7 +4294,9 @@ public class InstitutionContractRepository : RepositoryBase x.StartService.Date <= previusMonthStart.Date && x.EndService.Date >= previusMonthEnd.Date).ToList(); - var institutionContracts = await _context.InstitutionContractSet.AsSplitQuery().Select(x => + var institutionContracts = await _context.InstitutionContractSet.AsSplitQuery() + .Include(x => x.Installments) + .Select(x => new InstitutionContractViewModel { Id = x.id, @@ -4125,11 +4308,24 @@ public class InstitutionContractRepository : RepositoryBase new InstitutionContractInstallmentViewModel + { AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr }) + .OrderBy(ins => ins.InstallmentDateGr).Skip(1).ToList(), }).Where(x => x.ContractStartGr < checkDate && x.ContractEndGr >= checkDate && - x.ContractAmountDouble > 0).GroupBy(x => x.ContractingPartyId).Select(x => x.First()) + x.ContractAmountDouble > 0 && x.VerificationStatus != InstitutionContractVerificationStatus.PendingForVerify) + .GroupBy(x => x.ContractingPartyId).Select(x => x.First()) .ToListAsync(); + // قرارداد هایی که بطور یکجا پرداخت شده اند + var paidInFull = institutionContracts.Where(x => + x.SigningType != InstitutionContractSigningType.Legacy && x.IsInstallment == false && x.SigningType != null).ToList(); + //حذف قراداد هایی که یکجا پرداخت شده اند از لیست ایجاد سند ماهانه + institutionContracts = institutionContracts.Except(paidInFull).ToList(); var contractingPartyList = await _context.PersonalContractingParties .Where(x => institutionContracts.Select(ins => ins.ContractingPartyId).Contains(x.id)).ToListAsync(); @@ -4146,7 +4342,15 @@ public class InstitutionContractRepository : RepositoryBase x.IsInstallment == false).ToList(); + var electronicInstitutionContract = institutionContracts.Where(x => x.IsInstallment == true).ToList(); + foreach (var item in oldInstitutionContract) { try { @@ -4198,6 +4402,8 @@ public class InstitutionContractRepository : RepositoryBase 0) // اگر بدهکار بود { //var employers = _context.Employers.Where(x => x.ContractingPartyId == item.ContractingPartyId) @@ -4239,58 +4445,28 @@ public class InstitutionContractRepository : RepositoryBase x.id == item.ContractingPartyId); + if (!string.IsNullOrWhiteSpace(contractingParty.LName)) + { + var partyName = contractingParty.IsLegal == "حقیقی" + ? $"{contractingParty.FName} {contractingParty.LName}" + : $"{contractingParty.LName}"; + if (!string.IsNullOrWhiteSpace(contractingParty.SureName)) + partyName = $"{partyName} ({contractingParty.SureName})"; + + if (partyName.Length > 25) partyName = $"{partyName.Substring(0, 25)}"; + + var isLegal = contractingParty.IsLegal == "حقوقی" ? true : false; + var isBlock = contractingParty.IsBlock == "true" ? true : false; + var isActive = contractingParty.IsActiveString == "true" ? true : false; + + if (!string.IsNullOrWhiteSpace(contractingParty.IsActiveString) && isActive) + { + var hasFinancialStatement = + financialStatmentList.Any(x => x.ContractingPartyId == item.ContractingPartyId); + + + var hasPhonNumber = phoneNumberList.Any(x => x.InstitutionContractId == item.Id); + + if (hasFinancialStatement && hasPhonNumber) + { + var phoneNumbers = phoneNumberList.Where(x => x.InstitutionContractId == item.Id) + .Select(x => new CreateContactInfo + { + PhoneType = x.PhoneType, + PhoneNumber = x.PhoneNumber, + + InstitutionContractId = x.InstitutionContractId, + SendSms = x.SendSms + }).Where(x => x.PhoneNumber.Length == 11).ToList(); + + var transactions = financialStatmentList.FirstOrDefault(x => + x.ContractingPartyId == item.ContractingPartyId); + + var debtor = transactions.FinancialTransactionList.Sum(x => x.Deptor); + var creditor = transactions.FinancialTransactionList.Sum(x => x.Creditor); + + + var id = $"{item.ContractingPartyId}"; + var aprove = $"{transactions.id}"; + var balance = debtor - creditor; + int templateId = 0; + //انتخاب قالب پیامک بر اساس حقیق/حقوقی + if (isLegal) + { + templateId = 789638; + if (typeOfSmsSetting == + TypeOfSmsSetting.MonthlyInstitutionContract) + { + templateId = 983035; + } + } + else + { + templateId = 768277; + if (typeOfSmsSetting == + TypeOfSmsSetting.MonthlyInstitutionContract) + { + templateId = 479624; + } + } + + if (balance > 0) // اگر بدهکار بود + { + var balanceToMoney = balance.ToMoney(); + + foreach (var number in phoneNumbers) + { + string publicId = transactions.PublicIdStr; + string code1 = publicId.Substring(0, 25); + string code2 = publicId.Substring(25); + + + smsList.Add(new SmsListData() + { + PhoneNumber = number.PhoneNumber, + TemplateId = templateId, + PartyName = partyName, + Amount = balanceToMoney, + ContractingPartyId = contractingParty.id, + AproveId = aprove, + TypeOfSmsMethod = "MonthlyBillNew", + Code1 = code1, + Code2 = code2, + InstitutionContractId = item.Id + }); + + } + } + } + } + } + + } + catch (Exception e) + { + _logger.LogError($"ContractingPartyId : {item.ContractingPartyId} - ContractingPartyName : {item.ContractingPartyName} - InstitutionContractId : {item.Id} خطای دریافت لیست بدهکاران "); + throw; + } + } + + #endregion Console.WriteLine("SmsListData: " + watch.Elapsed); return smsList; } - public async Task SendBlockSmsToContractingParties(List smsListData, string typeOfSms, - string sendMessStart, string sendMessEnd) - { - if (smsListData.Any()) - { - await _smsService.Alarm("09114221321", sendMessStart); - Thread.Sleep(1000); - await _smsService.Alarm("09111485044", sendMessStart); - Thread.Sleep(1000); - int successProcess = 1; - int countList = smsListData.Count; - foreach (var item in smsListData) - { - try - { - var smsResult = await _smsService.BlockMessage(item.PhoneNumber, item.PartyName, - item.Amount, item.AccountType, $"{item.ContractingPartyId}", item.AproveId); - Thread.Sleep(1000); - var createSmsResult = new Company.Domain.SmsResultAgg.SmsResult(smsResult.messaeId, - smsResult.message, typeOfSms, - item.PartyName, item.PhoneNumber, item.ContractingPartyId, item.InstitutionContractId); - await _smsResultRepository.CreateAsync(createSmsResult); - await _smsResultRepository.SaveChangesAsync(); - } - catch (Exception e) - { - string name = item.PartyName.Length > 18 ? item.PartyName.Substring(0, 18) : item.PartyName; - string errMess = $"{name}-خطا"; - await _smsService.Alarm("09114221321", errMess); - } - - Thread.Sleep(600); - var percent = (successProcess / (double)countList) * 100; - await _hubContext.Clients.Group(SendSmsHub.GetGroupName(10)) - .SendAsync("showStatus", (int)percent); - - successProcess += 1; - } - - - await _smsService.Alarm("09114221321", sendMessEnd); - Thread.Sleep(1000); - await _smsService.Alarm("09111485044", sendMessEnd); - } - } /// /// ارسال پیامک های یاد آور بدهی @@ -4645,6 +4795,7 @@ public class InstitutionContractRepository : RepositoryBase @@ -4816,7 +4967,7 @@ public class InstitutionContractRepository : RepositoryBase new InstitutionContractInstallmentViewModel - { AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr }) + { AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr }) .OrderBy(ins => ins.InstallmentDateGr).Skip(1).ToList(), }).Where(x => x.ContractStartGr < endOfMonthGr && x.ContractEndGr >= endOfMonthGr && x.ContractAmountDouble > 0 && @@ -4863,7 +5014,7 @@ public class InstitutionContractRepository : RepositoryBase new InstitutionContractInstallmentViewModel - { AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr }) + { AmountDouble = ins.Amount, InstallmentDateGr = ins.InstallmentDateGr }) .OrderBy(ins => ins.InstallmentDateGr).Skip(1).ToList(), }).ToListAsync(); @@ -5167,6 +5318,9 @@ public class InstitutionContractRepository : RepositoryBase GetIdByInstallmentId(long installmentId) { return await _context.InstitutionContractSet.Include(x => x.Installments) @@ -5520,7 +5674,7 @@ public class InstitutionContractRepository : RepositoryBase x.Id == request.TempId) .FirstOrDefaultAsync(); - // creationTemp.SetContractingPartyInfo(request.LegalType,request.RealParty,request.LegalParty); + // creationTemp.SetContractingPartyInfo(request.LegalType,request.RealParty,request.LegalParty); if (creationTemp == null) { @@ -5567,6 +5721,45 @@ public class InstitutionContractRepository : RepositoryBase GetIncludeInstallments(long id) + { + return _context.InstitutionContractSet.Include(x => x.Installments) + .FirstOrDefaultAsync(x => x.id == id); + } + private async Task> CreateLegalContractingPartyEntity( InstitutionContractCreationTempLegalParty request, long representativeId, string address, string city, string state) @@ -6333,6 +6532,377 @@ public class InstitutionContractRepository : RepositoryBase + x.DayOfMonth >= dayOfMonth && + x.TimeOfDay.Hours == hour && + x.TimeOfDay.Minutes == minute && + x.TypeOfSmsSetting == TypeOfSmsSetting.Warning && + x.IsActive + ); + } + else + { + checkAnyToExecute = await _context.SmsSettings + .AnyAsync(x => + x.DayOfMonth == dayOfMonth && + x.TimeOfDay.Hours == hour && + x.TimeOfDay.Minutes == minute && + x.TypeOfSmsSetting == TypeOfSmsSetting.Warning && + x.IsActive + ); + } + + + if (checkAnyToExecute) + { + //اجرای تسک + _logger.LogInformation("اجرای تسک ارسال پیامک هشدار SendWarningSms" + + persianNow + " - " + hour + ":" + minute); + + + } + } + + /// + ///دریافت لیست پیامک قرادا های آبی بدهکار + /// + /// + //public async Task> GetBlueSmsListData() + //{ + + // var institutionContracts = await _context.InstitutionContractSet.AsQueryable().Select(x => new InstitutionContractViewModel + // { + // Id = x.id, + // ContractingPartyId = x.ContractingPartyId, + // ContractingPartyName = x.ContractingPartyName, + // ContractStartGr = x.ContractStartGr, + // ContractStartFa = x.ContractStartFa, + // ContractEndGr = x.ContractEndGr, + // ContractEndFa = x.ContractEndFa, + // IsActiveString = x.IsActiveString, + // ContractAmountDouble = x.ContractAmount, + // OfficialCompany = x.OfficialCompany, + // IsInstallment = x.IsInstallment, + // VerificationStatus = x.VerificationStatus, + // SigningType = x.SigningType, + // }).Where(x => x.IsActiveString == "blue" && + // x.ContractAmountDouble > 0).GroupBy(x => x.ContractingPartyId).Select(x => x.First()).ToListAsync(); + + // // قرارداد هایی که بطور یکجا پرداخت شده اند + // var paidInFull = institutionContracts.Where(x => + // x.SigningType != InstitutionContractSigningType.Legacy && x.IsInstallment == false && x.SigningType != null).ToList(); + + // //حذف قراداد هایی که یکجا پرداخت شده اند از لیست ایجاد سند ماهانه + // institutionContracts = institutionContracts.Except(paidInFull).ToList(); + + // var contractingPartyList = await _context.PersonalContractingParties + // .Where(x => institutionContracts.Select(ins => ins.ContractingPartyId).Contains(x.id)).ToListAsync(); + + // var financialStatmentList = await _context.FinancialStatments.AsSplitQuery() + // .Where(x => institutionContracts.Select(ins => ins.ContractingPartyId).Contains(x.ContractingPartyId)) + // .Include(x => x.FinancialTransactionList).Where(x => x.FinancialTransactionList.Count > 0).ToListAsync(); + + // var phoneNumberList = await _context.InstitutionContractContactInfos + // .Where(x => institutionContracts.Select(ins => ins.Id).Contains(x.InstitutionContractId)) + // .Where(x => x.SendSms && x.PhoneType == "شماره همراه" && !string.IsNullOrWhiteSpace(x.PhoneNumber) && + // x.PhoneNumber.Length == 11).ToListAsync(); + // var legalActionSentSms =await _context.SmsResults + // .Where(x => x.TypeOfSms == "اقدام قضایی").ToListAsync(); + // var warningSentSms = await _context.SmsResults.Where(x => x.TypeOfSms.Contains("هشدار")).ToListAsync(); + + // var oldInstitutionContract = institutionContracts.Where(x => x.IsInstallment == false).ToList(); + // var electronicInstitutionContract = institutionContracts.Where(x => x.IsInstallment == true).ToList(); + + // foreach (var item in oldInstitutionContract) + // { + // try + // { + // var contractingParty = GetDetails(item.ContractingPartyId); + // bool hasLegalActionSentSms = legalActionSentSms.Any(x => x.InstitutionContractId == item.Id); + + // if (!string.IsNullOrWhiteSpace(contractingParty.LName) && !hasLegalActionSentSms) + // { + // //Thread.Sleep(500); + // var partyName = contractingParty.LName; + + // if (partyName.Length > 25) partyName = $"{partyName.Substring(0, 25)}"; + + // var isLegal = contractingParty.IsLegal == "حقوقی" ? true : false; + // var isBlock = contractingParty.IsBlock == "true" ? true : false; + // var isActive = contractingParty.IsActiveString == "true" ? true : false; + // if (!string.IsNullOrWhiteSpace(contractingParty.IsActiveString)) + // { + // var hasFinancialStatement = + // financialStatmentList.Any(x => x.ContractingPartyId == item.ContractingPartyId); + + // var hasPhonNumber = phoneNumberList.Any(x => x.InstitutionContractId == item.Id); + + // if (hasFinancialStatement && hasPhonNumber) + // { + // var phoneNumbers = phoneNumberList.Where(x => x.InstitutionContractId == item.Id) + // .Select(x => new CreateContactInfo + // { + // PhoneType = x.PhoneType, + // PhoneNumber = x.PhoneNumber, + + // InstitutionContractId = x.InstitutionContractId, + // SendSms = x.SendSms + // }).Where(x => x.PhoneNumber.Length == 11).ToList(); + + // var transactions = financialStatmentList.FirstOrDefault(x => + // x.ContractingPartyId == item.ContractingPartyId); + + + // var debtor = transactions.FinancialTransactionViewModels.Sum(x => x.Deptor); + // var creditor = transactions.FinancialTransactionViewModels.Sum(x => x.Creditor); + + + // var id = $"{item.ContractingPartyId}"; + // var aprove = $"{transactions.Id}"; + // var balance = debtor - creditor; + + // if (balance > 0) // اگر بدهکار بود + // { + + // if (isLegal) + // { + // if (item.OfficialCompany == "Official") // حقوقی بدهکار رسمی + // { + // var balanceToMoney = balance.ToMoney(); + + // foreach (var number in phoneNumbers) + // { + + // var isLastAlarmSend = _context.SmsResults.Any(x => ( + // x.ContractingPatyId == contractingParty.Id && + // x.Mobile == number.PhoneNumber) && (x.TypeOfSms == "اقدام قضایی" || x.TypeOfSms == "هشدار دوم")); + + // if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && + // number.PhoneNumber.Length == 11 && !isSend && !isLastAlarmSend) + // { + + // var smsResult = _smsService.MonthlyBill(number.PhoneNumber, 608443, + // partyName, + // balanceToMoney, id, aprove); + // Thread.Sleep(1000); + // if (smsResult.IsSuccedded) + // { + // var createSmsResult = new SmsResult(smsResult.MessageId, + // smsResult.Message, typeOfSms, partyName, number.PhoneNumber, + // item.ContractingPartyId, item.Id); + // _smsResultRepository.Create(createSmsResult); + // _smsResultRepository.SaveChanges(); + // Thread.Sleep(1000); + // } + + // } + // } + + + + // } + // else if (item.OfficialCompany == "NotOfficial") // حقوقی بدهکار غیر رسمی + // { + // var balanceToMoney = balance.ToMoney(); + // foreach (var number in phoneNumbers) + // { + // var isSend = _context.SmsResults.Any(x => + // x.ContractingPatyId == contractingParty.Id && + // x.Mobile == number.PhoneNumber && x.TypeOfSms == typeOfSms); + // var isLastAlarmSend = _context.SmsResults.Any(x => ( + // x.ContractingPatyId == contractingParty.Id && + // x.Mobile == number.PhoneNumber) && (x.TypeOfSms == "اقدام قضایی" || x.TypeOfSms == "هشدار دوم")); + // if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && + // number.PhoneNumber.Length == 11 && !isSend && !isLastAlarmSend) + // { + + // var smsResult = _smsService.MonthlyBill(number.PhoneNumber, 351691, + // partyName, + // balanceToMoney, id, aprove); + // Thread.Sleep(1000); + // if (smsResult.IsSuccedded) + // { + // var createSmsResult = new SmsResult(smsResult.MessageId, + // smsResult.Message, typeOfSms, partyName, number.PhoneNumber, + // item.ContractingPartyId, item.Id); + // _smsResultRepository.Create(createSmsResult); + // _smsResultRepository.SaveChanges(); + // Thread.Sleep(1000); + // } + + + + // } + // } + + + // } + // } + // else + // { + // if (item.OfficialCompany == "Official") // حقیقی بدهکار رسمی + // { + // var balanceToMoney = balance.ToMoney(); + + // foreach (var number in phoneNumbers) + // { + // var isSend = _context.SmsResults.Any(x => + // x.ContractingPatyId == contractingParty.Id && + // x.Mobile == number.PhoneNumber && x.TypeOfSms == typeOfSms); + // var isLastAlarmSend = _context.SmsResults.Any(x => ( + // x.ContractingPatyId == contractingParty.Id && + // x.Mobile == number.PhoneNumber) && (x.TypeOfSms == "اقدام قضایی" || x.TypeOfSms == "هشدار دوم")); + // if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && + // number.PhoneNumber.Length == 11 && !isSend && !isLastAlarmSend) + // { + + // var smsResult = _smsService.MonthlyBill(number.PhoneNumber, 190430, + // partyName, + // balanceToMoney, id, aprove); + // Thread.Sleep(1000); + // if (smsResult.IsSuccedded) + // { + // var createSmsResult = new SmsResult(smsResult.MessageId, + // smsResult.Message, typeOfSms, partyName, number.PhoneNumber, + // item.ContractingPartyId, item.Id); + // _smsResultRepository.Create(createSmsResult); + // _smsResultRepository.SaveChanges(); + // Thread.Sleep(1000); + // } + // } + // } + + + // } + // else if (item.OfficialCompany == "NotOfficial") // حقیقی بدهکار غیر رسمی + // { + // var balanceToMoney = balance.ToMoney(); + + // foreach (var number in phoneNumbers) + // { + // var isSend = _context.SmsResults.Any(x => + // x.ContractingPatyId == contractingParty.Id && + // x.Mobile == number.PhoneNumber && x.TypeOfSms == typeOfSms); + // var isLastAlarmSend = _context.SmsResults.Any(x => ( + // x.ContractingPatyId == contractingParty.Id && + // x.Mobile == number.PhoneNumber) && (x.TypeOfSms == "اقدام قضایی" || x.TypeOfSms == "هشدار دوم")); + // if (!string.IsNullOrWhiteSpace(number.PhoneNumber) && + // number.PhoneNumber.Length == 11 && !isSend && !isLastAlarmSend) + // { + // var smsResult = _smsService.MonthlyBill(number.PhoneNumber, 412829, + // partyName, + // balanceToMoney, id, aprove); + // Thread.Sleep(1000); + // if (smsResult.IsSuccedded) + // { + // var createSmsResult = new SmsResult(smsResult.MessageId, + // smsResult.Message, typeOfSms, partyName, number.PhoneNumber, + // item.ContractingPartyId, item.Id); + // _smsResultRepository.Create(createSmsResult); + // _smsResultRepository.SaveChanges(); + // Thread.Sleep(1000); + // } + + + // } + // } + + + // } + // } + // } + // } + // } + // } + // } + // catch (Exception e) + // { + + + // string name = item.ContractingPartyName.Length > 18 ? item.ContractingPartyName.Substring(0, 18) : item.ContractingPartyName; + // string errMess = $"{name}-خطا"; + // _smsService.Alarm("09114221321", errMess); + // _logger.LogError(e, "BlueWarningSms"); + // } + // } + //} + #endregion + + + #region LegalActionSms + + + public async Task SendLegalActionSmsTask() + { + var now = DateTime.Now; + + + // تبدیل تاریخ میلادی به شمسی + var persianNow = now.ToFarsi(); + var persianEndOfMonth = int.Parse(persianNow.FindeEndOfMonth().Substring(8, 2)); + var dayOfMonth = int.Parse(persianNow.Substring(8, 2)); + var hour = now.Hour; + var minute = now.Minute; + var checkAnyToExecute = false; + + //اگر آخرین روز ماه باشد + //اگر روز مثلا عدد روز 31 بود ولی آخرین روز ماه 30 بود + if (dayOfMonth == persianEndOfMonth) + { + checkAnyToExecute = await _context.SmsSettings + .AnyAsync(x => + x.DayOfMonth >= dayOfMonth && + x.TimeOfDay.Hours == hour && + x.TimeOfDay.Minutes == minute && + x.TypeOfSmsSetting == TypeOfSmsSetting.LegalAction && + x.IsActive + ); + } + else + { + checkAnyToExecute = await _context.SmsSettings + .AnyAsync(x => + x.DayOfMonth == dayOfMonth && + x.TimeOfDay.Hours == hour && + x.TimeOfDay.Minutes == minute && + x.TypeOfSmsSetting == TypeOfSmsSetting.LegalAction && + x.IsActive + ); + } + + if (checkAnyToExecute) + { + //اجرای تسک + _logger.LogInformation("اجرای تسک ارسال پیامک اقدام قضائی SendLegalActionSms" + + persianNow + " - " + hour + ":" + minute); + + + } + + } + #endregion + #region CustomViewModels public class WorkshopsAndEmployeeViewModel diff --git a/CompanyManagment.EFCore/Repository/PersonalContractingPartyRepository.cs b/CompanyManagment.EFCore/Repository/PersonalContractingPartyRepository.cs index ba888dc6..e0225194 100644 --- a/CompanyManagment.EFCore/Repository/PersonalContractingPartyRepository.cs +++ b/CompanyManagment.EFCore/Repository/PersonalContractingPartyRepository.cs @@ -773,6 +773,137 @@ public class PersonalContractingPartyRepository : RepositoryBase x.NationalId == nationalId); } + public async Task 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 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 } diff --git a/CompanyManagment.EFCore/Services/SmsService.cs b/CompanyManagment.EFCore/Services/SmsService.cs index 5f2da288..82cf6917 100644 --- a/CompanyManagment.EFCore/Services/SmsService.cs +++ b/CompanyManagment.EFCore/Services/SmsService.cs @@ -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(); + 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 diff --git a/PersonalContractingParty.Config/PersonalBootstrapper.cs b/PersonalContractingParty.Config/PersonalBootstrapper.cs index ebb0e49f..92e63a87 100644 --- a/PersonalContractingParty.Config/PersonalBootstrapper.cs +++ b/PersonalContractingParty.Config/PersonalBootstrapper.cs @@ -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(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/ServiceHost/Areas/Admin/Controllers/institutionContractController.cs b/ServiceHost/Areas/Admin/Controllers/institutionContractController.cs index b6794d88..62535914 100644 --- a/ServiceHost/Areas/Admin/Controllers/institutionContractController.cs +++ b/ServiceHost/Areas/Admin/Controllers/institutionContractController.cs @@ -48,7 +48,8 @@ public class institutionContractController : AdminBaseController IPersonalContractingPartyApp contractingPartyApplication, IContactInfoApplication contactInfoApplication, IAccountApplication accountApplication, IEmployerApplication employerApplication, IWorkshopApplication workshopApplication, ITemporaryClientRegistrationApplication temporaryClientRegistration, - ITemporaryClientRegistrationApplication clientRegistrationApplication, IHttpClientFactory httpClientFactory) + ITemporaryClientRegistrationApplication clientRegistrationApplication, IHttpClientFactory httpClientFactory + ,ILogger sepehrGatewayLogger) { _institutionContractApplication = institutionContractApplication; _contractingPartyApplication = contractingPartyApplication; @@ -58,7 +59,7 @@ public class institutionContractController : AdminBaseController _workshopApplication = workshopApplication; _temporaryClientRegistration = temporaryClientRegistration; _clientRegistrationApplication = clientRegistrationApplication; - _paymentGateway = new SepehrPaymentGateway(httpClientFactory); + _paymentGateway = new SepehrPaymentGateway(httpClientFactory, sepehrGatewayLogger); } /// @@ -241,7 +242,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 { @@ -338,21 +340,6 @@ public class institutionContractController : AdminBaseController }); } - /// - /// دانلود اکسل - /// - /// - [HttpGet("excel")] - public IActionResult OnGetDownloadExcel() - { - var institutionContractViewModels = - _institutionContractApplication.NewSearch(new() { IsActiveString = "both", TypeOfContract = "both" }); - var bytes = InstitutionContractExcelGenerator.GenerateExcel(new List()); - return File(bytes, - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - $"قرارداد های مالی.xlsx"); - } - [HttpPost("create/inquiry")] public async Task>> CreateInquiry( [FromBody] InstitutionContractCreationInquiryRequest request) @@ -548,7 +535,7 @@ public class institutionContractController : AdminBaseController return res; } - [HttpPost("creation/set-contracting-party")] + [HttpGet("creation/get-representative")] public async Task> GetRepresentatives(string nationalCode) { var res = await _contractingPartyApplication.GetRepresentativeIdByNationalCode(nationalCode); diff --git a/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs b/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs index c646f563..22ba9995 100644 --- a/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs +++ b/ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs @@ -89,7 +89,8 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk CompanyContext context, AccountContext accountContext, IHttpClientFactory httpClientFactory, IOptions appSetting, ITemporaryClientRegistrationApplication clientRegistrationApplication, IOnlinePayment onlinePayment, - IFaceEmbeddingService faceEmbeddingService, IAuthHelper authHelper, IInstitutionContractApplication institutionContractApplication) + IFaceEmbeddingService faceEmbeddingService, IAuthHelper authHelper, IInstitutionContractApplication institutionContractApplication + ,ILogger sepehrGatewayLogger) { _application = application; _rollCallDomainService = rollCallDomainService; @@ -101,7 +102,7 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk _faceEmbeddingService = faceEmbeddingService; _authHelper = authHelper; _institutionContractApplication = institutionContractApplication; - _paymentGateway = new SepehrPaymentGateway(httpClientFactory); + _paymentGateway = new SepehrPaymentGateway(httpClientFactory, sepehrGatewayLogger); } public void OnGet() diff --git a/ServiceHost/Areas/AdminNew/Pages/Company/FileBackup/Index.cshtml b/ServiceHost/Areas/AdminNew/Pages/Company/FileBackup/Index.cshtml index 9220ef4a..5a27d5cd 100644 --- a/ServiceHost/Areas/AdminNew/Pages/Company/FileBackup/Index.cshtml +++ b/ServiceHost/Areas/AdminNew/Pages/Company/FileBackup/Index.cshtml @@ -219,7 +219,7 @@
- + diff --git a/ServiceHost/Areas/AdminNew/Pages/Company/FileBackup/Index.cshtml.cs b/ServiceHost/Areas/AdminNew/Pages/Company/FileBackup/Index.cshtml.cs index 894764b7..de2e2326 100644 --- a/ServiceHost/Areas/AdminNew/Pages/Company/FileBackup/Index.cshtml.cs +++ b/ServiceHost/Areas/AdminNew/Pages/Company/FileBackup/Index.cshtml.cs @@ -1,4 +1,4 @@ -using _0_Framework.Application; +using _0_Framework.Application; using _0_Framework.Infrastructure; using _0_Framework.InfraStructure; using backService; @@ -6,6 +6,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Configuration.UserSecrets; +using System.IO; namespace ServiceHost.Areas.AdminNew.Pages.Company.FileBackup { @@ -68,8 +69,8 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.FileBackup { FileName = Path.GetFileName(x), FullPath = x, - CreationDate = Path.GetFileName(x).ExtractTimeFromInsurancebackup(), - }).OrderByDescending(x => x.CreationDate).ToList(); + CreationDate = new DateTime(), + }).ToList(); #endregion @@ -89,5 +90,22 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.FileBackup byte[] fileContent = System.IO.File.ReadAllBytes(path); return File(fileContent, "application/zip", fileName); } - } + + + public IActionResult OnGetDownloadFileLog(string path, string fileName) + { + if (!System.IO.File.Exists(path)) + return NotFound(); + + var stream = new FileStream( + path, + FileMode.Open, + FileAccess.Read, + FileShare.ReadWrite // 🔑 کلید حل مشکل + ); + + return File(stream, "text/plain", fileName); + } + + } } diff --git a/ServiceHost/Areas/Client/Controllers/FinancialController.cs b/ServiceHost/Areas/Client/Controllers/FinancialController.cs index 96b001be..68d8d494 100644 --- a/ServiceHost/Areas/Client/Controllers/FinancialController.cs +++ b/ServiceHost/Areas/Client/Controllers/FinancialController.cs @@ -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 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; } /// - /// ساخت + /// ساخت درگاه پرداخت برای موجودی حساب کلاینت /// - /// - /// - /// - /// [HttpPost("CreatePay")] [AllowAnonymous] - public async Task>> CreatePay([FromForm] CreateFinancialPayRequest request, CancellationToken cancellationToken) + public async Task>> CreatePay([FromForm] CreateFinancialPayRequest request) { var op = new OperationResult(); - 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); } } \ No newline at end of file diff --git a/ServiceHost/Controllers/GeneralController.cs b/ServiceHost/Controllers/GeneralController.cs index 4854bd4c..7871eef9 100644 --- a/ServiceHost/Controllers/GeneralController.cs +++ b/ServiceHost/Controllers/GeneralController.cs @@ -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; } /// @@ -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 Verify([FromForm]SepehrGatewayPayResponse payResponse) + public async Task 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>(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 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 HandleFailedTransaction(PaymentTransactionDetailsViewModel transaction) - { - var result = _paymentTransactionApplication.SetFailed(transaction.Id); - if (!result.IsSuccedded) - { - return new JsonResult(result); - } - + // در صورت ناموفق بودن return Redirect(BuildCallbackUrl(transaction.CallBackUrl, false, transaction.Id)); } diff --git a/ServiceHost/Program.cs b/ServiceHost/Program.cs index 53ed6274..921656cd 100644 --- a/ServiceHost/Program.cs +++ b/ServiceHost/Program.cs @@ -32,6 +32,8 @@ using GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser; using GozareshgirProgramManager.Infrastructure; using GozareshgirProgramManager.Infrastructure.Persistence.Seed; using Microsoft.OpenApi; +using Serilog; +using Serilog.Events; using ServiceHost.Hubs.ProgramManager; using ServiceHost.Notifications.ProgramManager; using ServiceHost.Conventions; @@ -53,7 +55,36 @@ builder.Services.AddHttpClient("holidayApi", c => c.BaseAddress = new System.Uri var connectionString = builder.Configuration.GetConnectionString("MesbahDb"); var connectionStringTestDb = builder.Configuration.GetConnectionString("TestDb"); +#region Serilog +var logDirectory = @"C:\Logs\Gozareshgir\"; +if (!Directory.Exists(logDirectory)) +{ + Directory.CreateDirectory(logDirectory); +} + +Log.Logger = new LoggerConfiguration() + //NO EF Core log + .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning) + + //NO DbCommand log + .MinimumLevel.Override("Microsoft.EntityFrameworkCore.Database.Command", LogEventLevel.Warning) + + //NO Microsoft Public log + .MinimumLevel.Override("Microsoft", LogEventLevel.Warning) + //.MinimumLevel.Information() + .WriteTo.File( + path: Path.Combine(logDirectory, "gozareshgir_log.txt"), + rollingInterval: RollingInterval.Day, + retainedFileCountLimit: 30, + shared: true, + outputTemplate: + "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}" + ).CreateLogger(); + + + +#endregion builder.Services.AddProgramManagerApplication(); builder.Services.AddProgramManagerInfrastructure(builder.Configuration); @@ -348,7 +379,8 @@ builder.Services.AddParbad().ConfigureGateways(gateways => }); - +builder.Host.UseSerilog(); +Log.Information("SERILOG STARTED SUCCESSFULLY"); var app = builder.Build(); app.UseCors("AllowSpecificOrigins"); diff --git a/ServiceHost/ServiceHost.csproj b/ServiceHost/ServiceHost.csproj index 744e0213..8eb8a743 100644 --- a/ServiceHost/ServiceHost.csproj +++ b/ServiceHost/ServiceHost.csproj @@ -94,11 +94,16 @@ + + + + + diff --git a/ServiceHost/appsettings.json b/ServiceHost/appsettings.json index 641c99b3..5c8728c8 100644 --- a/ServiceHost/appsettings.json +++ b/ServiceHost/appsettings.json @@ -22,7 +22,7 @@ "DbName": "mesbah_db", "DbBackupZipPath": "c://EveryHourBackupList//", "FastDbBackupZipPath": "c://FastBackupZipList//", - "InsuranceListZipPath": "c://InsuranceListZipPath//" + "InsuranceListZipPath": "c://Logs//Gozareshgir//" }, "faceModels": { "Faces": "c://labels//20//"