Compare commits

..

8 Commits

57 changed files with 896 additions and 422 deletions

View File

@@ -24,10 +24,10 @@ public class AqayePardakhtPaymentGateway:IPaymentGateway
{
_httpClient = httpClientFactory.CreateClient();
// if (appSetting.Value.Domain == ".dadmehrg.ir")
// {
// _pin = "7349F84E81AB584862D9";
// }
if (appSetting.Value.Domain == ".dadmehrg.ir")
{
_pin = "7349F84E81AB584862D9";
}
}

View File

@@ -204,8 +204,7 @@ public class SmsService : ISmsService
int pageSize = 100; // max: 100
SmsIr smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa");
var response = await smsIr.GetArchivedReportAsync(pageNumber, pageSize, unixTimestamp, unixTimestamp2);
MessageReportResult[] messages = response.Data;
foreach (var message in messages)
{

View File

@@ -0,0 +1,46 @@
using System.Collections.Generic;
using _0_Framework_b.Domain;
namespace Company.Domain.AuthorizedBankDetailsAgg
{
public class AuthorizedBankDetails : EntityBase
{
private AuthorizedBankDetails()
{
OwnersList = new List<AuthorizedBankDetailsOwner>();
}
public AuthorizedBankDetails(string cardNumber, string accountNumber, string ban, string bankName, List<AuthorizedBankDetailsOwner> ownersList)
{
CardNumber = cardNumber;
AccountNumber = accountNumber;
IBan = ban;
BankName = bankName;
OwnersList = ownersList ?? new List<AuthorizedBankDetailsOwner>();
}
public string CardNumber { get; private set; }
public string AccountNumber { get; private set; }
public string IBan { get; private set; }
public string BankName { get; private set; }
public List<AuthorizedBankDetailsOwner> OwnersList { get; private set; }
}
public class AuthorizedBankDetailsOwner // Value Object - not inheriting from EntityBase
{
private AuthorizedBankDetailsOwner() { }
public AuthorizedBankDetailsOwner(string fName, string lName, string nationalIdentifier, string customerType)
{
FName = fName;
LName = lName;
NationalIdentifier = nationalIdentifier;
CustomerType = customerType;
}
public string FName { get; private set; }
public string LName { get; private set; }
public string NationalIdentifier { get; private set; }
public string CustomerType { get; private set; }
}
}

View File

@@ -0,0 +1,13 @@
using _0_Framework_b.Domain;
using System.Collections.Generic;
using Company.Application.Contracts.AuthorizedBankDetails;
namespace Company.Domain.AuthorizedBankDetailsAgg
{
public interface IAuthorizedBankDetailsRepository : IRepository<long, AuthorizedBankDetails>
{
EditAuthorizedBankDetails GetDetails(long id);
List<AuthorizedBankDetailsViewModel> Search(AuthorizedBankDetailsSearchModel searchModel);
AuthorizedBankDetailsViewModel GetByIban(string iban);
}
}

View File

@@ -73,6 +73,4 @@ public interface IInstitutionContractRepository : IRepository<long, InstitutionC
#endregion
Task<List<InstitutionContractSelectListViewModel>> GetInstitutionContractSelectList(string search, string selected);
Task<(double amount, long contractingPartyId, long institutionContractId)> GetFirstPaymentAmount(Guid id);
InstitutionContract GetIncludeContacts(long institutionContractId);
}

View File

@@ -9,30 +9,22 @@ namespace Company.Domain.PaymentTransactionAgg;
/// </summary>
public class PaymentTransaction:EntityBase
{
private PaymentTransaction(){}
/// <summary>
/// سازنده کلاس PaymentTransaction با دریافت اطلاعات تراکنش.
/// </summary>
/// <param name="contractingPartyId">شناسه طرف قرارداد</param>
/// <param name="amount">مبلغ تراکنش</param>
/// <param name="contractingPartyName">نام طرف قرارداد</param>
/// <param name="callBackUrl">آدرس بازگشت</param>
/// <param name="transactionSource">منبع تراکنش</param>
/// <param name="sourceId">شناسه منبع</param>
/// <param name="contractingPartyName"></param>
/// <param name="callBackUrl"></param>
public PaymentTransaction(long contractingPartyId,
double amount,
string contractingPartyName,
string callBackUrl,
PaymentTransactionSource transactionSource,
long sourceId)
string contractingPartyName,string callBackUrl)
{
ContractingPartyId = contractingPartyId;
Status = PaymentTransactionStatus.Pending;
Amount = amount;
ContractingPartyName = contractingPartyName;
CallBackUrl = callBackUrl;
Source = transactionSource;
SourceId = sourceId;
}
/// <summary>
@@ -75,16 +67,6 @@ public class PaymentTransaction:EntityBase
/// </summary>
public string TransactionId { get; private set; }
/// <summary>
/// نوع منبع تراکنش
/// </summary>
public PaymentTransactionSource Source { get; private set; }
/// <summary>
/// شناسه منبع (مثال: 2145 برای چک، 874156 برای بیمه)
/// </summary>
public long SourceId { get; private set; }
public string CallBackUrl { get; private set; }
public void SetPaid(string cardNumber,string bankName)

View File

@@ -12,9 +12,7 @@ public class CaseHistoryRollCallExcelForEmployeeViewModel
public string EmployeeFullName { get; set; }
public string TotalWorkingHoursFa { get; set; }
public string TotalWorkingTimeSpan { get; set; }
public List<RollCallItemForEmployeeExcelViewModel> RollCalls { get; set; }
}
@@ -40,7 +38,8 @@ public class RollCallItemForEmployeeExcelViewModel
public bool HasLeave { get; set; }
public string TotalWorkingHours { get; set; }
public string EnterTimeDifferences { get; set; }
public string ExitTimeDifferences { get; set; }
}
public class RollCallTimeExcelViewModel

View File

@@ -113,11 +113,12 @@ public class RollCallExcelGenerator : ExcelGenerator
worksheet.Cells[i + row + 1, 1].Value = i + 1;
worksheet.Cells[i + row + 1, 2].Value = rollCall.DayOfWeekFa;
worksheet.Cells[i + row + 1, 3].Value = rollCall.DateFa;
worksheet.Cells[i + row + 1, 4].Value = "-";
worksheet.Cells[i + row + 1, 4].Value = rollCall.EnterTimeDifferences;
worksheet.Cells[i + row + 1, 5].Value = rollCall.StartsItems;
worksheet.Cells[i + row + 1, 6].Value = rollCall.EndsItems;
worksheet.Cells[i + row + 1, 7].Value = "-";
worksheet.Cells[i + row + 1, 8].Value = rollCall.TotalWorkingHours == string.Empty ? "ندارد" : rollCall.TotalWorkingHours;
worksheet.Cells[i + row + 1, 7].Value = rollCall.ExitTimeDifferences;
worksheet.Cells[i + row + 1, 8].Value = rollCall.TotalWorkingHours == string.Empty
? "ندارد" : rollCall.TotalWorkingHours;
// Style data cells
for (int j = 1; j <= 8; j++)
@@ -307,6 +308,49 @@ public class RollCallExcelGenerator : ExcelGenerator
return package.GetAsByteArray();
}
private string CalculateExitMinuteDifference(TimeSpan early, TimeSpan late)
{
if (early == TimeSpan.Zero && late == TimeSpan.Zero)
{
return "-";
}
else if (late != TimeSpan.Zero)
{
var minutes = late.TotalMinutes > 999 ? "999" : late.TotalMinutes.ToString();
return $"{minutes}+";
}
else if (early != TimeSpan.Zero)
{
var minutes = early.TotalMinutes > 999 ? "999" : early.TotalMinutes.ToString();
return $"{minutes}-";
}
else
{
return $"";
}
}
private string CalculateEntryMinuteDifference(TimeSpan early, TimeSpan late)
{
if (early == TimeSpan.Zero && late == TimeSpan.Zero)
{
return "-";
}
else if (late != TimeSpan.Zero)
{
var minutes = late.TotalMinutes > 999 ? "999" : late.TotalMinutes.ToString();
return $"{minutes}-";
}
else if (early != TimeSpan.Zero)
{
var minutes = early.TotalMinutes > 999 ? "999" : early.TotalMinutes.ToString();
return $"{minutes}+";
}
else
{
return $"";
}
}
}

