Merge branch 'Feature/FinancialInvoice/Init'

# Conflicts:
#	PersonalContractingParty.Config/PersonalBootstrapper.cs
This commit is contained in:
2025-11-17 20:52:31 +03:30
42 changed files with 56581 additions and 220 deletions

View File

@@ -39,7 +39,7 @@ public class AqayePardakhtPaymentGateway:IPaymentGateway
amount = command.Amount,
callback = command.CallBackUrl,
card_number = command.CardNumber,
invoice_id = command.InvoiceId,
invoice_id = command.TransactionId,
mobile = command.Mobile,
email = command.Email??"",
description = command.Description,
@@ -73,7 +73,7 @@ public class AqayePardakhtPaymentGateway:IPaymentGateway
amount = command.Amount,
callback = command.CallBackUrl,
card_number = command.Amount,
invoice_id = command.InvoiceId,
invoice_id = command.TransactionId,
mobile = command.Mobile,
email = command.Email,
description = command.Email,

View File

@@ -49,12 +49,13 @@ public class WalletAmountResponse
public class CreatePaymentGatewayRequest
{
public double Amount { get; set; }
public string TransactionId { get; set; }
public string CallBackUrl { get; set; }
public string InvoiceId { get; set; }
public string CardNumber { get; set; }
public string Mobile { get; set; }
public string Email { get; set; }
public string Description { get; set; }
public long FinancialInvoiceId { get; set; }
public IDictionary<string, object> ExtraData { get; set; }
}

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading;
@@ -16,18 +17,18 @@ public class SepehrPaymentGateway:IPaymentGateway
{
_httpClient = httpClient.CreateClient();
_httpClient.BaseAddress = new Uri("https://sepehr.shaparak.ir/Rest/V1/PeymentApi/");
}
public async Task<PaymentGatewayResponse> Create(CreatePaymentGatewayRequest command, CancellationToken cancellationToken = default)
{
command.ExtraData ??= new Dictionary<string, object>();
command.ExtraData.Add("financialInvoiceId", command.FinancialInvoiceId);
var extraData = JsonConvert.SerializeObject(command.ExtraData);
var res = await _httpClient.PostAsJsonAsync("GetToken", new
{
TerminalID = TerminalId,
Amount = command.Amount,
InvoiceID = command.InvoiceId,
InvoiceID = command.TransactionId,
callbackURL = command.CallBackUrl,
payload = extraData
}, cancellationToken: cancellationToken);

View File

@@ -0,0 +1,108 @@
using System;
using System.Collections.Generic;
using _0_Framework.Domain;
using Company.Domain.PaymentTransactionAgg;
using CompanyManagment.App.Contracts.FinancialInvoice;
namespace Company.Domain.FinancialInvoiceAgg;
public class FinancialInvoice : EntityBase
{
public string InvoiceNumber { get; private set; }
public string Description { get; set; }
public FinancialInvoiceStatus Status { get; private set; }
public DateTime? PaidAt { get; private set; }
public double Amount { get; private set; }
public Guid PublicId { get; private set; }
public bool IsActive { get; set; }
public List<PaymentTransaction> PaymentTransactions { get; private set; }
public long ContractingPartyId { get; private set; }
public List<FinancialInvoiceItem> Items { get; private set; }
public FinancialInvoice(double amount, long contractingPartyId, string description)
{
InvoiceNumber = GenerateInvoiceNumber();
Status = FinancialInvoiceStatus.Unpaid;
Amount = amount;
PublicId = Guid.NewGuid();
ContractingPartyId = contractingPartyId;
Description = description;
IsActive = true;
Items = [];
PaymentTransactions = [];
}
public void AddItem(FinancialInvoiceItem item)
{
Items ??= [];
Items.Add(item);
}
public void SetItems(List<FinancialInvoiceItem> items)
{
Items = items;
}
public void SetPaid(DateTime paidAt)
{
Status = FinancialInvoiceStatus.Paid;
PaidAt = paidAt;
}
public void SetUnpaid()
{
Status = FinancialInvoiceStatus.Unpaid;
PaidAt = null;
}
public void SetCancelled()
{
Status = FinancialInvoiceStatus.Cancelled;
PaidAt = null;
}
public void SetRefunded()
{
Status = FinancialInvoiceStatus.Refunded;
PaidAt = null;
}
public void DeActivate()
{
IsActive = false;
}
public void SetInvoiceNumber(string invoiceNumber)
{
InvoiceNumber = invoiceNumber;
}
private string GenerateInvoiceNumber()
{
var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
var random = new Random().Next(1000, 9999);
return $"GZ_{timestamp}{random}";
}
}
public class FinancialInvoiceItem : EntityBase
{
public string Description { get; private set; }
public double Amount { get; private set; }
public FinancialInvoiceItemType Type { get; set; }
public long EntityId { get; set; }
public FinancialInvoice FinancialInvoice { get; set; }
public long FinancialInvoiceId { get; set; }
public FinancialInvoiceItem(string description, double amount,
long financialInvoiceId, FinancialInvoiceItemType type, long entityId)
{
Description = description;
Amount = amount;
FinancialInvoiceId = financialInvoiceId;
Type = type;
EntityId = entityId;
}
}

View File

@@ -0,0 +1,13 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using _0_Framework.Domain;
using CompanyManagment.App.Contracts.FinancialInvoice;
namespace Company.Domain.FinancialInvoiceAgg;
public interface IFinancialInvoiceRepository : IRepository<long, FinancialInvoice>
{
EditFinancialInvoice GetDetails(long id);
List<FinancialInvoiceViewModel> Search(FinancialInvoiceSearchModel searchModel);
Task<FinancialInvoice> GetUnPaidByEntityId(long entityId, FinancialInvoiceItemType financialInvoiceItemType);
}

View File

@@ -5,6 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _0_Framework.Domain;
using Company.Domain.FinancialInvoiceAgg;
using Company.Domain.FinancialTransactionAgg;
namespace Company.Domain.FinancialStatmentAgg;

View File

@@ -22,6 +22,8 @@ public interface IFinancialStatmentRepository : IRepository<long, FinancialStatm
Task<OperationResult<ClientFinancialStatementViewModel>> GetDetailsByPublicId(string publicId);
Task<GetFinancialStatementBalanceAmount> GetBalanceAmount(long id);
Task<double> GetClientDebtAmount(long accountId);
Task<FinancialStatmentDetailsByContractingPartyViewModel> GetDetailsByContractingParty(long contractingPartyId,FinancialStatementSearchModel searchModel);
Task<double> GetClientDebtAmountByContractingPartyId(long contractingPartyId);
Task<FinancialStatmentDetailsByContractingPartyViewModel> GetDetailsByContractingParty(long contractingPartyId,FinancialStatementSearchModel searchModel);
Task<FinancialStatment> GetByContractingPartyId(long contractingPartyId);
}

View File