View File

@@ -0,0 +1,12 @@
namespace Company.Application.Contracts.AuthorizedBankDetails
{
public class AuthorizedBankDetailsSearchModel
{
public string CardNumber { get; set; }
public string AccountNumber { get; set; }
public string IBan { get; set; }
public string BankName { get; set; }
public string NationalIdentifier { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System;
using System.Collections.Generic;
namespace Company.Application.Contracts.AuthorizedBankDetails;
public class AuthorizedBankDetailsViewModel
{
public string NationalIdentifier { get; set; }
public long Id { get; set; }
public string CustomerType { get; set; }
public string CardNumber { get; set; }
public string AccountNumber { get; set; }
public string IBan { get; set; }
public string BankName { get; set; }
public List<AuthorizedBankDetailsOwnerViewModel> Owners { get; set; }
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Company.Application.Contracts.AuthorizedBankDetails
{
public class CreateAuthorizedBankDetails
{
public string CardNumber { get; set; }
public string AccountNumber { get; set; }
public string IBan { get; set; }
public string BankName { get; set; }
public List<CreateAuthorizedBankDetailsOwner> OwnersList { get; set; }
}
public class CreateAuthorizedBankDetailsOwner
{
public string FName { get; set; }
public string LName { get; set; }
public string NationalIdentifier { get; set; }
public string CustomerType { get; set; }
}
}

View File

@@ -0,0 +1,28 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace Company.Application.Contracts.AuthorizedBankDetails
{
public class EditAuthorizedBankDetails
{
public long Id { get; set; }
public string CardNumber { get; set; }
public string AccountNumber { get; set; }
public string IBan { get; set; }
public string BankName { get; set; }
public List<AuthorizedBankDetailsOwnerViewModel> OwnersList { get; set; }
}
public class AuthorizedBankDetailsOwnerViewModel
{
public string FName { get; set; }
public string LName { get; set; }
public string NationalIdentifier { get; set; }
public string CustomerType { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
using System.Collections.Generic;
using _0_Framework.Application;
using Company.Application.Contracts.AuthorizedBankDetails;
namespace Company.Application.Contracts.AuthorizedBankDetails
{
public interface IAuthorizedBankDetailsApplication
{
OperationResult Create(CreateAuthorizedBankDetails command);
EditAuthorizedBankDetails GetDetails(long id);
List<AuthorizedBankDetailsViewModel> Search(AuthorizedBankDetailsSearchModel searchModel);
AuthorizedBankDetailsViewModel GetByIban(string iban);
}
}

View File

@@ -90,7 +90,7 @@ public class InquiryContractingPartyBankDetailsRequest
public string CardNumber { get; set; }
public string AccountNumber { get; set; }
public string IBan { get; set; }
public UidBanks UidBank { get; set; }
public UidBanks? UidBank { get; set; }
}
public class ContractingPartyBankInquiryResponse
{

View File

@@ -239,8 +239,7 @@ public interface IInstitutionContractApplication
#endregion
Task<(double amount, long contractingPartyId, long institutionContractId)> GetFirstPaymentAmount(Guid id);
Task<OperationResult> CompletePendingVerify(long institutionContractId);
Task<OperationResult> ResendVerifyLink(long institutionContractId);
}
public class InsitutionContractAmendmentPaymentRequest

View File

@@ -17,7 +17,4 @@ public class CreatePaymentTransaction
/// مسیر برگشت پس از پرداخت
/// </summary>
public string CallBackUrl { get; set; }
public PaymentTransactionSource Source { get; set; }
public long SourceId { get; set; }
}

View File

@@ -101,15 +101,5 @@ public class PaymentTransactionDetailsViewModel
/// </summary>
public string TransactionId { get; set; }
/// <summary>
/// نوع منبع تراکنش
/// </summary>
public PaymentTransactionSource Source { get; set; }
/// <summary>
/// شناسه منبع (مثال: 2145 برای چک، 874156 برای بیمه)
/// </summary>
public string SourceId { get; set; }
public string CallBackUrl { get; set; }
}

View File

@@ -1,17 +0,0 @@
namespace CompanyManagment.App.Contracts.PaymentTransaction;
/// <summary>
/// انواع منابع تراکنش پرداخت
/// </summary>
public enum PaymentTransactionSource
{
/// <summary>
/// سایر
/// </summary>
Other,
/// <summary>
/// قرارداد
/// </summary>
InstitutionContract
}

View File

@@ -1,22 +1,21 @@
namespace CompanyManagment.App.Contracts.PaymentTransaction;
/// <summary>
/// وضعیت‌های مختلف تراکنش پرداخت
/// وضعیت تراکنش درگاه پرداخت
/// </summary>
public enum PaymentTransactionStatus
{
/// <summary>
/// در انتظار پرداخت
/// تراکنش در انتظار انجام است.
/// </summary>
Pending = 1,
Pending,
/// <summary>
/// پرداخت موفق
/// تراکنش با شکست مواجه شد.
/// </summary>
Success = 2,
Failed,
/// <summary>
/// پرداخت ناموفق
/// تراکنش با موفقیت انجام شد.
/// </summary>
Failed = 3
}
Success,
}

View File

@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using _0_Framework.Application;
using Company.Application.Contracts.AuthorizedBankDetails;
using Company.Domain.AuthorizedBankDetailsAgg;
namespace CompanyManagment.Application
{
public class AuthorizedBankDetailsApplication : IAuthorizedBankDetailsApplication
{
private readonly IAuthorizedBankDetailsRepository _authorizedBankDetailsRepository;
public AuthorizedBankDetailsApplication(IAuthorizedBankDetailsRepository authorizedBankDetailsRepository)
{
_authorizedBankDetailsRepository = authorizedBankDetailsRepository;
}
public OperationResult Create(CreateAuthorizedBankDetails command)
{
var operation = new OperationResult();
if (_authorizedBankDetailsRepository.Exists(x => x.CardNumber == command.CardNumber &&
x.AccountNumber == command.AccountNumber &&
x.IBan == command.IBan))
return operation.Failed(ApplicationMessages.DuplicatedRecord);
var ownersList = new List<AuthorizedBankDetailsOwner>();
if (command.OwnersList != null && command.OwnersList.Count > 0)
{
foreach (var owner in command.OwnersList)
{
var bankDetailsOwner = new AuthorizedBankDetailsOwner(
owner.FName,
owner.LName,
owner.NationalIdentifier,
owner.CustomerType
);
ownersList.Add(bankDetailsOwner);
}
}
var authorizedBankDetails = new AuthorizedBankDetails(
command.CardNumber,
command.AccountNumber,
command.IBan,
command.BankName,
ownersList
);
_authorizedBankDetailsRepository.Create(authorizedBankDetails);
_authorizedBankDetailsRepository.SaveChanges();
return operation.Succcedded();
}
public EditAuthorizedBankDetails GetDetails(long id)
{
return _authorizedBankDetailsRepository.GetDetails(id);
}
public List<AuthorizedBankDetailsViewModel> Search(AuthorizedBankDetailsSearchModel searchModel)
{
return _authorizedBankDetailsRepository.Search(searchModel);
}
public AuthorizedBankDetailsViewModel GetByIban(string iban)
{
return _authorizedBankDetailsRepository.GetByIban(iban);
}
}
}

View File

@@ -193,7 +193,7 @@ public class ContractingPartyBankAccountsApplication : IContractingPartyBankAcco
}
else if (!string.IsNullOrWhiteSpace(accountNumber))
{
var accountNumberRes = await _uidService.AccountToIban(accountNumber, uidBank);
var accountNumberRes = await _uidService.AccountToIban(accountNumber, uidBank.Value);
if (accountNumberRes.ResponseContext.Status.Code != 0)
{
throw new BadRequestException(

View File

@@ -2,17 +2,14 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Security.Policy;
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 Azure.Core;
using Company.Domain.ContarctingPartyAgg;
using Company.Domain.EmployeeAgg;
using Company.Domain.empolyerAgg;
@@ -26,7 +23,6 @@ using Company.Domain.WorkshopAgg;
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;
@@ -1253,6 +1249,32 @@ public class InstitutionContractApplication : IInstitutionContractApplication
if (institutionContract.VerifyCode != code)
return op.Failed("کد وارد شده صحیح نمی باشد");
var transaction = await _institutionContractRepository.BeginTransactionAsync();
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 transaction.CommitAsync();
await _institutionContractRepository.SaveChangesAsync();
return op.Succcedded();
}
@@ -1323,44 +1345,26 @@ public class InstitutionContractApplication : IInstitutionContractApplication
return _institutionContractRepository.GetAmendmentPaymentDetails(request);
}
public async Task<(double amount,long contractingPartyId,long institutionContractId)> GetFirstPaymentAmount(Guid id)
public async Task<OperationResult> ResendVerifyLink(long institutionContractId)
{
var balanceAmount = await _institutionContractRepository.GetFirstPaymentAmount(id);
return balanceAmount;
}
public async Task<OperationResult> CompletePendingVerify(long institutionContractId)
{
var institutionContract = _institutionContractRepository.GetIncludeContacts(institutionContractId);
var institutionContract = _institutionContractRepository.Get(institutionContractId);
var transaction = await _institutionContractRepository.BeginTransactionAsync();
var phone = institutionContract.ContactInfoList.FirstOrDefault(x =>
x.SendSms && x.Position == "طرف قرارداد" && x.PhoneType == "شماره همراه");
var contractingParty = _contractingPartyRepository.Get(institutionContract.ContractingPartyId);
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 (institutionContract == null)
{
throw new NotFoundException("رکورد مورد نظر یافت نشد");
}
await transaction.CommitAsync();
await _institutionContractRepository.SaveChangesAsync();
return new OperationResult().Succcedded();
if (institutionContract.VerificationStatus != InstitutionContractVerificationStatus.PendingForVerify)
{
throw new BadRequestException("این قرارداد مالی در وضعیت مناسبی برای ارسال مجدد لینک تایید نمی باشد");
}
var contractingParty = _contractingPartyRepository.Get(institutionContract.ContractingPartyId);
if (contractingParty == null)
throw new NotFoundException("طرف قرارداد یافت نشد");
var contractingPartyFullName = contractingParty.FName + " " + contractingParty.LName;
await _smsService.SendInstitutionVerificationLink(contractingParty.Phone, contractingPartyFullName,
institutionContract.PublicId);
return new OperationResult().Succcedded();
}

View File

@@ -50,9 +50,7 @@ public class PaymentTransactionApplication : IPaymentTransactionApplication
command.ContractingPartyId,
command.Amount,
contractingPartyName,
command.CallBackUrl,
command.Source,
command.SourceId);
command.CallBackUrl);
await _paymentTransactionRepository.CreateAsync(entity);
await _paymentTransactionRepository.SaveChangesAsync();

View File

@@ -1,5 +1,6 @@
using Company.Domain.AdminMonthlyOverviewAgg;
using Company.Domain.AndroidApkVersionAgg;
using Company.Domain.AuthorizedBankDetailsAgg;
using Company.Domain.BankAgg;
using Company.Domain.BillAgg;
using Company.Domain.Board;
@@ -201,6 +202,9 @@ public class CompanyContext : DbContext
public DbSet<InstitutionContractContactInfoTemp> InstitutionContractContactInfoTemps { get; set; }
public DbSet<AuthorizedBankDetails> AuthorizedBankDetails { get; set; }
#endregion
#region Pooya
@@ -309,7 +313,6 @@ public class CompanyContext : DbContext
public DbSet<Employer> Employers { get; set; }
public CompanyContext(DbContextOptions<CompanyContext> options) :base(options)
{

View File

@@ -0,0 +1,34 @@
using Company.Domain.AuthorizedBankDetailsAgg;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace CompanyManagment.EFCore.Mapping
{
public class AuthorizedBankDetailsMapping : IEntityTypeConfiguration<AuthorizedBankDetails>
{
public void Configure(EntityTypeBuilder<AuthorizedBankDetails> builder)
{
builder.ToTable("AuthorizedBankDetails");
builder.HasKey(x => x.id);
builder.Property(x => x.CardNumber).HasMaxLength(50);
builder.Property(x => x.AccountNumber).HasMaxLength(50);
builder.Property(x => x.IBan).HasMaxLength(50);
builder.Property(x => x.BankName).HasMaxLength(100);
// Configure owners as owned entities (value objects)
builder.OwnsMany(x => x.OwnersList, ownersBuilder =>
{
ownersBuilder.ToTable("AuthorizedBankDetailsOwners");
ownersBuilder.WithOwner().HasForeignKey("AuthorizedBankDetailsId");
ownersBuilder.Property<int>("Id").ValueGeneratedOnAdd();
ownersBuilder.HasKey("Id");
ownersBuilder.Property(x => x.FName).HasMaxLength(100);
ownersBuilder.Property(x => x.LName).HasMaxLength(100);
ownersBuilder.Property(x => x.NationalIdentifier).HasMaxLength(20);
ownersBuilder.Property(x => x.CustomerType).HasMaxLength(50);
});
}
}
}

View File

@@ -17,7 +17,6 @@ public class PaymentTransactionMapping:IEntityTypeConfiguration<PaymentTransacti
builder.Property(x => x.Status).HasConversion<string>().HasMaxLength(35);
builder.Property(x => x.ContractingPartyName).HasMaxLength(255);
builder.Property(x => x.CallBackUrl).HasMaxLength(500);
builder.Property(x => x.Source).HasConversion<string>().HasMaxLength(35);
}
}

View File

@@ -1,52 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace CompanyManagment.EFCore.Migrations
{
/// <inheritdoc />
public partial class addsourcetopaymenttransaction : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Source",
table: "PaymentTransactions",
type: "nvarchar(35)",
maxLength: 35,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<long>(
name: "SourceId",
table: "PaymentTransactions",
type: "bigint",
nullable: false,
defaultValue: 0L);
migrationBuilder.AddColumn<long>(
name: "LawId",
table: "InstitutionContractAmendments",
type: "bigint",
nullable: false,
defaultValue: 0L);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Source",
table: "PaymentTransactions");
migrationBuilder.DropColumn(
name: "SourceId",
table: "PaymentTransactions");
migrationBuilder.DropColumn(
name: "LawId",
table: "InstitutionContractAmendments");
}
}
}

View File

@@ -13,8 +13,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace CompanyManagment.EFCore.Migrations
{
[DbContext(typeof(CompanyContext))]
[Migration("20251018094820_add source to payment transaction")]
partial class addsourcetopaymenttransaction
[Migration("20251019092906_add authorized bank details")]
partial class addauthorizedbankdetails
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@@ -93,6 +93,38 @@ namespace CompanyManagment.EFCore.Migrations
b.ToTable("AndroidApkVersions", (string)null);
});
modelBuilder.Entity("Company.Domain.AuthorizedBankDetailsAgg.AuthorizedBankDetails", b =>
{
b.Property<long>("id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("id"));
b.Property<string>("AccountNumber")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("BankName")
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("CardNumber")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("IBan")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("id");
b.ToTable("AuthorizedBankDetails", (string)null);
});
modelBuilder.Entity("Company.Domain.AuthorizedPersonAgg.AuthorizedPerson", b =>
{
b.Property<long>("id")
@@ -4909,14 +4941,6 @@ namespace CompanyManagment.EFCore.Migrations
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Source")
.IsRequired()
.HasMaxLength(35)
.HasColumnType("nvarchar(35)");
b.Property<long>("SourceId")
.HasColumnType("bigint");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(35)
@@ -6884,6 +6908,48 @@ namespace CompanyManagment.EFCore.Migrations
b.ToTable("EmployerWorkshop");
});
modelBuilder.Entity("Company.Domain.AuthorizedBankDetailsAgg.AuthorizedBankDetails", b =>
{
b.OwnsMany("Company.Domain.AuthorizedBankDetailsAgg.AuthorizedBankDetailsOwner", "OwnersList", b1 =>
{
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property<int>("Id"));
b1.Property<long>("AuthorizedBankDetailsId")
.HasColumnType("bigint");
b1.Property<string>("CustomerType")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b1.Property<string>("FName")
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b1.Property<string>("LName")
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b1.Property<string>("NationalIdentifier")
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");
b1.HasKey("Id");
b1.HasIndex("AuthorizedBankDetailsId");
b1.ToTable("AuthorizedBankDetailsOwners", (string)null);
b1.WithOwner()
.HasForeignKey("AuthorizedBankDetailsId");
});
b.Navigation("OwnersList");
});
modelBuilder.Entity("Company.Domain.Board.Board", b =>
{
b.HasOne("Company.Domain.BoardType.BoardType", "BoardType")

View File

@@ -0,0 +1,68 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace CompanyManagment.EFCore.Migrations
{
/// <inheritdoc />
public partial class addauthorizedbankdetails : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AuthorizedBankDetails",
columns: table => new
{
id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
CardNumber = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
AccountNumber = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
IBan = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
BankName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
CreationDate = table.Column<DateTime>(type: "datetime2", nullable: false)
},
constraints: table => { table.PrimaryKey("PK_AuthorizedBankDetails", x => x.id); });
migrationBuilder.CreateTable(
name: "AuthorizedBankDetailsOwners",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
FName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
LName = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
NationalIdentifier = table.Column<string>(type: "nvarchar(20)", maxLength: 20, nullable: true),
CustomerType = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
AuthorizedBankDetailsId = table.Column<long>(type: "bigint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AuthorizedBankDetailsOwners", x => x.Id);
table.ForeignKey(
name: "FK_AuthorizedBankDetailsOwners_AuthorizedBankDetails_AuthorizedBankDetailsId",
column: x => x.AuthorizedBankDetailsId,
principalTable: "AuthorizedBankDetails",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_AuthorizedBankDetailsOwners_AuthorizedBankDetailsId",
table: "AuthorizedBankDetailsOwners",
column: "AuthorizedBankDetailsId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AuthorizedBankDetailsOwners");
migrationBuilder.DropTable(
name: "AuthorizedBankDetails");
}
}
}