@@ -1,5 +1,6 @@
using System;
using _0_Framework.Domain;
using Company.Domain.FinancialInvoiceAgg;
using CompanyManagment.App.Contracts.PaymentTransaction;
namespace Company.Domain.PaymentTransactionAgg;
@@ -9,14 +10,15 @@ namespace Company.Domain.PaymentTransactionAgg;
/// </summary>
public class PaymentTransaction:EntityBase
{
/// <summary>
/// سازنده کلاس PaymentTransaction با دریافت اطلاعات تراکنش.
/// </summary>
/// <param name="contractingPartyId">شناسه طرف قرارداد</param>
/// <param name="amount">مبلغ تراکنش</param>
/// <param name="contractingPartyName"></param>
/// <param name="callBackUrl"></param>
public PaymentTransaction(long contractingPartyId,
/// <summary>
/// سازنده کلاس PaymentTransaction با دریافت اطلاعات تراکنش.
/// </summary>
/// <param name="contractingPartyId">شناسه طرف قرارداد</param>
/// <param name="amount">مبلغ تراکنش</param>
/// <param name="contractingPartyName"></param>
/// <param name="callBackUrl"></param>
/// <param name="gateway"></param>
public PaymentTransaction(long contractingPartyId,
double amount,
string contractingPartyName,string callBackUrl,
PaymentTransactionGateWay gateway)
@@ -74,6 +76,9 @@ public class PaymentTransaction:EntityBase
public string Rrn { get; private set; }
public string DigitalReceipt { get; private set; }
public FinancialInvoice FinancialInvoice { get; set; }
public long? FinancialInvoiceId { get; set; }
public void SetPaid(string cardNumber,string bankName,string rrn,string digitalReceipt)
{

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
namespace CompanyManagment.App.Contracts.FinancialInvoice;
public class CreateFinancialInvoice
{
public double Amount { get; set; }
public long ContractingPartyId { get; set; }
public string Description { get; set; }
public List<CreateFinancialInvoiceItem>? Items { get; set; }
}
public class CreateFinancialInvoiceItem
{
public string Description { get; set; }
public double Amount { get; set; }
public FinancialInvoiceItemType Type { get; set; }
public long EntityId { get; set; }
}

View File

@@ -0,0 +1,23 @@
using System.Collections.Generic;
namespace CompanyManagment.App.Contracts.FinancialInvoice;
public class EditFinancialInvoice
{
public long Id { get; set; }
public string InvoiceNumber { get; set; }
public string Description { get; set; }
public double Amount { get; set; }
public FinancialInvoiceStatus Status { get; set; }
public List<EditFinancialInvoiceItem>? Items { get; set; }
}
public class EditFinancialInvoiceItem
{
public long Id { get; set; }
public string Description { get; set; }
public double Amount { get; set; }
public FinancialInvoiceItemType Type { get; set; }
public long EntityId { get; set; }
}

View File

@@ -0,0 +1,25 @@
namespace CompanyManagment.App.Contracts.FinancialInvoice;
public enum FinancialInvoiceItemType
{
/// <summary>
/// قسط قرارداد خرید از موسسه
/// </summary>
BuyInstitutionContractInstallment,
/// <summary>
/// خرید قرارداد از موسسه
/// </summary>
BuyInstitutionContract,
/// <summary>
///قسط ارتقا قرارداد موسسه
/// </summary>
AmendmentInstitutionContractInstallment,
/// <summary>
/// ارتقا قرارداد موسسه
/// </summary>
AmendmentInstitutionContract,
/// <summary>
/// بدهی قبلی
/// </summary>
PreviousDebt,
}

View File

@@ -0,0 +1,12 @@
namespace CompanyManagment.App.Contracts.FinancialInvoice;
public class FinancialInvoiceSearchModel
{
public string? Description { get; set; }
public FinancialInvoiceStatus? Status { get; set; }
public long? ContractingPartyId { get; set; }
public string? FromDate { get; set; }
public string? ToDate { get; set; }
public double? MinAmount { get; set; }
public double? MaxAmount { get; set; }
}

View File

@@ -0,0 +1,21 @@
namespace CompanyManagment.App.Contracts.FinancialInvoice;
public enum FinancialInvoiceStatus
{
/// <summary>
/// پرداخت نشده
/// </summary>
Unpaid = 0,
/// <summary>
/// پرداخت شده کامل
/// </summary>
Paid = 1,
/// <summary>
/// فاکتور لغو شده
/// </summary>
Cancelled = 4,
/// <summary>
/// // بازپرداخت شده (در صورت برگشت وجه)
/// </summary>
Refunded = 5,
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
namespace CompanyManagment.App.Contracts.FinancialInvoice;
public class FinancialInvoiceViewModel
{
public long Id { get; set; }
public string InvoiceNumber { get; set; }
public string Description { get; set; }
public string Status { get; set; }
public string PaidAt { get; set; }
public double Amount { get; set; }
public Guid PublicId { get; set; }
public long ContractingPartyId { get; set; }
public string ContractingPartyName { get; set; }
public string CreationDate { get; set; }
public int ItemsCount { get; set; }
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using _0_Framework.Application;
namespace CompanyManagment.App.Contracts.FinancialInvoice;
public interface IFinancialInvoiceApplication
{
OperationResult Create(CreateFinancialInvoice command);
OperationResult Edit(EditFinancialInvoice command);
OperationResult SetPaid(long id, DateTime paidAt);
OperationResult SetUnpaid(long id);
OperationResult SetCancelled(long id);
OperationResult SetRefunded(long id);
EditFinancialInvoice GetDetails(long id);
List<FinancialInvoiceViewModel> Search(FinancialInvoiceSearchModel searchModel);
}

View File

@@ -213,7 +213,7 @@ public interface IInstitutionContractApplication
Task<GetInstitutionVerificationDetailsViewModel> GetVerificationDetails(Guid id);
Task<OperationResult<OtpResultViewModel>> SendVerifyOtp(Guid id);
Task<OperationResult> VerifyOtp(Guid publicId, string code);
Task<OperationResult<string>> VerifyOtpAndMakeGateway(Guid publicId, string code, string callbackUrl);
Task<InstitutionContractWorkshopDetailViewModel> GetWorkshopInitialDetails(long workshopDetailsId);
#region Extension
@@ -251,6 +251,8 @@ public interface IInstitutionContractApplication
/// <param name="id"></param>
/// <returns></returns>
Task<InstitutionContractPrintViewModel> PrintOneAsync(long id);
Task<OperationResult> SetPendingWorkflow(long entityId);
}
public class InstitutionContractPrintViewModel

View File

@@ -0,0 +1,214 @@
using System;
using System.Collections.Generic;
using System.Linq;
using _0_Framework.Application;
using _0_Framework.InfraStructure;
using Company.Domain.FinancialInvoiceAgg;
using CompanyManagment.App.Contracts.FinancialInvoice;
using CompanyManagment.EFCore;
namespace CompanyManagment.Application;
public class FinancialInvoiceApplication : RepositoryBase<long, FinancialInvoice>, IFinancialInvoiceApplication
{
private readonly IFinancialInvoiceRepository _financialInvoiceRepository;
private readonly CompanyContext _context;
public FinancialInvoiceApplication(IFinancialInvoiceRepository financialInvoiceRepository, CompanyContext context) : base(context)
{
_financialInvoiceRepository = financialInvoiceRepository;
_context = context;
}
public OperationResult Create(CreateFinancialInvoice command)
{
var operation = new OperationResult();
if (command.Amount <= 0)
return operation.Failed("مبلغ فاکتور باید بزرگتر از صفر باشد");
if (command.ContractingPartyId <= 0)
return operation.Failed("طرف قرارداد نامعتبر است");
if (string.IsNullOrWhiteSpace(command.Description))
return operation.Failed("توضیحات فاکتور الزامی است");
var financialInvoice = new FinancialInvoice(command.Amount, command.ContractingPartyId, command.Description);
if (command.Items != null && command.Items.Any())
{
foreach (var item in command.Items)
{
if (string.IsNullOrWhiteSpace(item.Description))
return operation.Failed("توضیحات آیتم الزامی است");
if (item.Amount <= 0)
return operation.Failed("مبلغ آیتم باید بزرگتر از صفر باشد");
var invoiceItem = new FinancialInvoiceItem(item.Description, item.Amount,
financialInvoice.id, item.Type, item.EntityId);
financialInvoice.AddItem(invoiceItem);
}
}
_financialInvoiceRepository.Create(financialInvoice);
_financialInvoiceRepository.SaveChanges();
return operation.Succcedded();
}
public OperationResult Edit(EditFinancialInvoice command)
{
var operation = new OperationResult();
var financialInvoice = _financialInvoiceRepository.Get(command.Id);
if (financialInvoice == null)
return operation.Failed("فاکتور مورد نظر یافت نشد");
if (financialInvoice.Status == FinancialInvoiceStatus.Paid)
return operation.Failed("امکان ویرایش فاکتور پرداخت شده وجود ندارد");
if (string.IsNullOrWhiteSpace(command.Description))
return operation.Failed("توضیحات فاکتور الزامی است");
// Update description
financialInvoice.Description = command.Description;
// Update items if provided
if (command.Items != null)
{
// Clear existing items
if (financialInvoice.Items != null)
{
financialInvoice.Items.Clear();
}
else
{
financialInvoice.SetItems([]);
}
// Add updated items
foreach (var item in command.Items)
{
if (string.IsNullOrWhiteSpace(item.Description))
return operation.Failed("توضیحات آیتم الزامی است");
if (item.Amount <= 0)
return operation.Failed("مبلغ آیتم باید بزرگتر از صفر باشد");
var invoiceItem = new FinancialInvoiceItem(item.Description, item.Amount,
financialInvoice.id, item.Type, item.EntityId);
financialInvoice.AddItem(invoiceItem);
}
}
_financialInvoiceRepository.SaveChanges();
return operation.Succcedded();
}
public OperationResult SetPaid(long id, DateTime paidAt)
{
var operation = new OperationResult();
var financialInvoice = _financialInvoiceRepository.Get(id);
if (financialInvoice == null)
return operation.Failed("فاکتور مورد نظر یافت نشد");
if (financialInvoice.Status == FinancialInvoiceStatus.Paid)
return operation.Failed("فاکتور قبلاً پرداخت شده است");
if (financialInvoice.Status == FinancialInvoiceStatus.Cancelled)
return operation.Failed("امکان پرداخت فاکتور لغو شده وجود ندارد");
financialInvoice.SetPaid(paidAt);
_financialInvoiceRepository.SaveChanges();
return operation.Succcedded();
}
public OperationResult SetUnpaid(long id)
{
var operation = new OperationResult();
var financialInvoice = _financialInvoiceRepository.Get(id);
if (financialInvoice == null)
return operation.Failed("فاکتور مورد نظر یافت نشد");
financialInvoice.SetUnpaid();
_financialInvoiceRepository.SaveChanges();
return operation.Succcedded();
}
public OperationResult SetCancelled(long id)
{
var operation = new OperationResult();
var financialInvoice = _financialInvoiceRepository.Get(id);
if (financialInvoice == null)
return operation.Failed("فاکتور مورد نظر یافت نشد");
if (financialInvoice.Status == FinancialInvoiceStatus.Paid)
return operation.Failed("امکان لغو فاکتور پرداخت شده وجود ندارد");
financialInvoice.SetCancelled();
_financialInvoiceRepository.SaveChanges();
return operation.Succcedded();
}
public OperationResult SetRefunded(long id)
{
var operation = new OperationResult();
var financialInvoice = _financialInvoiceRepository.Get(id);
if (financialInvoice == null)
return operation.Failed("فاکتور مورد نظر یافت نشد");
if (financialInvoice.Status != FinancialInvoiceStatus.Paid)
return operation.Failed("فقط فاکتورهای پرداخت شده قابل بازپرداخت هستند");
financialInvoice.SetRefunded();
_financialInvoiceRepository.SaveChanges();
return operation.Succcedded();
}
public EditFinancialInvoice GetDetails(long id)
{
return _financialInvoiceRepository.GetDetails(id);
}
public List<FinancialInvoiceViewModel> Search(FinancialInvoiceSearchModel searchModel)
{
return _financialInvoiceRepository.Search(searchModel);
}
//public OperationResult Remove(long id)
//{
// var operation = new OperationResult();
// try
// {
// var financialInvoice = _financialInvoiceRepository.Get(id);
// if (financialInvoice == null)
// return operation.Failed("فاکتور مورد نظر یافت نشد");
// if (financialInvoice.Status == FinancialInvoiceStatus.Paid)
// return operation.Failed("امکان حذف فاکتور پرداخت شده وجود ندارد");
// // Remove the entity using the context directly since Remove method might not be available
// _context.FinancialInvoiceSet.Remove(financialInvoice);
// _financialInvoiceRepository.SaveChanges();
// return operation.Succcedded();
// }
// catch (Exception ex)
// {
// return operation.Failed("خطا در حذف فاکتور");
// }
//}
}

View File

@@ -2,10 +2,12 @@
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;
@@ -13,16 +15,20 @@ 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.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.Workshop;
using CompanyManagment.EFCore.Migrations;
@@ -50,6 +56,9 @@ public class InstitutionContractApplication : IInstitutionContractApplication
private readonly IAccountApplication _accountApplication;
private readonly ISmsService _smsService;
private readonly IUidService _uidService;
private readonly IFinancialInvoiceRepository _financialInvoiceRepository;
private readonly IPaymentGateway _paymentGateway;
private readonly IPaymentTransactionRepository _paymentTransactionRepository;
public InstitutionContractApplication(IInstitutionContractRepository institutionContractRepository,
@@ -59,7 +68,8 @@ public class InstitutionContractApplication : IInstitutionContractApplication
IFinancialStatmentApplication financialStatmentApplication, IWorkshopApplication workshopApplication,
IContractingPartyTempRepository contractingPartyTempRepository,
IFinancialStatmentRepository financialStatmentRepository, IContactInfoApplication contactInfoApplication,
IAccountApplication accountApplication, ISmsService smsService, IUidService uidService)
IAccountApplication accountApplication, ISmsService smsService, IUidService uidService,
IFinancialInvoiceRepository financialInvoiceRepository,IHttpClientFactory httpClientFactory, IPaymentTransactionRepository paymentTransactionRepository)
{
_institutionContractRepository = institutionContractRepository;
_contractingPartyRepository = contractingPartyRepository;
@@ -75,6 +85,9 @@ public class InstitutionContractApplication : IInstitutionContractApplication
_accountApplication = accountApplication;
_smsService = smsService;
_uidService = uidService;
_financialInvoiceRepository = financialInvoiceRepository;
_paymentTransactionRepository = paymentTransactionRepository;
_paymentGateway = new SepehrPaymentGateway(httpClientFactory);
}
public OperationResult Create(CreateInstitutionContract command)
@@ -1060,11 +1073,16 @@ public class InstitutionContractApplication : IInstitutionContractApplication
await _financialStatmentRepository.CreateAsync(financialStatement);
}
if (command.IsInstallment)
double invoiceAmount;
string invoiceItemDescription;
FinancialInvoiceItemType invoiceItemType;
long invoiceItemEntityId;
if (command.IsInstallment)
{
var installments =
CalculateInstallment(command.TotalAmount, (int)command.Duration, command.ContractStartFa, true);
// دریافت مبلغ اولین قسط
//این کار برای این هست که اولین قسط باید با تاریخ امروز باشد و باید به وضعیت مالی بدهی ایجاد شود که یوزر اولین بدهی را وارد کند
var firstInstallmentAmount = installments.First().Amount;
@@ -1075,25 +1093,41 @@ public class InstitutionContractApplication : IInstitutionContractApplication
// ایجاد قسط جدید با تاریخ امروز
var todayInstallment = new InstitutionContractInstallment(DateTime.Today, firstInstallmentAmount, "");
var financialTransaction = new FinancialTransaction(0, today, today.ToFarsi(),
"قسط اول سرویس", "debt", "بابت خدمات", firstInstallmentAmount, 0, 0);
financialStatement.AddFinancialTransaction(financialTransaction);
// اضافه کردن قسط جدید به ابتدای لیست
installments.Insert(0, todayInstallment);
entity.SetInstallments(installments);
await _institutionContractRepository.SaveChangesAsync();
var financialTransaction = new FinancialTransaction(0, today, today.ToFarsi(),
"قسط اول سرویس", "debt", "بابت خدمات", firstInstallmentAmount, 0, 0);
financialStatement.AddFinancialTransaction(financialTransaction);
invoiceAmount = firstInstallmentAmount;
invoiceItemDescription = $"پرداخت قسط اول قرارداد شماره {entity.ContractNo}";
invoiceItemType = FinancialInvoiceItemType.BuyInstitutionContractInstallment;
invoiceItemEntityId = todayInstallment.Id;
}
else
{
var financialTransaction = new FinancialTransaction(0, today, today.ToFarsi(),
"پرداخت کل سرویس", "debt", "بابت خدمات", command.TotalAmount, 0, 0);
financialStatement.AddFinancialTransaction(financialTransaction);
}
invoiceAmount = command.TotalAmount;
invoiceItemDescription = $"پرداخت کل قرارداد شماره {entity.ContractNo}";
invoiceItemType = FinancialInvoiceItemType.BuyInstitutionContract;
invoiceItemEntityId = entity.id;
}
var financialInvoice = new FinancialInvoice(invoiceAmount, contractingParty.id, $"خرید قرارداد مالی شماره {entity.ContractNo}");
var financialInvoiceItem = new FinancialInvoiceItem(invoiceItemDescription, invoiceAmount, 0,invoiceItemType, invoiceItemEntityId);
financialInvoice.AddItem(financialInvoiceItem);
await _institutionContractRepository.CreateAsync(entity);
await _financialInvoiceRepository.CreateAsync(financialInvoice);
await _institutionContractRepository.CreateAsync(entity);
await _institutionContractRepository.SaveChangesAsync();
var mainContactInfo = new CreateContactInfo
@@ -1232,9 +1266,9 @@ public class InstitutionContractApplication : IInstitutionContractApplication
return new OperationResult<OtpResultViewModel>().Succcedded(result);
}
public async Task<OperationResult> VerifyOtp(Guid publicId, string code)
public async Task<OperationResult<string>> VerifyOtpAndMakeGateway(Guid publicId, string code,string callbackUrl)
{
var op = new OperationResult();
var op = new OperationResult<string>();
var institutionContract = await _institutionContractRepository.GetByPublicIdAsync(publicId);
if (institutionContract == null)
{
@@ -1255,32 +1289,67 @@ public class InstitutionContractApplication : IInstitutionContractApplication
if (institutionContract.VerifyCode != code)
return op.Failed("کد وارد شده صحیح نمی باشد");
var transaction = await _institutionContractRepository.BeginTransactionAsync();
institutionContract.SetPendingWorkflow();
var dbTransaction = await _institutionContractRepository.BeginTransactionAsync();
var phone = institutionContract.ContactInfoList.FirstOrDefault(x =>
x.SendSms && x.Position == "طرف قرارداد" && x.PhoneType == "شماره همراه");
if (phone !=null)
long entityId = 0;
FinancialInvoiceItemType financialInvoiceItemType;
if (institutionContract.IsInstallment)
{
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);
entityId = institutionContract.Installments.MinBy(x => x.InstallmentDateGr).Id;
financialInvoiceItemType = FinancialInvoiceItemType.BuyInstitutionContractInstallment;
}
else
{
entityId = institutionContract.id;
financialInvoiceItemType = FinancialInvoiceItemType.BuyInstitutionContract;
}
await transaction.CommitAsync();
var financialInvoice =await _financialInvoiceRepository.GetUnPaidByEntityId(entityId, financialInvoiceItemType);
var amount = financialInvoice.Amount;
var transaction = new PaymentTransaction(institutionContract.ContractingPartyId, amount,
institutionContract.ContractingPartyName, "https://client.gozareshgir.ir",
PaymentTransactionGateWay.SepehrPay);
await _paymentTransactionRepository.CreateAsync(transaction);
await _financialInvoiceRepository.SaveChangesAsync();
var createPayment = new CreatePaymentGatewayRequest()
{
Amount = amount,
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);
// 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);
// }
await dbTransaction.CommitAsync();
await _institutionContractRepository.SaveChangesAsync();
return op.Succcedded();
return op.Succcedded(gatewayResponse.Token);
}
public async Task<InstitutionContractWorkshopDetailViewModel> GetWorkshopInitialDetails(long workshopDetailsId)
@@ -1387,6 +1456,24 @@ public class InstitutionContractApplication : IInstitutionContractApplication
return (await _institutionContractRepository.PrintAllAsync([id])).FirstOrDefault();
}
public async Task<OperationResult> SetPendingWorkflow(long entityId)
{
var op = new OperationResult();
var institutionContract = _institutionContractRepository.Get(entityId);
if (institutionContract == null)
{
return op.Failed("قرارداد مالی یافت نشد");
}
if (institutionContract.VerificationStatus != InstitutionContractVerificationStatus.PendingForVerify)
{
return op.Failed("وضعیت قرارداد مالی برای این عملیات مناسب نمی باشد");
}
institutionContract.SetPendingWorkflow();
await _institutionContractRepository.SaveChangesAsync();
return op.Succcedded();
}
private async Task<OperationResult<PersonalContractingParty>> CreateLegalContractingPartyEntity(
CreateInstitutionContractLegalPartyRequest request, long representativeId, string address, string city,

View File

@@ -45,6 +45,7 @@ using Company.Domain.FileEmployerAgg;
using Company.Domain.FileState;
using Company.Domain.FileTiming;
using Company.Domain.FileTitle;
using Company.Domain.FinancialInvoiceAgg;
using Company.Domain.FinancialStatmentAgg;
using Company.Domain.FinancialTransactionAgg;
using Company.Domain.FineAgg;
@@ -204,12 +205,13 @@ public class CompanyContext : DbContext
public DbSet<AuthorizedBankDetails> AuthorizedBankDetails { get; set; }
#endregion
public DbSet<FinancialInvoice> FinancialInvoices { get; set; }
#region Pooya
#endregion
public DbSet<EmployeeDocumentItem> EmployeeDocumentItems { get; set; }
#region Pooya
public DbSet<EmployeeDocumentItem> EmployeeDocumentItems { get; set; }
public DbSet<EmployeeDocuments> EmployeeDocuments { get; set; }
public DbSet<WorkshopSubAccount> WorkshopSubAccounts { get; set; }

View File

@@ -0,0 +1,17 @@
using Company.Domain.FinancialInvoiceAgg;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace CompanyManagment.EFCore.Mapping;
public class FinancialInvoiceItemMapping : IEntityTypeConfiguration<FinancialInvoiceItem>
{
public void Configure(EntityTypeBuilder<FinancialInvoiceItem> builder)
{
builder.Property(x=>x.Description).HasMaxLength(800);
builder.Property(x => x.Type).HasConversion<string>().HasMaxLength(50);
builder.HasOne(x => x.FinancialInvoice).WithMany(x => x.Items)
.HasForeignKey(x => x.FinancialInvoiceId);
}
}

View File

@@ -0,0 +1,25 @@
using Company.Domain.FinancialInvoiceAgg;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace CompanyManagment.EFCore.Mapping;
public class FinancialInvoiceMapping:IEntityTypeConfiguration<FinancialInvoice>
{
public void Configure(EntityTypeBuilder<FinancialInvoice> builder)
{
builder.HasKey(x => x.id);
builder.Property(x => x.Status).HasConversion<string>().HasMaxLength(20);
builder.Property(x => x.PaidAt).IsRequired(false);
builder.Property(x => x.Description).HasMaxLength(800);
builder.Property(x => x.InvoiceNumber).HasMaxLength(22);
builder.HasMany(x => x.Items).WithOne(x => x.FinancialInvoice)
.HasForeignKey(x => x.FinancialInvoiceId).IsRequired().OnDelete(DeleteBehavior.Cascade);
builder.HasMany(x => x.PaymentTransactions).WithOne(x => x.FinancialInvoice)
.HasForeignKey(x => x.FinancialInvoiceId).IsRequired(false).OnDelete(DeleteBehavior.NoAction);
}
}

View File

@@ -14,7 +14,7 @@ public class FinancialTransactionMapping : IEntityTypeConfiguration<FinancialTra
builder.Property(x => x.TdateFa);
builder.Property(x => x.TdateFa).HasMaxLength(10);
builder.Property(x => x.TypeOfTransaction).HasMaxLength(10);
builder.Property(x => x.DescriptionOption).HasMaxLength(50);
builder.Property(x => x.DescriptionOption).HasMaxLength(100);
builder.Property(x => x.Description).HasMaxLength(600);
builder.Property(x => x.Deptor);
builder.Property(x => x.Creditor);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace CompanyManagment.EFCore.Migrations
{
/// <inheritdoc />
public partial class AddfinancialInvoiceTable : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "FinancialInvoice",
columns: table => new
{
id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Month = table.Column<int>(type: "int", nullable: false),
Year = table.Column<int>(type: "int", nullable: false),
Status = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: false),
PaidAt = table.Column<DateTime>(type: "datetime2", nullable: true),
Amount = table.Column<double>(type: "float", nullable: false),
SmsCode = table.Column<string>(type: "nvarchar(122)", maxLength: 122, nullable: true),
FinancialStatementId = table.Column<long>(type: "bigint", nullable: true),
CreationDate = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_FinancialInvoice", x => x.id);
table.ForeignKey(
name: "FK_FinancialInvoice_FinancialStatments_FinancialStatementId",
column: x => x.FinancialStatementId,
principalTable: "FinancialStatments",
principalColumn: "id");
});
migrationBuilder.CreateIndex(
name: "IX_FinancialInvoice_FinancialStatementId",
table: "FinancialInvoice",
column: "FinancialStatementId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "FinancialInvoice");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,226 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace CompanyManagment.EFCore.Migrations
{
/// <inheritdoc />
public partial class addfinancialinvoice : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_FinancialInvoice_FinancialStatments_FinancialStatementId",
table: "FinancialInvoice");
migrationBuilder.DropPrimaryKey(
name: "PK_FinancialInvoice",
table: "FinancialInvoice");
migrationBuilder.DropColumn(
name: "Month",
table: "FinancialInvoice");
migrationBuilder.DropColumn(
name: "SmsCode",
table: "FinancialInvoice");
migrationBuilder.DropColumn(
name: "Year",
table: "FinancialInvoice");
migrationBuilder.RenameTable(
name: "FinancialInvoice",
newName: "FinancialInvoices");
migrationBuilder.RenameColumn(
name: "FinancialStatementId",
table: "FinancialInvoices",
newName: "FinancialStatmentid");
migrationBuilder.RenameIndex(
name: "IX_FinancialInvoice_FinancialStatementId",
table: "FinancialInvoices",
newName: "IX_FinancialInvoices_FinancialStatmentid");
migrationBuilder.AddColumn<long>(
name: "FinancialInvoiceId",
table: "PaymentTransactions",
type: "bigint",
nullable: true);
migrationBuilder.AddColumn<long>(
name: "ContractingPartyId",
table: "FinancialInvoices",
type: "bigint",
nullable: false,
defaultValue: 0L);
migrationBuilder.AddColumn<string>(
name: "Description",
table: "FinancialInvoices",
type: "nvarchar(800)",
maxLength: 800,
nullable: true);
migrationBuilder.AddColumn<bool>(
name: "IsActive",
table: "FinancialInvoices",
type: "bit",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<Guid>(
name: "PublicId",
table: "FinancialInvoices",
type: "uniqueidentifier",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
migrationBuilder.AddPrimaryKey(
name: "PK_FinancialInvoices",
table: "FinancialInvoices",
column: "id");
migrationBuilder.CreateTable(
name: "FinancialInvoiceItem",
columns: table => new
{
id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Description = table.Column<string>(type: "nvarchar(800)", maxLength: 800, nullable: true),
Amount = table.Column<double>(type: "float", nullable: false),
Type = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: false),
EntityId = table.Column<long>(type: "bigint", nullable: false),
FinancialInvoiceId = table.Column<long>(type: "bigint", nullable: false),
CreationDate = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_FinancialInvoiceItem", x => x.id);
table.ForeignKey(
name: "FK_FinancialInvoiceItem_FinancialInvoices_FinancialInvoiceId",
column: x => x.FinancialInvoiceId,
principalTable: "FinancialInvoices",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_PaymentTransactions_FinancialInvoiceId",
table: "PaymentTransactions",
column: "FinancialInvoiceId");
migrationBuilder.CreateIndex(
name: "IX_FinancialInvoiceItem_FinancialInvoiceId",
table: "FinancialInvoiceItem",
column: "FinancialInvoiceId");
migrationBuilder.AddForeignKey(
name: "FK_FinancialInvoices_FinancialStatments_FinancialStatmentid",
table: "FinancialInvoices",
column: "FinancialStatmentid",
principalTable: "FinancialStatments",
principalColumn: "id");
migrationBuilder.AddForeignKey(
name: "FK_PaymentTransactions_FinancialInvoices_FinancialInvoiceId",
table: "PaymentTransactions",
column: "FinancialInvoiceId",
principalTable: "FinancialInvoices",
principalColumn: "id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_FinancialInvoices_FinancialStatments_FinancialStatmentid",
table: "FinancialInvoices");
migrationBuilder.DropForeignKey(
name: "FK_PaymentTransactions_FinancialInvoices_FinancialInvoiceId",
table: "PaymentTransactions");
migrationBuilder.DropTable(
name: "FinancialInvoiceItem");
migrationBuilder.DropIndex(
name: "IX_PaymentTransactions_FinancialInvoiceId",
table: "PaymentTransactions");
migrationBuilder.DropPrimaryKey(
name: "PK_FinancialInvoices",
table: "FinancialInvoices");
migrationBuilder.DropColumn(
name: "FinancialInvoiceId",
table: "PaymentTransactions");
migrationBuilder.DropColumn(
name: "ContractingPartyId",
table: "FinancialInvoices");
migrationBuilder.DropColumn(
name: "Description",
table: "FinancialInvoices");
migrationBuilder.DropColumn(
name: "IsActive",
table: "FinancialInvoices");
migrationBuilder.DropColumn(
name: "PublicId",
table: "FinancialInvoices");
migrationBuilder.RenameTable(
name: "FinancialInvoices",
newName: "FinancialInvoice");
migrationBuilder.RenameColumn(
name: "FinancialStatmentid",
table: "FinancialInvoice",
newName: "FinancialStatementId");
migrationBuilder.RenameIndex(
name: "IX_FinancialInvoices_FinancialStatmentid",
table: "FinancialInvoice",
newName: "IX_FinancialInvoice_FinancialStatementId");
migrationBuilder.AddColumn<int>(
name: "Month",
table: "FinancialInvoice",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<string>(
name: "SmsCode",
table: "FinancialInvoice",
type: "nvarchar(122)",
maxLength: 122,
nullable: true);
migrationBuilder.AddColumn<int>(
name: "Year",
table: "FinancialInvoice",
type: "int",
nullable: false,
defaultValue: 0);
migrationBuilder.AddPrimaryKey(
name: "PK_FinancialInvoice",
table: "FinancialInvoice",
column: "id");
migrationBuilder.AddForeignKey(
name: "FK_FinancialInvoice_FinancialStatments_FinancialStatementId",
table: "FinancialInvoice",
column: "FinancialStatementId",
principalTable: "FinancialStatments",
principalColumn: "id");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,59 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace CompanyManagment.EFCore.Migrations
{
/// <inheritdoc />
public partial class addinvoicenumber : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_FinancialInvoices_FinancialStatments_FinancialStatmentid",
table: "FinancialInvoices");
migrationBuilder.DropIndex(
name: "IX_FinancialInvoices_FinancialStatmentid",
table: "FinancialInvoices");
migrationBuilder.DropColumn(
name: "FinancialStatmentid",
table: "FinancialInvoices");
migrationBuilder.AddColumn<string>(
name: "InvoiceNumber",
table: "FinancialInvoices",
type: "nvarchar(18)",
maxLength: 18,
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "InvoiceNumber",
table: "FinancialInvoices");
migrationBuilder.AddColumn<long>(
name: "FinancialStatmentid",
table: "FinancialInvoices",
type: "bigint",
nullable: true);
migrationBuilder.CreateIndex(
name: "IX_FinancialInvoices_FinancialStatmentid",
table: "FinancialInvoices",
column: "FinancialStatmentid");
migrationBuilder.AddForeignKey(
name: "FK_FinancialInvoices_FinancialStatments_FinancialStatmentid",
table: "FinancialInvoices",
column: "FinancialStatmentid",
principalTable: "FinancialStatments",
principalColumn: "id");
}
}
}

View File

@@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace CompanyManagment.EFCore.Migrations
{
/// <inheritdoc />
public partial class changemaxlengthforfinancialinvoicenumber : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "InvoiceNumber",
table: "FinancialInvoices",
type: "nvarchar(22)",
maxLength: 22,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(18)",
oldMaxLength: 18,
oldNullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "InvoiceNumber",
table: "FinancialInvoices",
type: "nvarchar(18)",
maxLength: 18,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(22)",
oldMaxLength: 22,
oldNullable: true);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace CompanyManagment.EFCore.Migrations
{
/// <inheritdoc />
public partial class changedescriptionOptionmaxlength : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "DescriptionOption",
table: "FinancialTransactions",
type: "nvarchar(100)",
maxLength: 100,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(50)",
oldMaxLength: 50,
oldNullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "DescriptionOption",
table: "FinancialTransactions",
type: "nvarchar(50)",
maxLength: 50,
nullable: true,
oldClrType: typeof(string),
oldType: "nvarchar(100)",
oldMaxLength: 100,
oldNullable: true);
}
}
}