View File

@@ -90,6 +90,38 @@ namespace CompanyManagment.EFCore.Migrations
b.ToTable("AndroidApkVersions", (string)null);
});
modelBuilder.Entity("Company.Domain.AuthorizedBankDetailsAgg.AuthorizedBankDetails", b =>
{
b.Property<long>("id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("id"));
b.Property<string>("AccountNumber")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("BankName")
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("CardNumber")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("IBan")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("id");
b.ToTable("AuthorizedBankDetails", (string)null);
});
modelBuilder.Entity("Company.Domain.AuthorizedPersonAgg.AuthorizedPerson", b =>
{
b.Property<long>("id")
@@ -4906,14 +4938,6 @@ namespace CompanyManagment.EFCore.Migrations
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Source")
.IsRequired()
.HasMaxLength(35)
.HasColumnType("nvarchar(35)");
b.Property<long>("SourceId")
.HasColumnType("bigint");
b.Property<string>("Status")
.IsRequired()
.HasMaxLength(35)
@@ -6881,6 +6905,48 @@ namespace CompanyManagment.EFCore.Migrations
b.ToTable("EmployerWorkshop");
});
modelBuilder.Entity("Company.Domain.AuthorizedBankDetailsAgg.AuthorizedBankDetails", b =>
{
b.OwnsMany("Company.Domain.AuthorizedBankDetailsAgg.AuthorizedBankDetailsOwner", "OwnersList", b1 =>
{
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b1.Property<int>("Id"));
b1.Property<long>("AuthorizedBankDetailsId")
.HasColumnType("bigint");
b1.Property<string>("CustomerType")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b1.Property<string>("FName")
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b1.Property<string>("LName")
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b1.Property<string>("NationalIdentifier")
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");
b1.HasKey("Id");
b1.HasIndex("AuthorizedBankDetailsId");
b1.ToTable("AuthorizedBankDetailsOwners", (string)null);
b1.WithOwner()
.HasForeignKey("AuthorizedBankDetailsId");
});
b.Navigation("OwnersList");
});
modelBuilder.Entity("Company.Domain.Board.Board", b =>
{
b.HasOne("Company.Domain.BoardType.BoardType", "BoardType")

View File

@@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
using System.Linq;
using _0_Framework.Application;
using _0_Framework_b.InfraStructure;
using Company.Application.Contracts.AuthorizedBankDetails;
using Company.Domain.AuthorizedBankDetailsAgg;
using Microsoft.EntityFrameworkCore;
namespace CompanyManagment.EFCore.Repository
{
public class AuthorizedBankDetailsRepository : RepositoryBase<long, AuthorizedBankDetails>, IAuthorizedBankDetailsRepository
{
private readonly CompanyContext _context;
public AuthorizedBankDetailsRepository(CompanyContext context) : base(context)
{
_context = context;
}
public EditAuthorizedBankDetails GetDetails(long id)
{
var authorizedBankDetails = _context.AuthorizedBankDetails
.Include(x => x.OwnersList)
.FirstOrDefault(x => x.id == id);
if (authorizedBankDetails == null)
return new EditAuthorizedBankDetails();
var result = new EditAuthorizedBankDetails
{
Id = authorizedBankDetails.id,
CardNumber = authorizedBankDetails.CardNumber,
AccountNumber = authorizedBankDetails.AccountNumber,
IBan = authorizedBankDetails.IBan,
BankName = authorizedBankDetails.BankName,
OwnersList = authorizedBankDetails.OwnersList.Select(o => new AuthorizedBankDetailsOwnerViewModel
{
FName = o.FName,
LName = o.LName,
NationalIdentifier = o.NationalIdentifier,
CustomerType = o.CustomerType
}).ToList()
};
return result;
}
public List<AuthorizedBankDetailsViewModel> Search(AuthorizedBankDetailsSearchModel searchModel)
{
var query = _context.AuthorizedBankDetails
.Include(x => x.OwnersList)
.Select(x => new AuthorizedBankDetailsViewModel
{
Id = x.id,
CardNumber = x.CardNumber,
AccountNumber = x.AccountNumber,
IBan = x.IBan,
});
if (!string.IsNullOrWhiteSpace(searchModel.CardNumber))
query = query.Where(x => x.CardNumber.Contains(searchModel.CardNumber));
if (!string.IsNullOrWhiteSpace(searchModel.AccountNumber))
query = query.Where(x => x.AccountNumber.Contains(searchModel.AccountNumber));
if (!string.IsNullOrWhiteSpace(searchModel.IBan))
query = query.Where(x => x.IBan.Contains(searchModel.IBan));
// if (!string.IsNullOrWhiteSpace(searchModel.BankName))
// query = query.Where(x => x.BankName.Contains(searchModel.BankName));
if (!string.IsNullOrWhiteSpace(searchModel.NationalIdentifier))
query = query.Where(x =>
_context.AuthorizedBankDetails
.Include(a => a.OwnersList)
.Any(a => a.id == x.Id &&
a.OwnersList.Any(o => o.NationalIdentifier.Contains(searchModel.NationalIdentifier))));
return query.OrderByDescending(x => x.Id).ToList();
}
public AuthorizedBankDetailsViewModel GetByIban(string iban)
{
return _context.AuthorizedBankDetails
.Include(x => x.OwnersList)
.Where(x => x.IBan == iban)
.Select(x => new AuthorizedBankDetailsViewModel
{
Id = x.id,
CardNumber = x.CardNumber,
AccountNumber = x.AccountNumber,
IBan = x.IBan,
BankName = x.BankName,
NationalIdentifier = x.OwnersList.FirstOrDefault().NationalIdentifier,
Owners = x.OwnersList.Select(o=> new AuthorizedBankDetailsOwnerViewModel()
{
FName = o.FName,
LName = o.LName,
NationalIdentifier = o.NationalIdentifier,
CustomerType = o.CustomerType
}).ToList()
})
.FirstOrDefault();
}
}
}

View File

@@ -10,6 +10,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AccountManagement.Application.Contracts.SubAccount;
using ZstdSharp.Unsafe;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
namespace CompanyManagment.EFCore.Repository;
@@ -266,14 +267,26 @@ public class FinancialStatmentRepository : RepositoryBase<long, FinancialStatmen
public async Task<FinancialStatmentDetailsByContractingPartyViewModel> GetDetailsByContractingParty(long contractingPartyId,FinancialStatementSearchModel searchModel)
{
var contractingParty = await _context.PersonalContractingParties
.FirstOrDefaultAsync(x=>x.id == contractingPartyId);
if (contractingParty == null)
throw new NotFoundException("طرف حساب یافت نشد");
var financialStatement = await _context.FinancialStatments
.Include(x=>x.FinancialTransactionList)
.FirstOrDefaultAsync(x=>x.ContractingPartyId == contractingPartyId);
if (financialStatement == null)
{
throw new NotFoundException("وضعیت مالی مورد نظر یافت نشد");
financialStatement = new FinancialStatment(contractingPartyId,contractingParty.FName+" "+contractingParty.LName);
await _context.AddAsync(financialStatement);
await _context.SaveChangesAsync();
}
bool searched = false;
#region Search
@@ -383,7 +396,8 @@ public class FinancialStatmentRepository : RepositoryBase<long, FinancialStatmen
};
list.Add(item);
}
list.Reverse();
var res = new FinancialStatmentDetailsByContractingPartyViewModel()
{
@@ -392,7 +406,7 @@ public class FinancialStatmentRepository : RepositoryBase<long, FinancialStatmen
TotalCredit = financialStatement.FinancialTransactionList.Sum(x => x.Creditor),
TotalDebt = financialStatement.FinancialTransactionList.Sum(x => x.Deptor),
ContractingPartyName = financialStatement.ContractingPartyName,
List = list.OrderByDescending(x=>x.DateTimeGr).ToList(),
List = list,
};
return res;
}

View File

@@ -2441,36 +2441,6 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
}
public async Task<(double amount,long contractingPartyId,long institutionContractId)> GetFirstPaymentAmount(Guid id)
{
var institutionContract = await _context.InstitutionContractSet
.Include(institutionContract => institutionContract.Installments)
.FirstOrDefaultAsync(x => x.PublicId == id);
long contractingPartyId = institutionContract.ContractingPartyId;
long institutionContractId = institutionContract.id;
if (institutionContract == null)
throw new NotFoundException("قرارداد مالی یافت نشد");
if (!institutionContract.IsInstallment)
return (institutionContract.TotalAmount,contractingPartyId,institutionContractId);
var institutionContractInstallment = institutionContract.Installments.FirstOrDefault();
if (institutionContractInstallment == null)
throw new NotFoundException("قسطی برای این قرارداد یافت نشد");
return (institutionContract.TotalAmount,contractingPartyId,institutionContractId);
}
public InstitutionContract GetIncludeContacts(long institutionContractId)
{
var institutionContract = _context.InstitutionContractSet
.Include(x => x.ContactInfoList)
.FirstOrDefault(x => x.id == institutionContractId);
if (institutionContract == null)
throw new NotFoundException("قرارداد مالی یافت نشد");
return institutionContract;
}
private InstitutionContractExtensionPaymentResponse CalculateInPersonPayment(
InstitutionContractExtensionPlanDetail selectedPlan, double baseAmount, double tenPercent,

View File

@@ -1517,7 +1517,9 @@ public class RollCallRepository : RepositoryBase<long, RollCall>, IRollCallRepos
StartDate = y.StartDate.Value.ToString("HH:mm"),
EndDate = y.EndDate!.Value.ToString("HH:mm"),
StartDateGr = y.StartDate.Value,
EndDateGr = y.EndDate.Value
EndDateGr = y.EndDate.Value,
EntryTimeDifferences = CalculateEntryTimeDifferences( y.EarlyEntryDuration, y.LateEntryDuration),
ExitTimeDifferences = CalculateExitTimeDifferences(y.EarlyExitDuration, y.LateExitDuration)
}),
TotalWorkingHoursSpan = new TimeSpan(rollCallsList.Where(y => x.Date == y.ShiftDate.Date)
.Sum(y => (y.EndDate!.Value - y.StartDate.Value).Ticks)),

View File