View File

@@ -2835,6 +2835,86 @@ namespace CompanyManagment.EFCore.Migrations
b.ToTable("File_Titles", (string)null);
});
modelBuilder.Entity("Company.Domain.FinancialInvoiceAgg.FinancialInvoice", b =>
{
b.Property<long>("id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("id"));
b.Property<double>("Amount")
.HasColumnType("float");
b.Property<long>("ContractingPartyId")
.HasColumnType("bigint");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(800)
.HasColumnType("nvarchar(800)");
b.Property<string>("InvoiceNumber")
.HasMaxLength(22)
.HasColumnType("nvarchar(22)");
b.Property<bool>("IsActive")
.HasColumnType("bit");
b.Property<DateTime?>("PaidAt")
.HasColumnType("datetime2");
b.Property<Guid>("PublicId")
.HasColumnType("uniqueidentifier");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");
b.HasKey("id");
b.ToTable("FinancialInvoices");
});
modelBuilder.Entity("Company.Domain.FinancialInvoiceAgg.FinancialInvoiceItem", b =>
{
b.Property<long>("id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("id"));
b.Property<double>("Amount")
.HasColumnType("float");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasMaxLength(800)
.HasColumnType("nvarchar(800)");
b.Property<long>("EntityId")
.HasColumnType("bigint");
b.Property<long>("FinancialInvoiceId")
.HasColumnType("bigint");
b.Property<string>("Type")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("id");
b.HasIndex("FinancialInvoiceId");
b.ToTable("FinancialInvoiceItem");
});
modelBuilder.Entity("Company.Domain.FinancialStatmentAgg.FinancialStatment", b =>
{
b.Property<long>("id")
@@ -2886,8 +2966,8 @@ namespace CompanyManagment.EFCore.Migrations
.HasColumnType("nvarchar(600)");
b.Property<string>("DescriptionOption")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<long>("FinancialStatementId")
.HasColumnType("bigint");
@@ -5002,6 +5082,9 @@ namespace CompanyManagment.EFCore.Migrations
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<long?>("FinancialInvoiceId")
.HasColumnType("bigint");
b.Property<string>("Gateway")
.IsRequired()
.HasMaxLength(35)
@@ -5025,6 +5108,8 @@ namespace CompanyManagment.EFCore.Migrations
b.HasKey("id");
b.HasIndex("FinancialInvoiceId");
b.ToTable("PaymentTransactions", (string)null);
});
@@ -9958,6 +10043,17 @@ namespace CompanyManagment.EFCore.Migrations
b.Navigation("FileTiming");
});
modelBuilder.Entity("Company.Domain.FinancialInvoiceAgg.FinancialInvoiceItem", b =>
{
b.HasOne("Company.Domain.FinancialInvoiceAgg.FinancialInvoice", "FinancialInvoice")
.WithMany("Items")
.HasForeignKey("FinancialInvoiceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("FinancialInvoice");
});
modelBuilder.Entity("Company.Domain.FinancialTransactionAgg.FinancialTransaction", b =>
{
b.HasOne("Company.Domain.FinancialStatmentAgg.FinancialStatment", "FinancialStatment")
@@ -10505,6 +10601,16 @@ namespace CompanyManagment.EFCore.Migrations
b.Navigation("PaymentToEmployee");
});
modelBuilder.Entity("Company.Domain.PaymentTransactionAgg.PaymentTransaction", b =>
{
b.HasOne("Company.Domain.FinancialInvoiceAgg.FinancialInvoice", "FinancialInvoice")
.WithMany("PaymentTransactions")
.HasForeignKey("FinancialInvoiceId")
.OnDelete(DeleteBehavior.NoAction);
b.Navigation("FinancialInvoice");
});
modelBuilder.Entity("Company.Domain.PenaltyTitle.PenaltyTitle", b =>
{
b.HasOne("Company.Domain.Petition.Petition", "Petition")
@@ -10909,6 +11015,13 @@ namespace CompanyManagment.EFCore.Migrations
b.Navigation("FileStates");
});
modelBuilder.Entity("Company.Domain.FinancialInvoiceAgg.FinancialInvoice", b =>
{
b.Navigation("Items");
b.Navigation("PaymentTransactions");
});
modelBuilder.Entity("Company.Domain.FinancialStatmentAgg.FinancialStatment", b =>
{
b.Navigation("FinancialTransactionList");

View File

@@ -0,0 +1,103 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using _0_Framework.Application;
using _0_Framework.InfraStructure;
using Company.Domain.FinancialInvoiceAgg;
using CompanyManagment.App.Contracts.FinancialInvoice;
using Microsoft.EntityFrameworkCore;
namespace CompanyManagment.EFCore.Repository;
public class FinancialInvoiceRepository : RepositoryBase<long, FinancialInvoice>, IFinancialInvoiceRepository
{
private readonly CompanyContext _context;
public FinancialInvoiceRepository(CompanyContext context) : base(context)
{
_context = context;
}
public EditFinancialInvoice GetDetails(long id)
{
var financialInvoice = _context.FinancialInvoices
.Include(x => x.Items)
.FirstOrDefault(x => x.id == id);
if (financialInvoice == null)
return null;
return new EditFinancialInvoice
{
Id = financialInvoice.id,
Description = financialInvoice.Description,
Amount = financialInvoice.Amount,
Status = financialInvoice.Status,
InvoiceNumber = financialInvoice.InvoiceNumber,
Items = financialInvoice.Items?.Select(x => new EditFinancialInvoiceItem
{
Id = x.id,
Description = x.Description,
Amount = x.Amount,
Type = x.Type,
EntityId = x.EntityId
}).ToList()
};
}
public List<FinancialInvoiceViewModel> Search(FinancialInvoiceSearchModel searchModel)
{
var query = _context.FinancialInvoices
.Include(x => x.Items)
.AsQueryable();
if (!string.IsNullOrWhiteSpace(searchModel.Description))
query = query.Where(x => x.Description.Contains(searchModel.Description));
if (searchModel.Status.HasValue)
query = query.Where(x => x.Status == searchModel.Status.Value);
if (searchModel.ContractingPartyId.HasValue)
query = query.Where(x => x.ContractingPartyId == searchModel.ContractingPartyId.Value);
if (!string.IsNullOrWhiteSpace(searchModel.FromDate))
{
var fromDate = searchModel.FromDate.ToGeorgianDateTime();
query = query.Where(x => x.CreationDate >= fromDate);
}
if (!string.IsNullOrWhiteSpace(searchModel.ToDate))
{
var toDate = searchModel.ToDate.ToGeorgianDateTime();
query = query.Where(x => x.CreationDate <= toDate);
}
if (searchModel.MinAmount.HasValue)
query = query.Where(x => x.Amount >= searchModel.MinAmount.Value);
if (searchModel.MaxAmount.HasValue)
query = query.Where(x => x.Amount <= searchModel.MaxAmount.Value);
return query.OrderByDescending(x => x.id)
.Select(x => new FinancialInvoiceViewModel
{
Id = x.id,
Description = x.Description,
Status = x.Status.ToString(),
PaidAt = x.PaidAt.HasValue ? x.PaidAt.Value.ToFarsi() : "",
Amount = x.Amount,
PublicId = x.PublicId,
ContractingPartyId = x.ContractingPartyId,
CreationDate = x.CreationDate.ToFarsi(),
ItemsCount = x.Items != null ? x.Items.Count : 0
}).ToList();
}
public async Task<FinancialInvoice> GetUnPaidByEntityId(long entityId,
FinancialInvoiceItemType financialInvoiceItemType)
{
return await _context.FinancialInvoices.Include(x => x.Items)
.Where(x => x.Status == FinancialInvoiceStatus.Unpaid).FirstOrDefaultAsync(x => x.Items
.Any(y => y.Type == financialInvoiceItemType && y.EntityId == entityId));
}
}

View File

@@ -265,7 +265,21 @@ public class FinancialStatmentRepository : RepositoryBase<long, FinancialStatmen
}
public async Task<FinancialStatmentDetailsByContractingPartyViewModel> GetDetailsByContractingParty(long contractingPartyId,FinancialStatementSearchModel searchModel)
public async Task<double> GetClientDebtAmountByContractingPartyId(long contractingPartyId)
{
var resStatement = await _context.FinancialStatments.Include(x => x.FinancialTransactionList)
.FirstOrDefaultAsync(x => x.ContractingPartyId == contractingPartyId);
if (resStatement == null)
return 0;
return resStatement.FinancialTransactionList.Sum(x => x.Deptor) -
resStatement.FinancialTransactionList.Sum(x => x.Creditor);
}
public async Task<FinancialStatmentDetailsByContractingPartyViewModel> GetDetailsByContractingParty(long contractingPartyId,FinancialStatementSearchModel searchModel)
{
var contractingParty = await _context.PersonalContractingParties
.FirstOrDefaultAsync(x=>x.id == contractingPartyId);
@@ -413,6 +427,6 @@ public class FinancialStatmentRepository : RepositoryBase<long, FinancialStatmen
public async Task<FinancialStatment> GetByContractingPartyId(long contractingPartyId)
{
return await _context.FinancialStatments.FirstOrDefaultAsync(x => x.ContractingPartyId == contractingPartyId);
return await _context.FinancialStatments.Include(x=>x.FinancialTransactionList).FirstOrDefaultAsync(x => x.ContractingPartyId == contractingPartyId);
}
}

View File

@@ -14,6 +14,7 @@ using _0_Framework.InfraStructure;
using Company.Domain.ContarctingPartyAgg;
using Company.Domain.ContractingPartyAccountAgg;
using Company.Domain.empolyerAgg;
using Company.Domain.FinancialInvoiceAgg;
using Company.Domain.FinancialStatmentAgg;
using Company.Domain.FinancialTransactionAgg;
using Company.Domain.InstitutionContractAgg;
@@ -23,6 +24,7 @@ using Company.Domain.InstitutionContractExtensionTempAgg;
using Company.Domain.InstitutionPlanAgg;
using Company.Domain.WorkshopAgg;
using CompanyManagment.App.Contracts.Employer;
using CompanyManagment.App.Contracts.FinancialInvoice;
using CompanyManagment.App.Contracts.InstitutionContract;
using CompanyManagment.App.Contracts.InstitutionContractContactinfo;
using CompanyManagment.App.Contracts.Law;
@@ -1839,7 +1841,10 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
public async Task<InstitutionContract> GetByPublicIdAsync(Guid id)
{
return await _context.InstitutionContractSet.Include(x=>x.ContactInfoList).FirstOrDefaultAsync(x => x.PublicId == id);
return await _context.InstitutionContractSet
.Include(x=>x.ContactInfoList)
.Include(x=>x.Installments)
.FirstOrDefaultAsync(x => x.PublicId == id);
}
#region Extension
@@ -2295,6 +2300,10 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
}
var today = DateTime.Today;
double invoiceAmount;
string invoiceItemDescription;
FinancialInvoiceItemType invoiceItemType;
long invoiceItemEntityId;
if (request.IsInstallment && payment is InstitutionContractPaymentMonthlyViewModel monthly)
{
var installments = monthly.Installments.Select(x =>
@@ -2311,23 +2320,40 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
// ایجاد قسط جدید با تاریخ امروز
var todayInstallment = new InstitutionContractInstallment(DateTime.Today, firstInstallmentAmount, "");
var financialTransaction = new FinancialTransaction(0, today, today.ToFarsi(),
"قسط اول سرویس", "debt", "بابت خدمات", firstInstallmentAmount, 0, 0);
financialStatement.AddFinancialTransaction(financialTransaction);
// اضافه کردن قسط جدید به ابتدای لیست
installments.Insert(0, todayInstallment);
entity.SetInstallments(installments);
await SaveChangesAsync();
var financialTransaction = new FinancialTransaction(0, today, today.ToFarsi(),
"قسط اول سرویس", "debt", "بابت خدمات", firstInstallmentAmount, 0, 0);
financialStatement.AddFinancialTransaction(financialTransaction);
invoiceAmount = firstInstallmentAmount;
invoiceItemDescription = $"پرداخت قسط اول قرارداد شماره {entity.ContractNo}";
invoiceItemType = FinancialInvoiceItemType.BuyInstitutionContractInstallment;
invoiceItemEntityId = todayInstallment.Id;
}
else
{
var financialTransaction = new FinancialTransaction(0, today, today.ToFarsi(),
"پرداخت کل سرویس", "debt", "بابت خدمات", totalAmount, 0, 0);
financialStatement.AddFinancialTransaction(financialTransaction);
invoiceAmount = totalAmount;
invoiceItemDescription = $"پرداخت کل قرارداد شماره {entity.ContractNo}";
invoiceItemType = FinancialInvoiceItemType.BuyInstitutionContract;
invoiceItemEntityId = entity.id;
}
var financialInvoice = new FinancialInvoice(invoiceAmount, contractingParty.id, $"خرید قرارداد مالی شماره {entity.ContractNo}");
var financialInvoiceItem = new FinancialInvoiceItem(invoiceItemDescription, invoiceAmount, 0,invoiceItemType, invoiceItemEntityId);
financialInvoice.AddItem(financialInvoiceItem);
await _context.AddAsync(financialInvoice);
await SaveChangesAsync();
foreach (var contactInfo in institutionContractTemp.ContactInfos)
{
if (contactInfo.PhoneNumber != null)

View File

@@ -214,6 +214,7 @@ 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;
@@ -228,6 +229,7 @@ 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;
@@ -484,11 +486,14 @@ public class PersonalBootstrapper
services.AddTransient<IAuthorizedBankDetailsApplication, AuthorizedBankDetailsApplication>();
services
.AddTransient<IInstitutionContractExtenstionTempRepository, InstitutionContractExtenstionTempRepository>();
.AddTransient<IInstitutionContractExtenstionTempRepository, InstitutionContractExtenstionTempRepository>();
services.AddTransient<IEmployeeFaceEmbeddingRepository, EmployeeFaceEmbeddingRepository>();
services.AddTransient<IEmployeeFaceEmbeddingApplication, EmployeeFaceEmbeddingApplication>();
services.AddTransient<IFinancialInvoiceRepository, FinancialInvoiceRepository>();
services.AddTransient<IFinancialInvoiceApplication, FinancialInvoiceApplication>();
#endregion
#region Pooya

View File

@@ -2,6 +2,7 @@ using System.Collections.Concurrent;
using System.Transactions;
using _0_Framework.Application;
using _0_Framework.Application.Enums;
using _0_Framework.Application.PaymentGateway;
using _0_Framework.Application.Sms;
using _0_Framework.Exceptions;
using AccountManagement.Application.Contracts.Account;
@@ -37,6 +38,8 @@ public class institutionContractController : AdminBaseController
private readonly IWorkshopApplication _workshopApplication;
private readonly ITemporaryClientRegistrationApplication _temporaryClientRegistration;
private readonly ITemporaryClientRegistrationApplication _clientRegistrationApplication;
private readonly IPaymentGateway _paymentGateway;
private static readonly ConcurrentDictionary<Guid, SemaphoreSlim> _locks
= new ConcurrentDictionary<Guid, SemaphoreSlim>();
@@ -45,7 +48,8 @@ public class institutionContractController : AdminBaseController
public institutionContractController(IInstitutionContractApplication institutionContractApplication,
IPersonalContractingPartyApp contractingPartyApplication, IContactInfoApplication contactInfoApplication,
IAccountApplication accountApplication, IEmployerApplication employerApplication,
IWorkshopApplication workshopApplication, ITemporaryClientRegistrationApplication temporaryClientRegistration, ITemporaryClientRegistrationApplication clientRegistrationApplication)
IWorkshopApplication workshopApplication, ITemporaryClientRegistrationApplication temporaryClientRegistration,
ITemporaryClientRegistrationApplication clientRegistrationApplication,IHttpClientFactory httpClientFactory)
{
_institutionContractApplication = institutionContractApplication;
_contractingPartyApplication = contractingPartyApplication;
@@ -55,6 +59,7 @@ public class institutionContractController : AdminBaseController
_workshopApplication = workshopApplication;
_temporaryClientRegistration = temporaryClientRegistration;
_clientRegistrationApplication = clientRegistrationApplication;
_paymentGateway = new SepehrPaymentGateway(httpClientFactory);
}
/// <summary>
@@ -462,11 +467,37 @@ public class institutionContractController : AdminBaseController
[HttpPost("/api/institutionContract/Verify")]
[AllowAnonymous]
public async Task<ActionResult<OperationResult>> Verify([FromBody] InstitutionVerificationRequest command)
public async Task<ActionResult<OperationResult<string>>> Verify([FromBody] InstitutionVerificationRequest command)
{
var res = await _institutionContractApplication.VerifyOtp(command.Id, command.Code);
return res;
// URL برای redirect به درگاه پرداخت
var paymentRedirectUrl = Url.Action("ProcessPayment", "institutionContract", new { area = "Admin" }, Request.Scheme);
var res = await _institutionContractApplication.VerifyOtpAndMakeGateway(command.Id, command.Code, paymentRedirectUrl);
if (!res.IsSuccedded)
return new OperationResult<string>().Failed(res.Message);
var payUrl = _paymentGateway.GetStartPayUrl(res.Data);
// URL کامل برای redirect شامل paymentUrl به عنوان query parameter
var redirectUrl = $"{paymentRedirectUrl}?paymentUrl={Uri.EscapeDataString(payUrl)}";
return new OperationResult<string>().Succcedded(redirectUrl);
}
[HttpGet("/api/institutionContract/ProcessPayment")]
[AllowAnonymous]
public IActionResult ProcessPayment([FromQuery] string paymentUrl)
{
if (string.IsNullOrEmpty(paymentUrl))
{
return BadRequest("Payment URL is required");
}
// redirect به درگاه پرداخت
return Redirect(paymentUrl);
}
[HttpPost("/api/institutionContract/Verification/{id:guid}/send-otp")]
[AllowAnonymous]

View File

@@ -107,9 +107,9 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk
_context.PaymentTransactions.Add(transaction);
await _context.SaveChangesAsync();
var command = new CreatePaymentGatewayRequest()
var command = new CreatePaymentGatewayRequest()
{
InvoiceId = transaction.id.ToString(),
TransactionId = transaction.id.ToString(),
Amount = amount,
CallBackUrl = callBack
};
@@ -118,7 +118,10 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk
if (createRes.IsSuccess)
{
var payUrl = _paymentGateway.GetStartPayUrl(createRes.Token);
transaction.SetTransactionId(createRes.Token);
await _context.SaveChangesAsync();
var payUrl = _paymentGateway.GetStartPayUrl(createRes.Token);
return Redirect(payUrl);
}
else
@@ -251,7 +254,7 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk
Amount = 1000,
Email = "mahanch83@gmail.com",
CallBackUrl = Url.Page("/CallBack/Index", null, null, Request.Scheme, Request.Host.Value),
InvoiceId = "{C771E841-B810-413D-9D4C-9F659575B8CC}",
TransactionId = "{C771E841-B810-413D-9D4C-9F659575B8CC}",
};
var createResponse = await _paymentGateway.Create(command, cancellationToken);

View File

@@ -86,7 +86,7 @@ public class FinancialController : ClientBaseController
{
CallBackUrl = callbackUrl,
Amount = balanceAmount.Amount/10,
InvoiceId = transaction.SendId.ToString(),
TransactionId = transaction.SendId.ToString(),
};
var gatewayResponse = await _paymentGateway.Create(command, cancellationToken);

View File

@@ -19,23 +19,29 @@ using System.Globalization;
using System.Net.Http;
using System.Security.Cryptography;
using System.Threading;
using CompanyManagment.App.Contracts.FinancialInvoice;
using CompanyManagment.App.Contracts.InstitutionContract;
namespace ServiceHost.Controllers;
public class GeneralController : GeneralBaseController
{
private readonly IPaymentTransactionApplication _paymentTransactionApplication;
private readonly IPaymentGateway _paymentGateway;
private readonly IFinancialStatmentApplication _financialStatmentApplication;
private readonly IOnlinePayment _onlinePayment;
private readonly IFinancialInvoiceApplication _financialInvoiceApplication;
private readonly IInstitutionContractApplication _institutionContractApplication;
public GeneralController(IPaymentTransactionApplication paymentTransactionApplication,IHttpClientFactory clientFactory, IFinancialStatmentApplication financialStatmentApplication, IOptions<AppSettingConfiguration> appSetting, IOnlinePayment onlinePayment)
public GeneralController(IPaymentTransactionApplication paymentTransactionApplication,
IHttpClientFactory clientFactory, IFinancialStatmentApplication financialStatmentApplication,
IFinancialInvoiceApplication financialInvoiceApplication,
IInstitutionContractApplication institutionContractApplication)
{
_paymentTransactionApplication = paymentTransactionApplication;
_paymentGateway = new SepehrPaymentGateway(clientFactory);
_financialStatmentApplication = financialStatmentApplication;
_onlinePayment = onlinePayment;
_financialInvoiceApplication = financialInvoiceApplication;
_institutionContractApplication = institutionContractApplication;
}
/// <summary>
@@ -63,101 +69,135 @@ public class GeneralController : GeneralBaseController
[HttpGet("/api/callback"), HttpPost("/api/callback")]
public async Task<IActionResult> Verify(SepehrGatewayPayResponse payResponse)
{
if (!long.TryParse(payResponse.invoiceid, out var paymentTransactionId))
{
return BadRequest("Invalid invoice_id");
}
if (!long.TryParse(payResponse.invoiceid, out var paymentTransactionId))
{
return BadRequest("Invalid invoice_id");
}
var transaction = await _paymentTransactionApplication.GetDetails(paymentTransactionId);
var transaction = await _paymentTransactionApplication.GetDetails(paymentTransactionId);
if (transaction == null)
{
return NotFound("Transaction not found");
}
if (transaction == null)
{
return NotFound("Transaction not found");
}
if (transaction.Status != PaymentTransactionStatus.Pending)
{
return BadRequest("این تراکنش قبلا پرداخت شده است");
}
if (payResponse.respcode != 0)
{
return await HandleFailedTransaction(transaction);
}
var verifyCommand = new VerifyPaymentGateWayRequest()
{
Amount = transaction.Amount,
TransactionId = payResponse.invoiceid,
DigitalReceipt = payResponse.digitalreceipt
};
var verifyRes = await _paymentGateway.Verify(verifyCommand, CancellationToken.None);
if (transaction.Status != PaymentTransactionStatus.Pending)
{
return BadRequest("این تراکنش قبلا پرداخت شده است");
}
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 new JsonResult(statementResult);
}
if (payResponse.respcode != 0)
{
return await HandleFailedTransaction(transaction);
}
var setSuccessResult = _paymentTransactionApplication.SetSuccess(paymentTransactionId, payResponse.cardnumber, payResponse.issuerbank, payResponse.rrn.ToString(), payResponse.digitalreceipt);
if (!setSuccessResult.IsSuccedded)
{
return await HandleFailedTransaction(transaction);
}
return Redirect(BuildCallbackUrl(transaction.CallBackUrl, true, transaction.Id));
}
// در غیر این صورت تراکنش ناموفق است
return await HandleFailedTransaction(transaction);
var extraData = JsonConvert.DeserializeObject<IDictionary<string, object>>(payResponse.payload);
extraData.TryGetValue("financialInvoiceId", out var financialInvoiceIdObj);
if (financialInvoiceIdObj == null ||
!long.TryParse(financialInvoiceIdObj.ToString(), out var financialInvoiceId))
{
return BadRequest("فاکتور مالی نامعتبر است");
}
//var data = JsonConvert.SerializeObject(invoice.AdditionalData);
//var statics =
//JsonConvert.SerializeObject(res);
var financialInvoice = _financialInvoiceApplication.GetDetails(financialInvoiceId);
//await _onlinePayment.CancelAsync(invoice);
//return new JsonResult(new
//{
// data,
// statics
//});
if (financialInvoice == null)
{
return BadRequest("فاکتور مالی نامعتبر است");
}
//// 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;
if (financialInvoice.Status != FinancialInvoiceStatus.Unpaid)
{
return BadRequest("فاکتور مالی نامعتبر است");
}
// return Content("The payment was not successful.");
//}
if (financialInvoice.Amount != transaction.Amount)
{
return await HandleFailedTransaction(transaction);
}
//// Note: Save the verifyResult.TransactionCode in your database.
var verifyCommand = new VerifyPaymentGateWayRequest()
{
Amount = transaction.Amount,
TransactionId = payResponse.invoiceid,
DigitalReceipt = payResponse.digitalreceipt
};
var verifyRes = await _paymentGateway.Verify(verifyCommand, CancellationToken.None);
_financialInvoiceApplication.SetPaid(financialInvoiceId, DateTime.Now);
if (verifyRes.IsSuccess)
{
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 == FinancialInvoiceItemType.BuyInstitutionContract) ?? false)
{
var financialItems = financialInvoice.Items
.Where(x => x.Type == FinancialInvoiceItemType.BuyInstitutionContract);
foreach (var editFinancialInvoiceItem in financialItems)
{
await _institutionContractApplication.SetPendingWorkflow(editFinancialInvoiceItem.EntityId);
}
}
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
//});
[HttpPost("/api/callback3232")]
public async Task<IActionResult> OnGetCallBack(string? transid, string? cardnumber, string? tracking_number,
string bank, string invoice_id, string? status,CancellationToken cancellationToken)
//// Check if the invoice is new, or it's already processed before.
//if (invoice.Status != PaymentFetchResultStatus.ReadyForVerifying)
//{
// // You can also see if the invoice is already verified before.
// var isAlreadyVerified = invoice.IsAlreadyVerified;
// return Content("The payment was not successful.");
//}
//// Note: Save the verifyResult.TransactionCode in your database.
}
[HttpPost("/api/callback3232")]
public async Task<IActionResult> OnGetCallBack(string? transid, string? cardnumber, string? tracking_number,
string bank, string invoice_id, string? status, CancellationToken cancellationToken)
{
if (!long.TryParse(invoice_id, out var paymentTransactionId))
{
@@ -183,10 +223,10 @@ public class GeneralController : GeneralBaseController
var verifyCommand = new VerifyPaymentGateWayRequest()
{
Amount = transaction.Amount/10,
Amount = transaction.Amount / 10,
TransactionId = transid
};
var verifyRes =await _paymentGateway.Verify(verifyCommand, cancellationToken);
var verifyRes = await _paymentGateway.Verify(verifyCommand, cancellationToken);
// اگر استاتوس 1 باشد، تراکنش موفق است
if (verifyRes.IsSuccess)
@@ -200,7 +240,6 @@ public class GeneralController : GeneralBaseController
TypeOfTransaction = "credit",
DescriptionOption = "بابت قرارداد مابین (روابط کار)",
Description = "درگاه بانکی",
};
var statementResult = _financialStatmentApplication.CreateFromBankGateway(command);
if (!statementResult.IsSuccedded)
@@ -208,12 +247,14 @@ public class GeneralController : GeneralBaseController
return await HandleFailedTransaction(transaction);
}
var setSuccessResult = _paymentTransactionApplication.SetSuccess(paymentTransactionId, cardnumber, bank,null,null);
var setSuccessResult =
_paymentTransactionApplication.SetSuccess(paymentTransactionId, cardnumber, bank, null, null);
if (!setSuccessResult.IsSuccedded)
{
return new JsonResult(setSuccessResult);
}
return Redirect(BuildCallbackUrl(transaction.CallBackUrl, true, transaction.Id));
}
@@ -237,83 +278,83 @@ public class GeneralController : GeneralBaseController
var statusCode = isSuccess ? "1" : "0";
return $"{baseUrl}/callback?Status={statusCode}&transactionId={transactionId}";
}
}
public class TokenReq
{
public long Amount { get; set; }
public long Amount { get; set; }
public string CallbackUrl { get; set; }
[Display(Name = "شماره فاکتور")]
[MaxLength(100)]
[Required]
[Key]
// be ezaye har pazirande bayad yekta bashad
public string invoiceID { get; set; }
[Required]
public long terminalID { get; set; }
/*
* JSON Bashad
* etelaate takmili site harchi
* nabayad char khas dashte bashe (*'"xp_%!+- ...)
*/
public string Payload { get; set; } = "";
public string email { get; set; }
public string CallbackUrl { get; set; }
[Display(Name = "شماره فاکتور")]
[MaxLength(100)]
[Required]
[Key]
// be ezaye har pazirande bayad yekta bashad
public string invoiceID { get; set; }
[Required] public long terminalID { get; set; }
/*
* JSON Bashad
* etelaate takmili site harchi
* nabayad char khas dashte bashe (*'"xp_%!+- ...)
*/
public string Payload { get; set; } = "";
public string email { get; set; }
}
public class TokenResp
{
// if 0 = success
public int Status { get; set; }
public string AccessToken { get; set; }
// if 0 = success
public int Status { get; set; }
public string AccessToken { get; set; }
}
public class PayRequest
{
[Required]
[MaxLength(3000)]
public string token { get; set; }
[Required]
public long terminalID { get; set; }
public string nationalCode { get; set; }
[Required] [MaxLength(3000)] public string token { get; set; }
[Required] public long terminalID { get; set; }
public string nationalCode { get; set; }
}
public class SepehrGatewayPayResponse
{
/* 0 yni movafaq
* -1 yni enseraf
* -2 yni etmam zaman
*/
public int respcode { get; set; }
[Display(Name = "متن نتیجه تراکنش")]
public string respmsg { get; set; }
[Display(Name = "مبلغ کسر شده از مشتری")]
public long amount { get; set; }
[Display(Name = " شماره فاکتور ")]
public string invoiceid { get; set; }
[Display(Name = " اطلاعاتی که پذیرنده ارسال کرد ")]
public string payload { get; set; }
[Display(Name = " شماره ترمینال ")]
public long terminalid { get; set; }
[Display(Name = " شماره پیگیری ")]
public long tracenumber { get; set; }
// bayad negah dari she hatman to db
[Display(Name = " شماره سند بانکی ")]
public long rrn { get; set; }
[Display(Name = " زمان و تاریخ پرداخت ")]
public string datepaid { get; set; }
[Display(Name = " رسید دیجیتال ")]
public string digitalreceipt { get; set; }
[Display(Name = " نام بانک صادر کننده کارت ")]
public string issuerbank { get; set; }
[Display(Name = " شماره کارت ")]
public string cardnumber { get; set; }
/* 0 yni movafaq
* -1 yni enseraf
* -2 yni etmam zaman
*/
public int respcode { get; set; }
[Display(Name = "متن نتیجه تراکنش")] public string respmsg { get; set; }
[Display(Name = "مبلغ کسر شده از مشتری")]
public long amount { get; set; }
[Display(Name = " شماره فاکتور ")] public string invoiceid { get; set; }
[Display(Name = " اطلاعاتی که پذیرنده ارسال کرد ")]
public string payload { get; set; }
[Display(Name = " شماره ترمینال ")] public long terminalid { get; set; }
[Display(Name = " شماره پیگیری ")] public long tracenumber { get; set; }
// bayad negah dari she hatman to db
[Display(Name = " شماره سند بانکی ")] public long rrn { get; set; }
[Display(Name = " زمان و تاریخ پرداخت ")]
public string datepaid { get; set; }
[Display(Name = " رسید دیجیتال ")] public string digitalreceipt { get; set; }
[Display(Name = " نام بانک صادر کننده کارت ")]
public string issuerbank { get; set; }
[Display(Name = " شماره کارت ")] public string cardnumber { get; set; }
}
public class AdviceReq
{
[Display(Name = " رسید دیجیتال ")]
public string digitalreceipt { get; set; }
public long Tid { get; set; }
[Display(Name = " رسید دیجیتال ")] public string digitalreceipt { get; set; }
public long Tid { get; set; }
}

View File

@@ -41,7 +41,9 @@
},
"SmsSettings": {
"IsTestMode": true,
"TestNumbers": [ "09116967898", "09116067106", "09114221321" ]
"TestNumbers": [ "09116967898"
//, "09116067106", "09114221321"
]
},
"SepehrGateWayTerminalId": 99213700