@@ -1,4 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text;
@@ -7,6 +9,7 @@ using Newtonsoft.Json;
using CompanyManagment.App.Contracts.AuthorizedPerson;
using _0_Framework.Application;
using _0_Framework.Application.UID;
using Company.Application.Contracts.AuthorizedBankDetails;
namespace CompanyManagment.EFCore.Services;
@@ -14,19 +17,21 @@ public class UidService : IUidService
{
private readonly HttpClient _httpClient;
private readonly IAuthorizedPersonApplication _authorizedPersonApplication;
private readonly IAuthorizedBankDetailsApplication _authorizedBankDetailsApplication;
private const string BaseUrl = "https://json-api.uid.ir/api/";
public const string BusinessToken = "5e03dd4e-999d-466f-92d8-7c0b1f66a8e9";
public const string BusinessId = "98ed67ca-d441-4978-a748-e8bebce010eb";
public UidService(IAuthorizedPersonApplication authorizedPersonApplication)
public UidService(IAuthorizedPersonApplication authorizedPersonApplication, IAuthorizedBankDetailsApplication authorizedBankDetailsApplication)
{
_httpClient = new HttpClient()
{
BaseAddress = new Uri(BaseUrl)
};
_authorizedPersonApplication = authorizedPersonApplication;
_authorizedBankDetailsApplication = authorizedBankDetailsApplication;
}
public async Task<PersonalInfoResponse> GetPersonalInfo(string nationalCode, string birthDate)
@@ -152,18 +157,94 @@ public class UidService : IUidService
public async Task<IbanInquiryResponse> IbanInquiry(string iban)
{
var request = new
{
iban,
requestContext = new UidRequestContext()
};
var json = JsonConvert.SerializeObject(request);
var contentType = new StringContent(json, Encoding.UTF8, "application/json");
// First check if bank details exist in database
var existingBankDetails = _authorizedBankDetailsApplication.GetByIban(iban);
if (existingBankDetails != null)
{
// Return data from database instead of calling API
return CreateIbanInquiryResponseFromDatabase(existingBankDetails);
}
// If not found in database, call UID API
var request = new
{
iban,
requestContext = new UidRequestContext()
};
var json = JsonConvert.SerializeObject(request);
var contentType = new StringContent(json, Encoding.UTF8, "application/json");
try
{
var requestResult = await _httpClient.PostAsync("inquiry/iban/v2", contentType);
requestResult.EnsureSuccessStatusCode();
//var stringRes =await requestResult.Content.ReadAsStringAsync();
var responseResult = await requestResult.Content.ReadFromJsonAsync<IbanInquiryResponse>();
if (responseResult.ResponseContext.Status.Code == 0)
{
var entity = new CreateAuthorizedBankDetails
{
IBan = iban,
AccountNumber = responseResult?.AccountBasicInformation?.AccountNumber ?? "",
BankName = responseResult?.AccountBasicInformation?.BankInformation?.BankName ?? "",
OwnersList = responseResult?.Owners.Select(x=> new CreateAuthorizedBankDetailsOwner()
{
FName = x.FirstName,
LName = x.LastName,
NationalIdentifier = x.NationalIdentifier,
CustomerType = x.CustomerType
}).ToList() ?? []
};
_authorizedBankDetailsApplication.Create(entity);
}
return responseResult;
}
catch
{
return new IbanInquiryResponse
{
ResponseContext = new ResponseContext(new UidStatus(14, "خطا در دریافت اطلاعات از سرویس"))
};
}
}
private IbanInquiryResponse CreateIbanInquiryResponseFromDatabase(AuthorizedBankDetailsViewModel bankDetails)
{
var accountBasicInfo = new IbanInquiryAccountBasicInformation
{
Iban = bankDetails.IBan,
AccountNumber = bankDetails.AccountNumber,
BankInformation = new IbanInquiryBankInformation
{
BankName = bankDetails.BankName
},
AccountStatus = "Active"
};
var owners = new List<IbanInquiryOwner>();
// Add owner information if available
if (bankDetails.Owners.Any())
{
var owner = bankDetails.Owners.First();
owners.Add(new IbanInquiryOwner
{
NationalIdentifier = owner.NationalIdentifier,
FirstName = owner.FName,
LastName = owner.LName,
CustomerType = owner.CustomerType
});
}
var responseContext = new ResponseContext(new UidStatus(0, "Success - از دیتابیس"));
return new IbanInquiryResponse
{
AccountBasicInformation = accountBasicInfo,
Owners = owners,
ResponseContext = responseContext
};
}
public async Task<AccountToIbanResponse> AccountToIban(string accountNumber, UidBanks bank)

View File

@@ -1,5 +1,6 @@
using System;
using _0_Framework.Application.UID;
using Company.Application.Contracts.AuthorizedBankDetails;
using Company.Domain.BillAgg;
using Company.Domain.Board;
using Company.Domain.ChapterAgg;
@@ -209,6 +210,7 @@ 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;
@@ -472,6 +474,9 @@ public class PersonalBootstrapper
services.AddTransient<ILawApplication,LawApplication>();
services.AddTransient<ILawRepository,LawRepository>();
services.AddTransient<IAuthorizedBankDetailsRepository, AuthorizedBankDetailsRepository>();
services.AddTransient<IAuthorizedBankDetailsApplication, AuthorizedBankDetailsApplication>();
services
.AddTransient<IInstitutionContractExtenstionTempRepository, InstitutionContractExtenstionTempRepository>();
#endregion

View File

@@ -2,7 +2,6 @@ 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;
@@ -12,7 +11,6 @@ using CompanyManagment.App.Contracts.Employer;
using CompanyManagment.App.Contracts.InstitutionContract;
using CompanyManagment.App.Contracts.InstitutionContractContactinfo;
using CompanyManagment.App.Contracts.InstitutionPlan;
using CompanyManagment.App.Contracts.PaymentTransaction;
using CompanyManagment.App.Contracts.PersonalContractingParty;
using CompanyManagment.App.Contracts.Representative;
using CompanyManagment.App.Contracts.TemporaryClientRegistration;
@@ -21,7 +19,6 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
using Microsoft.Extensions.Options;
using ServiceHost.Areas.Client.Pages.Company.PaymentToEmployee;
using ServiceHost.BaseControllers;
@@ -40,9 +37,6 @@ public class institutionContractController : AdminBaseController
private readonly IWorkshopApplication _workshopApplication;
private readonly ITemporaryClientRegistrationApplication _temporaryClientRegistration;
private readonly ITemporaryClientRegistrationApplication _clientRegistrationApplication;
private readonly IPaymentGateway _paymentGateway;
private readonly IPaymentTransactionApplication _paymentTransactionApplication;
private static readonly ConcurrentDictionary<Guid, SemaphoreSlim> _locks
= new ConcurrentDictionary<Guid, SemaphoreSlim>();
@@ -51,9 +45,7 @@ public class institutionContractController : AdminBaseController
public institutionContractController(IInstitutionContractApplication institutionContractApplication,
IPersonalContractingPartyApp contractingPartyApplication, IContactInfoApplication contactInfoApplication,
IAccountApplication accountApplication, IEmployerApplication employerApplication,
IWorkshopApplication workshopApplication, ITemporaryClientRegistrationApplication temporaryClientRegistration,
ITemporaryClientRegistrationApplication clientRegistrationApplication, IHttpClientFactory httpClientFactory,
IOptions<AppSettingConfiguration> appSetting, IPaymentTransactionApplication paymentTransactionApplication)
IWorkshopApplication workshopApplication, ITemporaryClientRegistrationApplication temporaryClientRegistration, ITemporaryClientRegistrationApplication clientRegistrationApplication)
{
_institutionContractApplication = institutionContractApplication;
_contractingPartyApplication = contractingPartyApplication;
@@ -63,8 +55,6 @@ public class institutionContractController : AdminBaseController
_workshopApplication = workshopApplication;
_temporaryClientRegistration = temporaryClientRegistration;
_clientRegistrationApplication = clientRegistrationApplication;
_paymentTransactionApplication = paymentTransactionApplication;
_paymentGateway = new AqayePardakhtPaymentGateway(httpClientFactory, appSetting);
}
/// <summary>
@@ -478,57 +468,6 @@ public class institutionContractController : AdminBaseController
return res;
}
[HttpPost("/api/institutionContract/pay")]
public async Task<ActionResult<OperationResult>> PayContract([FromForm]institutionContractPayContractRequest request)
{
var id = request.Id;
var baseUrl = request.BaseUrl;
var op = new OperationResult();
var amount = await _institutionContractApplication.GetFirstPaymentAmount(id);
var callbackUrl = Url.Action(
action: "InstitutionContractCallBack",
controller: "General", // نام کنترلر بدون کلمه‌ی "Controller"
values: null,
protocol: Request.Scheme); // http یا https
var transactionCommand = new CreatePaymentTransaction()
{
Amount = amount.amount,
ContractingPartyId = amount.contractingPartyId,
CallBackUrl = baseUrl,
Source = PaymentTransactionSource.InstitutionContract,
SourceId = amount.institutionContractId
};
var transaction = await _paymentTransactionApplication.Create(transactionCommand);
if (!transaction.IsSuccedded)
{
return op.Failed(transaction.Message);
}
var command = new CreatePaymentGatewayRequest()
{
CallBackUrl = callbackUrl,
Amount = amount.amount/10,
InvoiceId = transaction.SendId.ToString(),
};
var gatewayResponse = await _paymentGateway.Create(command);
if (gatewayResponse.IsSuccess)
{
_ = await _paymentTransactionApplication.SetTransactionId(transaction.SendId, gatewayResponse.TransactionId);
return Redirect(_paymentGateway.GetStartPayUrl(gatewayResponse.TransactionId));
}
if (gatewayResponse.ErrorCode.HasValue)
{
return op.Failed($"خطا در ایجاد درگاه پرداخت: {gatewayResponse.ErrorCode.Value}");
}
return op.Failed("خطا در ایجاد درگاه پرداخت");
}
[HttpPost("/api/institutionContract/Verification/{id:guid}/send-otp")]
[AllowAnonymous]
public async Task<ActionResult<OperationResult<OtpResultViewModel>>> SendVerifyOtp(Guid id)
@@ -588,13 +527,15 @@ public class institutionContractController : AdminBaseController
var res =await _institutionContractApplication.GetAmendmentWorkshops(institutionContractId);
return res;
}
[HttpPost("resend-verify-link/{institutionContractId}")]
public async Task<OperationResult> ResendVerifyLink(long institutionContractId)
{
var res = await _institutionContractApplication.ResendVerifyLink(institutionContractId);
return res;
}
}
public class institutionContractPayContractRequest
{
public Guid Id { get; set; }
public string BaseUrl { get; set; }
}
public class VerifyOtpRequest
{

View File

@@ -871,6 +871,14 @@
</div>
<div class="child-check level2">
<label class="btn btn-icon waves-effect btn-default m-b-5 open-close">
<i class="ion-plus"></i> <i class="ion-minus" style="display: none;"></i><input type="checkbox" style="display: none" class="open-btn" />
</label>
<label class="btn btn-inverse waves-effect waves-light m-b-5 parentLevel2"> <input type="checkbox" disabled="disabled" value="1004" class="check-btn"> &nbsp;<span style="bottom: 2px;position: relative"> قرارداد های مالی </span> </label>
</div>
</div>
@* بررسی مدارک پرسنل *@
<div class="parent-check">

View File

@@ -881,6 +881,15 @@
</div>
<div class="child-check level2">
<label class="btn btn-icon waves-effect btn-default m-b-5 open-close">
<i class="ion-plus"></i> <i class="ion-minus" style="display: none;"></i><input type="checkbox" style="display: none" class="open-btn" />
</label>
<label class="btn btn-inverse waves-effect waves-light m-b-5 parentLevel2"> <input type="checkbox" disabled="disabled" value="1004" class="check-btn"> &nbsp;<span style="bottom: 2px;position: relative"> قرارداد های مالی </span> </label>
</div>
</div>
@* بررسی مدارک پرسنل *@
<div class="parent-check">

View File

@@ -195,7 +195,7 @@
<div class="rollcall-list Rtable Rtable--5cols Rtable--collapse px-1">
<div class="w-100 my-1">
<div class="absenceHeadColorTop" style="border-radius: 10px 10px 0 0;">غیبت</div>
<div class="absenceHeadColorTop" style="border-radius: 10px 10px 0 0;">عدم حضور</div>
<div class="Rtable-row Rtable-row--head align-items-center d-flex table-rollcall-absent absenceHeadColor">
<div class="Rtable-cell column-heading width1">ردیف</div>
<div class="Rtable-cell column-heading width2">نام پرسنل</div>
@@ -328,7 +328,7 @@
<div class="btnsRollCallOnlline">
<button class="btnRollCallStatus active" onclick="loadRollCallStatus('all')">آنلاین</button>
<button class="btnRollCallStatus" onclick="loadRollCallStatus('leave')">مرخصی <span id="leaveCount"></span></button>
<button class="btnRollCallStatus" onclick="loadRollCallStatus('absent')">غیبت <span id="absentCount"></span></button>
<button class="btnRollCallStatus" onclick="loadRollCallStatus('absent')">عدم حضور <span id="absentCount"></span></button>
</div>
</div>
<div class="wrapper">

View File

@@ -127,8 +127,8 @@
</a>
</div>
<div class="gwb-card" permission="1002">
<a href="https://admin@(AppSetting.Value.Domain)/workflow" class="click loadingButton">
<div class="gwb-card" permission="1004">
<a href="https://admin@(AppSetting.Value.Domain)/workflow/institution-contract" class="click loadingButton">
<div class="d-flex align-items-center justify-content-between p-1 w-100">
<div class="d-flex align-items-center">
<img src="~/AssetsClient/images/insuranceList.png" alt="" class="img-fluid mx-1" width="50px" />

View File

@@ -72,9 +72,7 @@ public class FinancialController : ClientBaseController
{
Amount = balanceAmount.Amount,
ContractingPartyId = balanceAmount.ContractingPartyId,
CallBackUrl = request.BaseUrl,
Source = PaymentTransactionSource.Other,
SourceId = 0
CallBackUrl = request.BaseUrl
};
var transaction = await _paymentTransactionApplication.Create(transactionCommand);

View File

@@ -231,7 +231,7 @@
<div class="day-off-parent">
<div class="day-off-title mb-2">
روزهای تعطیل هفته
روزهای فعالیت مجموعه
</div>
<div class="day-off-button-container mb-3">

View File

@@ -382,7 +382,9 @@ namespace ServiceHost.Areas.Client.Pages.Company.RollCall
IsAbsent = x.IsAbsent,
TotalWorkingHours = x.TotalWorkingHours,
StartsItems = string.Join(Environment.NewLine, x.RollCallTimesList.Select(tr=>tr.StartDate)),
EndsItems= string.Join(Environment.NewLine, x.RollCallTimesList.Select(tr=>tr.EndDate))
EndsItems= string.Join(Environment.NewLine, x.RollCallTimesList.Select(tr=>tr.EndDate)),
EnterTimeDifferences = string.Join(Environment.NewLine, x.RollCallTimesList.Select(tr=>tr.EntryTimeDifferences)),
ExitTimeDifferences = string.Join(Environment.NewLine, x.RollCallTimesList.Select(tr=>tr.ExitTimeDifferences))
}).ToList()
};

View File

@@ -234,7 +234,7 @@
<div class="rollcall-list Rtable Rtable--5cols Rtable--collapse px-1">
<div class="w-100 my-1">
<div class="absenceHeadColorTop" style="border-radius: 10px 10px 0 0;">غیبت</div>
<div class="absenceHeadColorTop" style="border-radius: 10px 10px 0 0;">عدم حضور</div>
<div class="Rtable-row Rtable-row--head align-items-center d-flex table-rollcall-absent absenceHeadColor">
<div class="Rtable-cell column-heading width1">ردیف</div>
<div class="Rtable-cell column-heading width2">نام پرسنل</div>
@@ -367,7 +367,7 @@
<div class="btnsRollCallOnlline">
<button class="btnRollCallStatus active" onclick="loadRollCallStatus('all')">آنلاین</button>
<button class="btnRollCallStatus" onclick="loadRollCallStatus('leave')">مرخصی <span id="leaveCount"></span></button>
<button class="btnRollCallStatus" onclick="loadRollCallStatus('absent')">غیبت <span id="absentCount"></span></button>
<button class="btnRollCallStatus" onclick="loadRollCallStatus('absent')">عدم حضور <span id="absentCount"></span></button>
</div>
</div>
<div class="wrapper">

View File

@@ -223,7 +223,7 @@
<div class="day-off-parent">
<div class="day-off-title mb-2">
روزهای تعطیل هفته
روزهای فعالیت مجموعه
</div>
<div class="day-off-button-container mb-3">

View File

@@ -383,7 +383,7 @@
<div class="day-off-parent">
<div class="day-off-title mb-2">
روزهای تعطیل هفته
روزهای فعالیت مجموعه
</div>
<div class="day-off-button-container mb-3">

View File

@@ -393,7 +393,7 @@
<div class="day-off-parent">
<div class="day-off-title mb-2">
روزهای تعطیل هفته
روزهای فعالیت مجموعه
</div>
<div class="day-off-button-container mb-3">

View File

@@ -17,7 +17,7 @@
<button type="button" class="btn-close position-absolute text-start" data-bs-dismiss="modal" aria-label="Close"></button>
<h6 class="m-0">پرینت حضور و غیاب انفرادی @Model.PersianMonthName ماه @Model.PersianYear</h6>
</div>
```````
<div class="modal-body" id="divTablescrollbar">
<div class="row main-table">
@@ -121,7 +121,17 @@
<span class="m-0">@item.DateFa</span>
</td>
<td style="font-family: 'IranText' !important; font-size: 10px !important; text-align: center">
-
@if (item.RollCallTimesList.Any())
{
@foreach (var rollCallItem in item.RollCallTimesList)
{
<div>@(rollCallItem.EntryTimeDifferences ?? "-")</div>
}
}
else
{
<span>-</span>
}
</td>
<td style="font-family: 'IranText' !important; font-size: 10px !important; text-align: center">
@if (item.RollCallTimesList.Any())
@@ -150,7 +160,17 @@
}
</td>
<td style="font-family: 'IranText' !important; font-size: 10px !important; text-align: center">
-
@if (item.RollCallTimesList.Any())
{
@foreach (var rollCallItem in item.RollCallTimesList)
{
<div>@(rollCallItem.ExitTimeDifferences ?? "-")</div>
}
}
else
{
<span>-</span>
}
</td>
<td style="font-family: 'IranText' !important; font-size: 10px !important; text-align: center">
@item.TotalWorkingHours

View File

@@ -90,7 +90,7 @@
<div class="day-off-parent">
<div class="day-off-title mb-2">
روزهای تعطیل هفته
روزهای فعالیت مجموعه
</div>
<div class="day-off-button-container mb-3">

View File

@@ -154,7 +154,7 @@
<div class="day-off-parent">
<div class="day-off-title mb-2">
روزهای تعطیل هفته
روزهای فعالیت مجموعه
</div>
<div class="day-off-button-container mb-3">

View File

@@ -218,7 +218,7 @@
<div class="day-off-parent mb-4">
<div class="day-off-title mb-2">
روزهای تعطیل هفته
روزهای فعالیت مجموعه
</div>
<div class="day-off-button-container mb-3">

View File

@@ -168,7 +168,7 @@
<div class="day-off-parent">
<div class="day-off-title mb-2">
روزهای تعطیل هفته
روزهای فعالیت مجموعه
</div>
<div class="day-off-button-container mb-3">

View File

@@ -71,7 +71,7 @@
<li class="active" data-menu="absent">
<div class="d-flex align-items-center justify-content-between" id="clickAbsentTab">
<a href="javascript:void(0);">غیبت</a>
<a href="javascript:void(0);">عدم حضور</a>
<div>
<div id="CountAbsentLoading" class="spinner-grow text-danger" role="status" style="align-items: center;justify-content: center;display: flex;margin: 0 0 0 9px;">
<span class="visually-hidden">Loading...</span>
@@ -218,7 +218,7 @@
<div class="Rtable-row SubAccountRowMobile align-items-center position-relative openAction">
<div class="Rtable-cell d-md-block d-flex width2">
<div class="Rtable-cell--content text-start">
<div class="roleName">غیبت</div>
<div class="roleName">عدم حضور</div>
</div>
</div>
<div>

View File

@@ -9,7 +9,6 @@ using _0_Framework.Application.PaymentGateway;
using Microsoft.Extensions.Options;
using CompanyManagment.App.Contracts.FinancialStatment;
using CompanyManagment.App.Contracts.FinancilTransaction;
using CompanyManagment.App.Contracts.InstitutionContract;
namespace ServiceHost.Controllers;
@@ -19,14 +18,12 @@ public class GeneralController : GeneralBaseController
private readonly IPaymentTransactionApplication _paymentTransactionApplication;
private readonly IPaymentGateway _paymentGateway;
private readonly IFinancialStatmentApplication _financialStatmentApplication;
private readonly IInstitutionContractApplication _institutionContractApplication;
public GeneralController(IPaymentTransactionApplication paymentTransactionApplication,IHttpClientFactory clientFactory, IFinancialStatmentApplication financialStatmentApplication, IOptions<AppSettingConfiguration> appSetting, IInstitutionContractApplication institutionContractApplication)
public GeneralController(IPaymentTransactionApplication paymentTransactionApplication,IHttpClientFactory clientFactory, IFinancialStatmentApplication financialStatmentApplication, IOptions<AppSettingConfiguration> appSetting)
{
_paymentTransactionApplication = paymentTransactionApplication;
_paymentGateway = new AqayePardakhtPaymentGateway(clientFactory, appSetting);
_financialStatmentApplication = financialStatmentApplication;
_institutionContractApplication = institutionContractApplication;
}
/// <summary>
@@ -115,93 +112,6 @@ public class GeneralController : GeneralBaseController
// در غیر این صورت تراکنش ناموفق است
return await HandleFailedTransaction(transaction, paymentTransactionId);
}
[HttpPost("/api/institution-contract/callback")]
public async Task<IActionResult> InstitutionContractCallBack(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("این تراکنش قبلا پرداخت شده است");
}
long institutionContractId = 0;
if (transaction.Source != PaymentTransactionSource.InstitutionContract
&& !long.TryParse(transaction.SourceId, out institutionContractId))
{
return BadRequest("اطلاعات تراکنش نامعتبر است");
}
// اگر شماره کارت یا شماره پیگیری خالی باشد، تراکنش ناموفق است
if (string.IsNullOrWhiteSpace(cardnumber) || string.IsNullOrWhiteSpace(tracking_number))
{
return await HandleFailedTransaction(transaction, paymentTransactionId);
}
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, paymentTransactionId);
}
var setSuccessResult = _paymentTransactionApplication.SetSuccess(paymentTransactionId, cardnumber, bank);
if (!setSuccessResult.IsSuccedded)
{
return new JsonResult(setSuccessResult);
}
//_institutionContractApplication.;
var institutionContract = await _institutionContractApplication
.CompletePendingVerify(institutionContractId);
if (!institutionContract.IsSuccedded)
{
return await HandleFailedTransaction(transaction, paymentTransactionId);
}
return Redirect(BuildCallbackUrl(transaction.CallBackUrl, true, transaction.Id));
}
// در غیر این صورت تراکنش ناموفق است
return await HandleFailedTransaction(transaction, paymentTransactionId);
}
private async Task<IActionResult> HandleFailedTransaction(PaymentTransactionDetailsViewModel transaction, long transactionId)
{

View File

@@ -420,7 +420,7 @@ input:checked + .sliderEUP:before {
background-color: #ffffff;
background: rgba(209, 50, 50, 0.15);
transition: ease .2s;
width: 55px;
/*width: 55px;*/
}
.btn-workflow-rollcall-edit {

View File

@@ -292,7 +292,7 @@ function loadEmployeeListByWorkFlowsAbsents(date) {
</button>
<button type="button" class="btn-workflow-absent" onclick="confirmAbsentAlert(${rollCallItem.employeeId}, '${data.dateTimeFa}')">
<span class="mx-1">غیبت</span>
<span class="mx-1 text-nowrap">عدم حضور</span>
</button>
<button class="btn-workflow-rollcall-edit position-relative" onclick="showModalEditRollCall(${rollCallItem.employeeId}, '${data.dateTimeFa}')">
@@ -1028,7 +1028,7 @@ function showModalEditLeave(leaveId) {
function confirmAbsentAlert(employeeId, dateFa) {
swal({
title: "آیا از تایید این غیبت اطمینان دارید؟",
title: "آیا از تایید این عدم حضور اطمینان دارید؟",
text: "",
type: "warning",
showCancelButton: true,