Compare commits
1 Commits
Feature/Fi
...
Feature/ro
| Author | SHA1 | Date | |
|---|---|---|---|
| 3258deeb2c |
@@ -39,7 +39,7 @@ public class AqayePardakhtPaymentGateway:IPaymentGateway
|
||||
amount = command.Amount,
|
||||
callback = command.CallBackUrl,
|
||||
card_number = command.CardNumber,
|
||||
invoice_id = command.TransactionId,
|
||||
invoice_id = command.InvoiceId,
|
||||
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.TransactionId,
|
||||
invoice_id = command.InvoiceId,
|
||||
mobile = command.Mobile,
|
||||
email = command.Email,
|
||||
description = command.Email,
|
||||
|
||||
@@ -49,13 +49,12 @@ 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; }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Json;
|
||||
using System.Threading;
|
||||
@@ -17,18 +16,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.TransactionId,
|
||||
InvoiceID = command.InvoiceId,
|
||||
callbackURL = command.CallBackUrl,
|
||||
payload = extraData
|
||||
}, cancellationToken: cancellationToken);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using _0_Framework.Application;
|
||||
using _0_Framework.Domain;
|
||||
using CompanyManagment.App.Contracts.AndroidApkVersion;
|
||||
|
||||
namespace Company.Domain.AndroidApkVersionAgg;
|
||||
|
||||
@@ -8,14 +9,17 @@ public class AndroidApkVersion:EntityBase
|
||||
{
|
||||
private AndroidApkVersion () { }
|
||||
|
||||
public AndroidApkVersion( string versionName,string versionCode, IsActive isActive, string path)
|
||||
public AndroidApkVersion( string versionName,string versionCode, IsActive isActive, string path, ApkType apkType, bool isForce = false)
|
||||
{
|
||||
|
||||
VersionName = versionName;
|
||||
VersionCode = versionCode;
|
||||
IsActive = isActive;
|
||||
Path = path;
|
||||
Title = $"Gozareshgir-{versionName}-{CreationDate:g}";
|
||||
ApkType = apkType;
|
||||
IsForce = isForce;
|
||||
var appName = apkType == ApkType.WebView ? "Gozareshgir-WebView" : "Gozareshgir-FaceDetection";
|
||||
Title = $"{appName}-{versionName}-{CreationDate:g}";
|
||||
}
|
||||
|
||||
public string Title { get; private set; }
|
||||
@@ -23,6 +27,9 @@ public class AndroidApkVersion:EntityBase
|
||||
public string VersionCode{ get; private set; }
|
||||
public IsActive IsActive { get; private set; }
|
||||
public string Path { get; set; }
|
||||
public ApkType ApkType { get; private set; }
|
||||
public bool IsForce { get; private set; }
|
||||
|
||||
|
||||
public void Active()
|
||||
{
|
||||
@@ -33,4 +40,4 @@ public class AndroidApkVersion:EntityBase
|
||||
{
|
||||
IsActive = IsActive.False;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using _0_Framework_b.Domain;
|
||||
using CompanyManagment.App.Contracts.AndroidApkVersion;
|
||||
|
||||
namespace Company.Domain.AndroidApkVersionAgg;
|
||||
|
||||
public interface IAndroidApkVersionRepository:IRepository<long,AndroidApkVersion>
|
||||
{
|
||||
IQueryable<AndroidApkVersion> GetActives();
|
||||
IQueryable<AndroidApkVersion> GetActives(ApkType apkType);
|
||||
AndroidApkVersion GetLatestActive(ApkType apkType);
|
||||
void Remove(AndroidApkVersion entity);
|
||||
System.Threading.Tasks.Task<string> GetLatestActiveVersionPath();
|
||||
System.Threading.Tasks.Task<string> GetLatestActiveVersionPath(ApkType apkType);
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
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);
|
||||
}
|
||||
@@ -5,7 +5,6 @@ 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;
|
||||
|
||||
@@ -22,8 +22,6 @@ public interface IFinancialStatmentRepository : IRepository<long, FinancialStatm
|
||||
Task<OperationResult<ClientFinancialStatementViewModel>> GetDetailsByPublicId(string publicId);
|
||||
Task<GetFinancialStatementBalanceAmount> GetBalanceAmount(long id);
|
||||
Task<double> GetClientDebtAmount(long accountId);
|
||||
Task<double> GetClientDebtAmountByContractingPartyId(long contractingPartyId);
|
||||
|
||||
Task<FinancialStatmentDetailsByContractingPartyViewModel> GetDetailsByContractingParty(long contractingPartyId,FinancialStatementSearchModel searchModel);
|
||||
Task<FinancialStatmentDetailsByContractingPartyViewModel> GetDetailsByContractingParty(long contractingPartyId,FinancialStatementSearchModel searchModel);
|
||||
Task<FinancialStatment> GetByContractingPartyId(long contractingPartyId);
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using _0_Framework.Domain;
|
||||
using Company.Domain.FinancialInvoiceAgg;
|
||||
using CompanyManagment.App.Contracts.PaymentTransaction;
|
||||
|
||||
namespace Company.Domain.PaymentTransactionAgg;
|
||||
@@ -10,15 +9,14 @@ 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>
|
||||
/// <param name="gateway"></param>
|
||||
public PaymentTransaction(long contractingPartyId,
|
||||
/// <summary>
|
||||
/// سازنده کلاس PaymentTransaction با دریافت اطلاعات تراکنش.
|
||||
/// </summary>
|
||||
/// <param name="contractingPartyId">شناسه طرف قرارداد</param>
|
||||
/// <param name="amount">مبلغ تراکنش</param>
|
||||
/// <param name="contractingPartyName"></param>
|
||||
/// <param name="callBackUrl"></param>
|
||||
public PaymentTransaction(long contractingPartyId,
|
||||
double amount,
|
||||
string contractingPartyName,string callBackUrl,
|
||||
PaymentTransactionGateWay gateway)
|
||||
@@ -76,9 +74,6 @@ 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)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace CompanyManagment.App.Contracts.AndroidApkVersion;
|
||||
|
||||
public enum ApkType
|
||||
{
|
||||
WebView,
|
||||
FaceDetection
|
||||
}
|
||||
|
||||
@@ -4,12 +4,15 @@ using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace CompanyManagment.App.Contracts.AndroidApkVersion;
|
||||
|
||||
public record AndroidApkVersionInfo(int LatestVersionCode, string LatestVersionName, bool ShouldUpdate, bool IsForceUpdate, string DownloadUrl, string ReleaseNotes);
|
||||
|
||||
public interface IAndroidApkVersionApplication
|
||||
{
|
||||
Task<OperationResult> CreateAndActive(IFormFile file);
|
||||
Task<OperationResult> CreateAndDeActive(IFormFile file);
|
||||
Task<string> GetLatestActiveVersionPath();
|
||||
Task<OperationResult> CreateAndActive(IFormFile file, ApkType apkType, bool isForce = false);
|
||||
Task<OperationResult> CreateAndDeActive(IFormFile file, ApkType apkType, bool isForce = false);
|
||||
Task<string> GetLatestActiveVersionPath(ApkType apkType);
|
||||
Task<AndroidApkVersionInfo> GetLatestActiveInfo(ApkType apkType, int currentVersionCode);
|
||||
OperationResult Remove(long id);
|
||||
|
||||
bool HasAndroidApkToDownload();
|
||||
bool HasAndroidApkToDownload(ApkType apkType);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
namespace CompanyManagment.App.Contracts.FinancialInvoice;
|
||||
|
||||
public enum FinancialInvoiceItemType
|
||||
{
|
||||
/// <summary>
|
||||
/// قسط قرارداد خرید از موسسه
|
||||
/// </summary>
|
||||
BuyInstitutionContractInstallment,
|
||||
/// <summary>
|
||||
/// خرید قرارداد از موسسه
|
||||
/// </summary>
|
||||
BuyInstitutionContract,
|
||||
/// <summary>
|
||||
///قسط ارتقا قرارداد موسسه
|
||||
/// </summary>
|
||||
AmendmentInstitutionContractInstallment,
|
||||
/// <summary>
|
||||
/// ارتقا قرارداد موسسه
|
||||
/// </summary>
|
||||
AmendmentInstitutionContract,
|
||||
/// <summary>
|
||||
/// بدهی قبلی
|
||||
/// </summary>
|
||||
PreviousDebt,
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
namespace CompanyManagment.App.Contracts.FinancialInvoice;
|
||||
|
||||
public enum FinancialInvoiceStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// پرداخت نشده
|
||||
/// </summary>
|
||||
Unpaid = 0,
|
||||
/// <summary>
|
||||
/// پرداخت شده کامل
|
||||
/// </summary>
|
||||
Paid = 1,
|
||||
/// <summary>
|
||||
/// فاکتور لغو شده
|
||||
/// </summary>
|
||||
Cancelled = 4,
|
||||
/// <summary>
|
||||
/// // بازپرداخت شده (در صورت برگشت وجه)
|
||||
/// </summary>
|
||||
Refunded = 5,
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
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);
|
||||
}
|
||||
@@ -213,7 +213,7 @@ public interface IInstitutionContractApplication
|
||||
|
||||
Task<GetInstitutionVerificationDetailsViewModel> GetVerificationDetails(Guid id);
|
||||
Task<OperationResult<OtpResultViewModel>> SendVerifyOtp(Guid id);
|
||||
Task<OperationResult<string>> VerifyOtpAndMakeGateway(Guid publicId, string code, string callbackUrl);
|
||||
Task<OperationResult> VerifyOtp(Guid publicId, string code);
|
||||
Task<InstitutionContractWorkshopDetailViewModel> GetWorkshopInitialDetails(long workshopDetailsId);
|
||||
|
||||
#region Extension
|
||||
@@ -251,8 +251,6 @@ public interface IInstitutionContractApplication
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
Task<InstitutionContractPrintViewModel> PrintOneAsync(long id);
|
||||
|
||||
Task<OperationResult> SetPendingWorkflow(long entityId);
|
||||
}
|
||||
|
||||
public class InstitutionContractPrintViewModel
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using AccountManagement.Domain.TaskAgg;
|
||||
using ApkReader;
|
||||
using Company.Domain.AndroidApkVersionAgg;
|
||||
using CompanyManagment.App.Contracts.AndroidApkVersion;
|
||||
using CompanyManagment.Application.Helpers;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using _0_Framework.Application;
|
||||
|
||||
@@ -24,7 +22,7 @@ public class AndroidApkVersionApplication : IAndroidApkVersionApplication
|
||||
_taskRepository = taskRepository;
|
||||
}
|
||||
|
||||
public async Task<OperationResult> CreateAndActive(IFormFile file)
|
||||
public async Task<OperationResult> CreateAndActive(IFormFile file, ApkType apkType, bool isForce = false)
|
||||
{
|
||||
OperationResult op = new OperationResult();
|
||||
|
||||
@@ -38,21 +36,41 @@ public class AndroidApkVersionApplication : IAndroidApkVersionApplication
|
||||
|
||||
#endregion
|
||||
|
||||
var activeApks = _androidApkVersionRepository.GetActives();
|
||||
var activeApks = _androidApkVersionRepository.GetActives(apkType);
|
||||
|
||||
await activeApks.ExecuteUpdateAsync(setter => setter.SetProperty(e => e.IsActive, IsActive.False));
|
||||
_androidApkVersionRepository.SaveChanges();
|
||||
|
||||
var folderName = apkType == ApkType.WebView ? "GozreshgirWebView" : "GozreshgirFaceDetection";
|
||||
var path = Path.Combine($"{_taskRepository.GetWebEnvironmentPath()}", "Storage",
|
||||
"Apk", "Android", "GozreshgirWebView");
|
||||
"Apk", "Android", folderName);
|
||||
|
||||
Directory.CreateDirectory(path);
|
||||
|
||||
//var apk = new ApkReader.ApkReader().Read(file.OpenReadStream());
|
||||
|
||||
string uniqueFileName = $"{Path.GetFileNameWithoutExtension(file.FileName)}{Path.GetExtension(file.FileName)}";
|
||||
|
||||
// Read APK metadata with error handling
|
||||
ApkInfo apk;
|
||||
try
|
||||
{
|
||||
apk = ApkHelper.ReadApkInfo(file.OpenReadStream());
|
||||
|
||||
// Validate APK info
|
||||
if (string.IsNullOrEmpty(apk.VersionName) || string.IsNullOrEmpty(apk.VersionCode))
|
||||
{
|
||||
return op.Failed("فایل APK معتبر نیست - اطلاعات نسخه یافت نشد");
|
||||
}
|
||||
|
||||
// Validate version code is numeric
|
||||
if (!int.TryParse(apk.VersionCode, out _))
|
||||
{
|
||||
return op.Failed("فایل APK معتبر نیست - کد نسخه باید عددی باشد");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return op.Failed("خطا در خواندن فایل APK: " + ex.Message);
|
||||
}
|
||||
|
||||
string uniqueFileName = $"{Path.GetFileNameWithoutExtension(file.FileName)}.v{apk.VersionName}{Path.GetExtension(file.FileName)}";
|
||||
string filepath = Path.Combine(path, uniqueFileName);
|
||||
|
||||
await using (var stream = new FileStream(filepath, FileMode.Create))
|
||||
@@ -60,13 +78,13 @@ public class AndroidApkVersionApplication : IAndroidApkVersionApplication
|
||||
await file.CopyToAsync(stream);
|
||||
}
|
||||
|
||||
var entity = new AndroidApkVersion("0", "0", IsActive.True, filepath);
|
||||
var entity = new AndroidApkVersion(apk.VersionName, apk.VersionCode, IsActive.True, filepath, apkType, isForce);
|
||||
_androidApkVersionRepository.Create(entity);
|
||||
_androidApkVersionRepository.SaveChanges();
|
||||
return op.Succcedded();
|
||||
}
|
||||
|
||||
public async Task<OperationResult> CreateAndDeActive(IFormFile file)
|
||||
public async Task<OperationResult> CreateAndDeActive(IFormFile file, ApkType apkType, bool isForce = false)
|
||||
{
|
||||
OperationResult op = new OperationResult();
|
||||
|
||||
@@ -81,12 +99,34 @@ public class AndroidApkVersionApplication : IAndroidApkVersionApplication
|
||||
#endregion
|
||||
|
||||
|
||||
var folderName = apkType == ApkType.WebView ? "GozreshgirWebView" : "GozreshgirFaceDetection";
|
||||
var path = Path.Combine($"{_taskRepository.GetWebEnvironmentPath()}", "Storage",
|
||||
"Apk", "Android", "GozreshgirWebView");
|
||||
"Apk", "Android", folderName);
|
||||
|
||||
Directory.CreateDirectory(path);
|
||||
|
||||
var apk = new ApkReader.ApkReader().Read(file.OpenReadStream());
|
||||
// Read APK metadata with error handling
|
||||
ApkInfo apk;
|
||||
try
|
||||
{
|
||||
apk = ApkHelper.ReadApkInfo(file.OpenReadStream());
|
||||
|
||||
// Validate APK info
|
||||
if (string.IsNullOrEmpty(apk.VersionName) || string.IsNullOrEmpty(apk.VersionCode))
|
||||
{
|
||||
return op.Failed("فایل APK معتبر نیست - اطلاعات نسخه یافت نشد");
|
||||
}
|
||||
|
||||
// Validate version code is numeric
|
||||
if (!int.TryParse(apk.VersionCode, out _))
|
||||
{
|
||||
return op.Failed("فایل APK معتبر نیست - کد نسخه باید عددی باشد");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return op.Failed("خطا در خواندن فایل APK: " + ex.Message);
|
||||
}
|
||||
|
||||
string uniqueFileName = $"{Path.GetFileNameWithoutExtension(file.FileName)}.v{apk.VersionName}{Path.GetExtension(file.FileName)}";
|
||||
|
||||
@@ -98,14 +138,15 @@ public class AndroidApkVersionApplication : IAndroidApkVersionApplication
|
||||
await file.CopyToAsync(stream);
|
||||
}
|
||||
|
||||
var entity = new AndroidApkVersion(apk.VersionName, apk.VersionCode, IsActive.False, filepath);
|
||||
var entity = new AndroidApkVersion(apk.VersionName, apk.VersionCode, IsActive.False, filepath, apkType, isForce);
|
||||
_androidApkVersionRepository.Create(entity);
|
||||
_androidApkVersionRepository.SaveChanges();
|
||||
return op.Succcedded();
|
||||
}
|
||||
|
||||
public async Task<string> GetLatestActiveVersionPath()
|
||||
public async Task<string> GetLatestActiveVersionPath(ApkType apkType)
|
||||
{
|
||||
return await _androidApkVersionRepository.GetLatestActiveVersionPath();
|
||||
return await _androidApkVersionRepository.GetLatestActiveVersionPath(apkType);
|
||||
}
|
||||
|
||||
public OperationResult Remove(long id)
|
||||
@@ -127,8 +168,22 @@ public class AndroidApkVersionApplication : IAndroidApkVersionApplication
|
||||
return op.Succcedded();
|
||||
}
|
||||
|
||||
public bool HasAndroidApkToDownload()
|
||||
public bool HasAndroidApkToDownload(ApkType apkType)
|
||||
{
|
||||
return _androidApkVersionRepository.Exists(x => x.IsActive == IsActive.True);
|
||||
return _androidApkVersionRepository.Exists(x => x.IsActive == IsActive.True && x.ApkType == apkType);
|
||||
}
|
||||
|
||||
public Task<AndroidApkVersionInfo> GetLatestActiveInfo(ApkType apkType, int currentVersionCode)
|
||||
{
|
||||
var latest = _androidApkVersionRepository.GetLatestActive(apkType);
|
||||
if (latest == null)
|
||||
return Task.FromResult(new AndroidApkVersionInfo(0, "0", false, false, string.Empty, string.Empty));
|
||||
|
||||
// Return API endpoint for downloading APK file
|
||||
var fileUrl = $"/api/android-apk/download?type={apkType}";
|
||||
int latestCode = 0;
|
||||
int.TryParse(latest.VersionCode, out latestCode);
|
||||
var shouldUpdate = latestCode > currentVersionCode;
|
||||
return Task.FromResult(new AndroidApkVersionInfo(latestCode, latest.VersionName, shouldUpdate, latest.IsForce, fileUrl, "Bug fixes and improvements"));
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ApkReader" Version="2.0.1.1" />
|
||||
<PackageReference Include="AndroidXml" Version="1.1.24" />
|
||||
<PackageReference Include="System.IO.Compression.ZipFile" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,214 +0,0 @@
|
||||
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("خطا در حذف فاکتور");
|
||||
// }
|
||||
//}
|
||||
}
|
||||
132
CompanyManagment.Application/Helpers/ApkHelper.cs
Normal file
132
CompanyManagment.Application/Helpers/ApkHelper.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace CompanyManagment.Application.Helpers
|
||||
{
|
||||
public class ApkInfo
|
||||
{
|
||||
public string VersionName { get; set; } = string.Empty;
|
||||
public string VersionCode { get; set; } = string.Empty;
|
||||
public string PackageName { get; set; } = string.Empty;
|
||||
public string ApplicationLabel { get; set; } = string.Empty;
|
||||
}
|
||||
|
||||
public static class ApkHelper
|
||||
{
|
||||
public static ApkInfo ReadApkInfo(Stream apkStream)
|
||||
{
|
||||
var apkInfo = new ApkInfo();
|
||||
|
||||
try
|
||||
{
|
||||
using var archive = new ZipArchive(apkStream, ZipArchiveMode.Read, true);
|
||||
var manifestEntry = archive.GetEntry("AndroidManifest.xml");
|
||||
|
||||
if (manifestEntry == null)
|
||||
{
|
||||
throw new InvalidOperationException("AndroidManifest.xml not found in APK file");
|
||||
}
|
||||
|
||||
using var manifestStream = manifestEntry.Open();
|
||||
using var memoryStream = new MemoryStream();
|
||||
manifestStream.CopyTo(memoryStream);
|
||||
var manifestBytes = memoryStream.ToArray();
|
||||
|
||||
// Parse the binary AndroidManifest.xml
|
||||
apkInfo = ParseBinaryManifest(manifestBytes);
|
||||
|
||||
// Validate that we found at least version information
|
||||
if (string.IsNullOrEmpty(apkInfo.VersionCode) && string.IsNullOrEmpty(apkInfo.VersionName))
|
||||
{
|
||||
throw new InvalidOperationException("Could not extract version information from APK");
|
||||
}
|
||||
|
||||
return apkInfo;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new InvalidOperationException($"Error reading APK file: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static ApkInfo ParseBinaryManifest(byte[] manifestBytes)
|
||||
{
|
||||
var apkInfo = new ApkInfo();
|
||||
|
||||
try
|
||||
{
|
||||
// Convert bytes to string for regex parsing
|
||||
var text = System.Text.Encoding.UTF8.GetString(manifestBytes);
|
||||
|
||||
// Extract package name
|
||||
var packageMatch = Regex.Match(text, @"package[^a-zA-Z]+([a-zA-Z][a-zA-Z0-9_]*(?:\.[a-zA-Z][a-zA-Z0-9_]*)+)", RegexOptions.IgnoreCase);
|
||||
if (packageMatch.Success)
|
||||
{
|
||||
apkInfo.PackageName = packageMatch.Groups[1].Value;
|
||||
}
|
||||
|
||||
// Extract version code - look for numeric values that could be version codes
|
||||
var versionCodeMatch = Regex.Match(text, @"versionCode[^\d]*(\d+)", RegexOptions.IgnoreCase);
|
||||
if (versionCodeMatch.Success)
|
||||
{
|
||||
apkInfo.VersionCode = versionCodeMatch.Groups[1].Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback: try to find reasonable numeric values
|
||||
var numbers = Regex.Matches(text, @"\b(\d{1,8})\b");
|
||||
foreach (Match numMatch in numbers)
|
||||
{
|
||||
if (int.TryParse(numMatch.Groups[1].Value, out int num) && num > 0 && num < 99999999)
|
||||
{
|
||||
apkInfo.VersionCode = num.ToString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract version name
|
||||
var versionNameMatch = Regex.Match(text, @"versionName[^\d]*(\d+(?:\.\d+)*(?:\.\d+)*)", RegexOptions.IgnoreCase);
|
||||
if (versionNameMatch.Success)
|
||||
{
|
||||
apkInfo.VersionName = versionNameMatch.Groups[1].Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback: look for version-like patterns
|
||||
var versionMatch = Regex.Match(text, @"\b(\d+\.\d+(?:\.\d+)*)\b");
|
||||
if (versionMatch.Success)
|
||||
{
|
||||
apkInfo.VersionName = versionMatch.Groups[1].Value;
|
||||
}
|
||||
}
|
||||
|
||||
// Set defaults if nothing found
|
||||
if (string.IsNullOrEmpty(apkInfo.VersionCode))
|
||||
apkInfo.VersionCode = "1";
|
||||
|
||||
if (string.IsNullOrEmpty(apkInfo.VersionName))
|
||||
apkInfo.VersionName = "1.0";
|
||||
|
||||
if (string.IsNullOrEmpty(apkInfo.PackageName))
|
||||
apkInfo.PackageName = "unknown.package";
|
||||
|
||||
return apkInfo;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Return default values if parsing fails
|
||||
return new ApkInfo
|
||||
{
|
||||
VersionCode = "1",
|
||||
VersionName = "1.0",
|
||||
PackageName = "unknown.package"
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,10 @@
|
||||
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;
|
||||
@@ -15,20 +13,16 @@ 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;
|
||||
@@ -56,9 +50,6 @@ 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,
|
||||
@@ -68,8 +59,7 @@ public class InstitutionContractApplication : IInstitutionContractApplication
|
||||
IFinancialStatmentApplication financialStatmentApplication, IWorkshopApplication workshopApplication,
|
||||
IContractingPartyTempRepository contractingPartyTempRepository,
|
||||
IFinancialStatmentRepository financialStatmentRepository, IContactInfoApplication contactInfoApplication,
|
||||
IAccountApplication accountApplication, ISmsService smsService, IUidService uidService,
|
||||
IFinancialInvoiceRepository financialInvoiceRepository,IHttpClientFactory httpClientFactory, IPaymentTransactionRepository paymentTransactionRepository)
|
||||
IAccountApplication accountApplication, ISmsService smsService, IUidService uidService)
|
||||
{
|
||||
_institutionContractRepository = institutionContractRepository;
|
||||
_contractingPartyRepository = contractingPartyRepository;
|
||||
@@ -85,9 +75,6 @@ public class InstitutionContractApplication : IInstitutionContractApplication
|
||||
_accountApplication = accountApplication;
|
||||
_smsService = smsService;
|
||||
_uidService = uidService;
|
||||
_financialInvoiceRepository = financialInvoiceRepository;
|
||||
_paymentTransactionRepository = paymentTransactionRepository;
|
||||
_paymentGateway = new SepehrPaymentGateway(httpClientFactory);
|
||||
}
|
||||
|
||||
public OperationResult Create(CreateInstitutionContract command)
|
||||
@@ -1073,16 +1060,11 @@ public class InstitutionContractApplication : IInstitutionContractApplication
|
||||
await _financialStatmentRepository.CreateAsync(financialStatement);
|
||||
}
|
||||
|
||||
double invoiceAmount;
|
||||
string invoiceItemDescription;
|
||||
FinancialInvoiceItemType invoiceItemType;
|
||||
long invoiceItemEntityId;
|
||||
if (command.IsInstallment)
|
||||
if (command.IsInstallment)
|
||||
{
|
||||
var installments =
|
||||
CalculateInstallment(command.TotalAmount, (int)command.Duration, command.ContractStartFa, true);
|
||||
|
||||
|
||||
// دریافت مبلغ اولین قسط
|
||||
//این کار برای این هست که اولین قسط باید با تاریخ امروز باشد و باید به وضعیت مالی بدهی ایجاد شود که یوزر اولین بدهی را وارد کند
|
||||
var firstInstallmentAmount = installments.First().Amount;
|
||||
@@ -1093,41 +1075,25 @@ 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 _financialInvoiceRepository.CreateAsync(financialInvoice);
|
||||
await _institutionContractRepository.CreateAsync(entity);
|
||||
await _institutionContractRepository.CreateAsync(entity);
|
||||
await _institutionContractRepository.SaveChangesAsync();
|
||||
|
||||
var mainContactInfo = new CreateContactInfo
|
||||
@@ -1266,9 +1232,9 @@ public class InstitutionContractApplication : IInstitutionContractApplication
|
||||
return new OperationResult<OtpResultViewModel>().Succcedded(result);
|
||||
}
|
||||
|
||||
public async Task<OperationResult<string>> VerifyOtpAndMakeGateway(Guid publicId, string code,string callbackUrl)
|
||||
public async Task<OperationResult> VerifyOtp(Guid publicId, string code)
|
||||
{
|
||||
var op = new OperationResult<string>();
|
||||
var op = new OperationResult();
|
||||
var institutionContract = await _institutionContractRepository.GetByPublicIdAsync(publicId);
|
||||
if (institutionContract == null)
|
||||
{
|
||||
@@ -1289,67 +1255,32 @@ public class InstitutionContractApplication : IInstitutionContractApplication
|
||||
if (institutionContract.VerifyCode != code)
|
||||
return op.Failed("کد وارد شده صحیح نمی باشد");
|
||||
|
||||
var dbTransaction = await _institutionContractRepository.BeginTransactionAsync();
|
||||
var transaction = await _institutionContractRepository.BeginTransactionAsync();
|
||||
institutionContract.SetPendingWorkflow();
|
||||
|
||||
long entityId = 0;
|
||||
FinancialInvoiceItemType financialInvoiceItemType;
|
||||
if (institutionContract.IsInstallment)
|
||||
var phone = institutionContract.ContactInfoList.FirstOrDefault(x =>
|
||||
x.SendSms && x.Position == "طرف قرارداد" && x.PhoneType == "شماره همراه");
|
||||
if (phone !=null)
|
||||
{
|
||||
entityId = institutionContract.Installments.MinBy(x => x.InstallmentDateGr).Id;
|
||||
financialInvoiceItemType = FinancialInvoiceItemType.BuyInstitutionContractInstallment;
|
||||
}
|
||||
else
|
||||
{
|
||||
entityId = institutionContract.id;
|
||||
financialInvoiceItemType = FinancialInvoiceItemType.BuyInstitutionContract;
|
||||
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);
|
||||
}
|
||||
|
||||
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 transaction.CommitAsync();
|
||||
await _institutionContractRepository.SaveChangesAsync();
|
||||
return op.Succcedded(gatewayResponse.Token);
|
||||
return op.Succcedded();
|
||||
}
|
||||
|
||||
public async Task<InstitutionContractWorkshopDetailViewModel> GetWorkshopInitialDetails(long workshopDetailsId)
|
||||
@@ -1456,24 +1387,6 @@ 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,
|
||||
|
||||
@@ -45,7 +45,6 @@ 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;
|
||||
@@ -205,13 +204,12 @@ public class CompanyContext : DbContext
|
||||
|
||||
public DbSet<AuthorizedBankDetails> AuthorizedBankDetails { get; set; }
|
||||
|
||||
public DbSet<FinancialInvoice> FinancialInvoices { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
#region Pooya
|
||||
|
||||
#region Pooya
|
||||
|
||||
public DbSet<EmployeeDocumentItem> EmployeeDocumentItems { get; set; }
|
||||
public DbSet<EmployeeDocumentItem> EmployeeDocumentItems { get; set; }
|
||||
public DbSet<EmployeeDocuments> EmployeeDocuments { get; set; }
|
||||
|
||||
public DbSet<WorkshopSubAccount> WorkshopSubAccounts { get; set; }
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
|
||||
using Company.Domain.AndroidApkVersionAgg;
|
||||
using Company.Domain.AndroidApkVersionAgg;
|
||||
using CompanyManagment.App.Contracts.AndroidApkVersion;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Hosting.Builder;
|
||||
using _0_Framework.Application;
|
||||
|
||||
namespace CompanyManagment.EFCore.Mapping;
|
||||
@@ -19,10 +18,15 @@ public class AndroidApkVersionMapping:IEntityTypeConfiguration<AndroidApkVersion
|
||||
v => v.ToString(),
|
||||
v => (IsActive)Enum.Parse(typeof(IsActive), v)).HasMaxLength(5);
|
||||
|
||||
builder.Property(x => x.ApkType).HasConversion(
|
||||
v => v.ToString(),
|
||||
v => (ApkType)Enum.Parse(typeof(ApkType), v)).HasMaxLength(20);
|
||||
|
||||
builder.Property(x => x.Title).HasMaxLength(50);
|
||||
builder.Property(x => x.VersionCode).HasMaxLength(20);
|
||||
builder.Property(x => x.VersionName).HasMaxLength(35);
|
||||
builder.Property(x => x.Path).HasMaxLength(255);
|
||||
builder.Property(x => x.IsForce);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
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);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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(100);
|
||||
builder.Property(x => x.DescriptionOption).HasMaxLength(50);
|
||||
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
@@ -1,52 +0,0 @@
|
||||
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
@@ -1,226 +0,0 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
namespace CompanyManagment.EFCore.Migrations
|
||||
{
|
||||
[DbContext(typeof(CompanyContext))]
|
||||
[Migration("20251117163856_change descriptionOption max length")]
|
||||
partial class changedescriptionOptionmaxlength
|
||||
[Migration("20251115161128_AddApkTypeToAndroidApkVersion")]
|
||||
partial class AddApkTypeToAndroidApkVersion
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
@@ -64,6 +64,11 @@ namespace CompanyManagment.EFCore.Migrations
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("id"));
|
||||
|
||||
b.Property<string>("ApkType")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("nvarchar(20)");
|
||||
|
||||
b.Property<DateTime>("CreationDate")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
@@ -2830,86 +2835,6 @@ 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")
|
||||
@@ -2961,8 +2886,8 @@ namespace CompanyManagment.EFCore.Migrations
|
||||
.HasColumnType("nvarchar(600)");
|
||||
|
||||
b.Property<string>("DescriptionOption")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("nvarchar(50)");
|
||||
|
||||
b.Property<long>("FinancialStatementId")
|
||||
.HasColumnType("bigint");
|
||||
@@ -5077,9 +5002,6 @@ namespace CompanyManagment.EFCore.Migrations
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("nvarchar(50)");
|
||||
|
||||
b.Property<long?>("FinancialInvoiceId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Gateway")
|
||||
.IsRequired()
|
||||
.HasMaxLength(35)
|
||||
@@ -5103,8 +5025,6 @@ namespace CompanyManagment.EFCore.Migrations
|
||||
|
||||
b.HasKey("id");
|
||||
|
||||
b.HasIndex("FinancialInvoiceId");
|
||||
|
||||
b.ToTable("PaymentTransactions", (string)null);
|
||||
});
|
||||
|
||||
@@ -10038,17 +9958,6 @@ 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")
|
||||
@@ -10596,16 +10505,6 @@ 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")
|
||||
@@ -11010,13 +10909,6 @@ 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");
|
||||
@@ -0,0 +1,30 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace CompanyManagment.EFCore.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddApkTypeToAndroidApkVersion : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "ApkType",
|
||||
table: "AndroidApkVersions",
|
||||
type: "nvarchar(20)",
|
||||
maxLength: 20,
|
||||
nullable: false,
|
||||
defaultValue: "");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ApkType",
|
||||
table: "AndroidApkVersions");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,8 +13,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
namespace CompanyManagment.EFCore.Migrations
|
||||
{
|
||||
[DbContext(typeof(CompanyContext))]
|
||||
[Migration("20251117140111_add invoice number")]
|
||||
partial class addinvoicenumber
|
||||
[Migration("20251116081057_AddIsForceFieldToAndroidApkVersions")]
|
||||
partial class AddIsForceFieldToAndroidApkVersions
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
@@ -64,6 +64,11 @@ namespace CompanyManagment.EFCore.Migrations
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("id"));
|
||||
|
||||
b.Property<string>("ApkType")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("nvarchar(20)");
|
||||
|
||||
b.Property<DateTime>("CreationDate")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
@@ -72,6 +77,9 @@ namespace CompanyManagment.EFCore.Migrations
|
||||
.HasMaxLength(5)
|
||||
.HasColumnType("nvarchar(5)");
|
||||
|
||||
b.Property<bool>("IsForce")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("Path")
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("nvarchar(255)");
|
||||
@@ -2830,86 +2838,6 @@ 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(18)
|
||||
.HasColumnType("nvarchar(18)");
|
||||
|
||||
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")
|
||||
@@ -5077,9 +5005,6 @@ namespace CompanyManagment.EFCore.Migrations
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("nvarchar(50)");
|
||||
|
||||
b.Property<long?>("FinancialInvoiceId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Gateway")
|
||||
.IsRequired()
|
||||
.HasMaxLength(35)
|
||||
@@ -5103,8 +5028,6 @@ namespace CompanyManagment.EFCore.Migrations
|
||||
|
||||
b.HasKey("id");
|
||||
|
||||
b.HasIndex("FinancialInvoiceId");
|
||||
|
||||
b.ToTable("PaymentTransactions", (string)null);
|
||||
});
|
||||
|
||||
@@ -10038,17 +9961,6 @@ 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")
|
||||
@@ -10596,16 +10508,6 @@ 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")
|
||||
@@ -11010,13 +10912,6 @@ 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");
|
||||
@@ -0,0 +1,29 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace CompanyManagment.EFCore.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddIsForceFieldToAndroidApkVersions : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsForce",
|
||||
table: "AndroidApkVersions",
|
||||
type: "bit",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsForce",
|
||||
table: "AndroidApkVersions");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,40 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -61,6 +61,11 @@ namespace CompanyManagment.EFCore.Migrations
|
||||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("id"));
|
||||
|
||||
b.Property<string>("ApkType")
|
||||
.IsRequired()
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("nvarchar(20)");
|
||||
|
||||
b.Property<DateTime>("CreationDate")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
@@ -69,6 +74,9 @@ namespace CompanyManagment.EFCore.Migrations
|
||||
.HasMaxLength(5)
|
||||
.HasColumnType("nvarchar(5)");
|
||||
|
||||
b.Property<bool>("IsForce")
|
||||
.HasColumnType("bit");
|
||||
|
||||
b.Property<string>("Path")
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("nvarchar(255)");
|
||||
@@ -2827,86 +2835,6 @@ 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")
|
||||
@@ -2958,8 +2886,8 @@ namespace CompanyManagment.EFCore.Migrations
|
||||
.HasColumnType("nvarchar(600)");
|
||||
|
||||
b.Property<string>("DescriptionOption")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("nvarchar(100)");
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("nvarchar(50)");
|
||||
|
||||
b.Property<long>("FinancialStatementId")
|
||||
.HasColumnType("bigint");
|
||||
@@ -5074,9 +5002,6 @@ namespace CompanyManagment.EFCore.Migrations
|
||||
.HasMaxLength(50)
|
||||
.HasColumnType("nvarchar(50)");
|
||||
|
||||
b.Property<long?>("FinancialInvoiceId")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<string>("Gateway")
|
||||
.IsRequired()
|
||||
.HasMaxLength(35)
|
||||
@@ -5100,8 +5025,6 @@ namespace CompanyManagment.EFCore.Migrations
|
||||
|
||||
b.HasKey("id");
|
||||
|
||||
b.HasIndex("FinancialInvoiceId");
|
||||
|
||||
b.ToTable("PaymentTransactions", (string)null);
|
||||
});
|
||||
|
||||
@@ -10035,17 +9958,6 @@ 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")
|
||||
@@ -10593,16 +10505,6 @@ 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")
|
||||
@@ -11007,13 +10909,6 @@ 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");
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Threading.Tasks;
|
||||
using _0_Framework.Application;
|
||||
using _0_Framework.InfraStructure;
|
||||
using Company.Domain.AndroidApkVersionAgg;
|
||||
using CompanyManagment.App.Contracts.AndroidApkVersion;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace CompanyManagment.EFCore.Repository;
|
||||
@@ -15,13 +16,21 @@ public class AndroidApkVersionRepository:RepositoryBase<long, AndroidApkVersion>
|
||||
_companyContext = companyContext;
|
||||
}
|
||||
|
||||
public IQueryable<AndroidApkVersion> GetActives()
|
||||
public IQueryable<AndroidApkVersion> GetActives(ApkType apkType)
|
||||
{
|
||||
return _companyContext.AndroidApkVersions.Where(x => x.IsActive == IsActive.True);
|
||||
return _companyContext.AndroidApkVersions.Where(x => x.IsActive == IsActive.True && x.ApkType == apkType);
|
||||
}
|
||||
|
||||
public async Task<string> GetLatestActiveVersionPath()
|
||||
public async Task<string> GetLatestActiveVersionPath(ApkType apkType)
|
||||
{
|
||||
return (await _companyContext.AndroidApkVersions.OrderByDescending(x=>x.CreationDate).FirstOrDefaultAsync(x => x.IsActive == IsActive.True)).Path;
|
||||
return (await _companyContext.AndroidApkVersions.OrderByDescending(x=>x.CreationDate).FirstOrDefaultAsync(x => x.IsActive == IsActive.True && x.ApkType == apkType)).Path;
|
||||
}
|
||||
|
||||
public AndroidApkVersion GetLatestActive(ApkType apkType)
|
||||
{
|
||||
return _companyContext.AndroidApkVersions
|
||||
.Where(x => x.IsActive == IsActive.True && x.ApkType == apkType)
|
||||
.OrderByDescending(x => x.CreationDate)
|
||||
.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -265,21 +265,7 @@ public class FinancialStatmentRepository : RepositoryBase<long, FinancialStatmen
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
public async Task<FinancialStatmentDetailsByContractingPartyViewModel> GetDetailsByContractingParty(long contractingPartyId,FinancialStatementSearchModel searchModel)
|
||||
{
|
||||
var contractingParty = await _context.PersonalContractingParties
|
||||
.FirstOrDefaultAsync(x=>x.id == contractingPartyId);
|
||||
@@ -427,6 +413,6 @@ public class FinancialStatmentRepository : RepositoryBase<long, FinancialStatmen
|
||||
|
||||
public async Task<FinancialStatment> GetByContractingPartyId(long contractingPartyId)
|
||||
{
|
||||
return await _context.FinancialStatments.Include(x=>x.FinancialTransactionList).FirstOrDefaultAsync(x => x.ContractingPartyId == contractingPartyId);
|
||||
return await _context.FinancialStatments.FirstOrDefaultAsync(x => x.ContractingPartyId == contractingPartyId);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,6 @@ 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;
|
||||
@@ -24,7 +23,6 @@ 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;
|
||||
@@ -1841,10 +1839,7 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
|
||||
|
||||
public async Task<InstitutionContract> GetByPublicIdAsync(Guid id)
|
||||
{
|
||||
return await _context.InstitutionContractSet
|
||||
.Include(x=>x.ContactInfoList)
|
||||
.Include(x=>x.Installments)
|
||||
.FirstOrDefaultAsync(x => x.PublicId == id);
|
||||
return await _context.InstitutionContractSet.Include(x=>x.ContactInfoList).FirstOrDefaultAsync(x => x.PublicId == id);
|
||||
}
|
||||
|
||||
#region Extension
|
||||
@@ -2300,10 +2295,6 @@ 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 =>
|
||||
@@ -2320,40 +2311,23 @@ 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)
|
||||
|
||||
@@ -214,7 +214,6 @@ 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;
|
||||
@@ -229,7 +228,6 @@ using CompanyManagement.Infrastructure.Mongo.InstitutionContractInsertTempRepo;
|
||||
using CompanyManagment.App.Contracts.EmployeeFaceEmbedding;
|
||||
using CompanyManagment.App.Contracts.Law;
|
||||
using CompanyManagment.EFCore.Repository;
|
||||
using CompanyManagment.App.Contracts.FinancialInvoice;
|
||||
|
||||
namespace PersonalContractingParty.Config;
|
||||
|
||||
@@ -483,14 +481,11 @@ 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
|
||||
|
||||
61
ServiceHost/Areas/Admin/Controllers/AndroidApkController.cs
Normal file
61
ServiceHost/Areas/Admin/Controllers/AndroidApkController.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
|
||||
using CompanyManagment.App.Contracts.AndroidApkVersion;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using ServiceHost.BaseControllers;
|
||||
|
||||
namespace ServiceHost.Areas.Admin.Controllers;
|
||||
|
||||
[AllowAnonymous]
|
||||
[ApiController]
|
||||
[Route("api/android-apk")]
|
||||
public class AndroidApkController:AdminBaseController
|
||||
{
|
||||
private readonly IAndroidApkVersionApplication _apkApp;
|
||||
public AndroidApkController(IAndroidApkVersionApplication apkApp)
|
||||
{
|
||||
_apkApp = apkApp;
|
||||
}
|
||||
|
||||
[HttpGet("check-update")]
|
||||
public async Task<IActionResult> CheckUpdate([FromQuery] ApkType type, [FromQuery] int currentVersionCode = 0)
|
||||
{
|
||||
|
||||
var info = await _apkApp.GetLatestActiveInfo(type, currentVersionCode);
|
||||
return Ok(new
|
||||
{
|
||||
latestVersionCode = info.LatestVersionCode,
|
||||
latestVersionName = info.LatestVersionName,
|
||||
shouldUpdate = info.ShouldUpdate,
|
||||
isForceUpdate = info.IsForceUpdate,
|
||||
downloadUrl = info.DownloadUrl,
|
||||
releaseNotes = info.ReleaseNotes
|
||||
});
|
||||
}
|
||||
|
||||
[HttpGet("download")]
|
||||
public async Task<IActionResult> Download([FromQuery] ApkType type)
|
||||
{
|
||||
// Check if APK exists
|
||||
if (!_apkApp.HasAndroidApkToDownload(type))
|
||||
{
|
||||
return NotFound(new { message = $"هیچ فایل APK فعالی برای {type} یافت نشد" });
|
||||
}
|
||||
|
||||
// Get the path to the latest active APK
|
||||
var path = await _apkApp.GetLatestActiveVersionPath(type);
|
||||
|
||||
if (string.IsNullOrEmpty(path) || !System.IO.File.Exists(path))
|
||||
{
|
||||
return NotFound(new { message = "فایل APK یافت نشد" });
|
||||
}
|
||||
|
||||
// Set appropriate file name for download
|
||||
var fileName = type == ApkType.WebView
|
||||
? "Gozareshgir.apk"
|
||||
: "Gozareshgir-FaceDetection.apk";
|
||||
|
||||
// Return the file for download
|
||||
return PhysicalFile(path, "application/vnd.android.package-archive", fileName);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -38,8 +37,6 @@ 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>();
|
||||
|
||||
@@ -48,8 +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)
|
||||
IWorkshopApplication workshopApplication, ITemporaryClientRegistrationApplication temporaryClientRegistration, ITemporaryClientRegistrationApplication clientRegistrationApplication)
|
||||
{
|
||||
_institutionContractApplication = institutionContractApplication;
|
||||
_contractingPartyApplication = contractingPartyApplication;
|
||||
@@ -59,7 +55,6 @@ public class institutionContractController : AdminBaseController
|
||||
_workshopApplication = workshopApplication;
|
||||
_temporaryClientRegistration = temporaryClientRegistration;
|
||||
_clientRegistrationApplication = clientRegistrationApplication;
|
||||
_paymentGateway = new SepehrPaymentGateway(httpClientFactory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -467,37 +462,11 @@ public class institutionContractController : AdminBaseController
|
||||
|
||||
[HttpPost("/api/institutionContract/Verify")]
|
||||
[AllowAnonymous]
|
||||
public async Task<ActionResult<OperationResult<string>>> Verify([FromBody] InstitutionVerificationRequest command)
|
||||
public async Task<ActionResult<OperationResult>> Verify([FromBody] InstitutionVerificationRequest command)
|
||||
{
|
||||
// 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);
|
||||
var res = await _institutionContractApplication.VerifyOtp(command.Id, command.Code);
|
||||
return res;
|
||||
}
|
||||
|
||||
[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]
|
||||
|
||||
@@ -10,7 +10,17 @@
|
||||
<label asp-for="File">Choose a file:</label>
|
||||
<input asp-for="File" type="file" required>
|
||||
</div>
|
||||
<button type="submit">Upload</button>
|
||||
<div style="margin-top:12px;">
|
||||
<label asp-for="SelectedApkType">نوع اپلیکیشن:</label>
|
||||
<select asp-for="SelectedApkType" asp-items="Html.GetEnumSelectList<CompanyManagment.App.Contracts.AndroidApkVersion.ApkType>()"></select>
|
||||
</div>
|
||||
<div style="margin-top:12px;">
|
||||
<label asp-for="IsForce">
|
||||
<input asp-for="IsForce" type="checkbox">
|
||||
آپدیت اجباری (Force Update)
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit" style="margin-top:12px;">Upload</button>
|
||||
</form>
|
||||
|
||||
<form asp-page-handler="ShiftDate" id="8" method="post">
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using _0_Framework.Domain.CustomizeCheckoutShared.Enums;
|
||||
using AccountManagement.Domain.AccountLeftWorkAgg;
|
||||
using AccountMangement.Infrastructure.EFCore;
|
||||
using Company.Domain.AndroidApkVersionAgg;
|
||||
using Company.Domain.CustomizeCheckoutAgg.ValueObjects;
|
||||
using Company.Domain.CustomizeCheckoutTempAgg.ValueObjects;
|
||||
using Company.Domain.RewardAgg;
|
||||
@@ -45,6 +46,8 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk
|
||||
|
||||
|
||||
[BindProperty] public IFormFile File { get; set; }
|
||||
[BindProperty] public ApkType SelectedApkType { get; set; }
|
||||
[BindProperty] public bool IsForce { get; set; }
|
||||
|
||||
public IndexModel(IAndroidApkVersionApplication application, IRollCallDomainService rollCallDomainService,
|
||||
CompanyContext context, AccountContext accountContext, IHttpClientFactory httpClientFactory,
|
||||
@@ -67,7 +70,7 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk
|
||||
|
||||
public async Task<IActionResult> OnPostUpload()
|
||||
{
|
||||
var result = await _application.CreateAndActive(File);
|
||||
var result = await _application.CreateAndActive(File, SelectedApkType, IsForce);
|
||||
ViewData["message"] = result.Message;
|
||||
return Page();
|
||||
}
|
||||
@@ -93,9 +96,9 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk
|
||||
_context.PaymentTransactions.Add(transaction);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var command = new CreatePaymentGatewayRequest()
|
||||
var command = new CreatePaymentGatewayRequest()
|
||||
{
|
||||
TransactionId = transaction.id.ToString(),
|
||||
InvoiceId = transaction.id.ToString(),
|
||||
Amount = amount,
|
||||
CallBackUrl = callBack
|
||||
};
|
||||
@@ -104,10 +107,7 @@ namespace ServiceHost.Areas.AdminNew.Pages.Company.AndroidApk
|
||||
|
||||
if (createRes.IsSuccess)
|
||||
{
|
||||
transaction.SetTransactionId(createRes.Token);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
var payUrl = _paymentGateway.GetStartPayUrl(createRes.Token);
|
||||
var payUrl = _paymentGateway.GetStartPayUrl(createRes.Token);
|
||||
return Redirect(payUrl);
|
||||
}
|
||||
else
|
||||
@@ -240,7 +240,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),
|
||||
TransactionId = "{C771E841-B810-413D-9D4C-9F659575B8CC}",
|
||||
InvoiceId = "{C771E841-B810-413D-9D4C-9F659575B8CC}",
|
||||
};
|
||||
var createResponse = await _paymentGateway.Create(command, cancellationToken);
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ using _0_Framework.Exceptions;
|
||||
using AccountManagement.Application.Contracts.Account;
|
||||
using AccountManagement.Application.Contracts.CameraAccount;
|
||||
using AccountManagement.Domain.TaskAgg;
|
||||
using CompanyManagment.App.Contracts.AndroidApkVersion;
|
||||
using CompanyManagment.App.Contracts.PersonnleCode;
|
||||
using CompanyManagment.App.Contracts.RollCall;
|
||||
using CompanyManagment.App.Contracts.RollCallEmployee;
|
||||
@@ -36,6 +37,7 @@ public class CameraController : CameraBaseController
|
||||
private long _workshopId;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
private readonly HttpClient _faceEmbeddingHttpClient;
|
||||
private readonly IAndroidApkVersionApplication _androidApkVersionApplication;
|
||||
|
||||
public CameraController(IWebHostEnvironment webHostEnvironment,
|
||||
IConfiguration configuration,
|
||||
@@ -48,7 +50,7 @@ public class CameraController : CameraBaseController
|
||||
IAccountApplication accountApplication,
|
||||
IPasswordHasher passwordHasher,
|
||||
ICameraAccountApplication cameraAccountApplication,
|
||||
IEmployeeFaceEmbeddingApplication employeeFaceEmbeddingApplication, IHttpClientFactory httpClientFactory)
|
||||
IEmployeeFaceEmbeddingApplication employeeFaceEmbeddingApplication, IHttpClientFactory httpClientFactory, IAndroidApkVersionApplication androidApkVersionApplication)
|
||||
{
|
||||
_webHostEnvironment = webHostEnvironment;
|
||||
_configuration = configuration;
|
||||
@@ -63,6 +65,7 @@ public class CameraController : CameraBaseController
|
||||
_cameraAccountApplication = cameraAccountApplication;
|
||||
_employeeFaceEmbeddingApplication = employeeFaceEmbeddingApplication;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_androidApkVersionApplication = androidApkVersionApplication;
|
||||
_faceEmbeddingHttpClient = httpClientFactory.CreateClient();
|
||||
_faceEmbeddingHttpClient.BaseAddress = new Uri("http://localhost:8000/");
|
||||
_workshopId= authHelper.GetWorkshopId();
|
||||
@@ -214,6 +217,50 @@ public class CameraController : CameraBaseController
|
||||
}
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpGet("check-update")]
|
||||
public async Task<IActionResult> CheckUpdate([FromQuery] ApkType type, [FromQuery] int currentVersionCode = 0)
|
||||
{
|
||||
|
||||
var info = await _androidApkVersionApplication.GetLatestActiveInfo(type, currentVersionCode);
|
||||
return Ok(new
|
||||
{
|
||||
latestVersionCode = 6000,
|
||||
latestVersionName = "2.0.0",
|
||||
shouldUpdate = info.ShouldUpdate,
|
||||
isForceUpdate = info.IsForceUpdate,
|
||||
downloadUrl = info.DownloadUrl,
|
||||
releaseNotes = info.ReleaseNotes
|
||||
});
|
||||
}
|
||||
|
||||
[AllowAnonymous]
|
||||
[HttpGet("download")]
|
||||
public async Task<IActionResult> Download([FromQuery] ApkType type)
|
||||
{
|
||||
// Check if APK exists
|
||||
if (!_androidApkVersionApplication.HasAndroidApkToDownload(type))
|
||||
{
|
||||
return NotFound(new { message = $"هیچ فایل APK فعالی برای {type} یافت نشد" });
|
||||
}
|
||||
|
||||
// Get the path to the latest active APK
|
||||
var path = await _androidApkVersionApplication.GetLatestActiveVersionPath(type);
|
||||
|
||||
if (string.IsNullOrEmpty(path) || !System.IO.File.Exists(path))
|
||||
{
|
||||
return NotFound(new { message = "فایل APK یافت نشد" });
|
||||
}
|
||||
|
||||
// Set appropriate file name for download
|
||||
var fileName = type == ApkType.WebView
|
||||
? "Gozareshgir.apk"
|
||||
: "Gozareshgir-FaceDetection.apk";
|
||||
|
||||
// Return the file for download
|
||||
return PhysicalFile(path, "application/vnd.android.package-archive", fileName);
|
||||
}
|
||||
|
||||
|
||||
[HttpGet("SendPersonelCodeToGetEmployeeId")]
|
||||
public IActionResult SendPersonelCodeToGetEmployeeId(long personelCode, long workshopId)
|
||||
|
||||
@@ -86,7 +86,7 @@ public class FinancialController : ClientBaseController
|
||||
{
|
||||
CallBackUrl = callbackUrl,
|
||||
Amount = balanceAmount.Amount/10,
|
||||
TransactionId = transaction.SendId.ToString(),
|
||||
InvoiceId = transaction.SendId.ToString(),
|
||||
};
|
||||
|
||||
var gatewayResponse = await _paymentGateway.Create(command, cancellationToken);
|
||||
|
||||
@@ -65,6 +65,7 @@ namespace ServiceHost.Areas.Client.Pages
|
||||
#region Mahan
|
||||
public bool HasInsuranceToConfirm { get; set; }
|
||||
public bool HasApkToDownload { get; set; }
|
||||
public bool HasFaceDetectionApkToDownload { get; set; }
|
||||
|
||||
#endregion
|
||||
public IndexModel(IAuthHelper authHelper, IPasswordHasher passwordHasher, IWorkshopApplication workshopApplication, ILeaveApplication leaveApplication, IEmployeeApplication employeeApplication, IPaymentToEmployeeItemApplication paymentToEmployeeItemApplication, IPaymentToEmployeeApplication paymentToEmployeeApplication, IHolidayItemApplication holidayItemApplication, IInsuranceListApplication insuranceListApplication, IAndroidApkVersionApplication androidApkVersionApplication, IRollCallServiceApplication rollCallServiceApplication, IPersonnelCodeApplication personnelCodeApplication, ICustomizeWorkshopSettingsApplication customizeWorkshopSettingsApplication, IBankApplication bankApplication, ILeftWorkTempApplication leftWorkTempApplication, IJobApplication jobApplication, ICustomizeWorkshopSettingsApplication customizeWorkshopEmployee, IRollCallEmployeeStatusApplication rollCallEmployeeStatusApplication, ICameraAccountApplication cameraAccountApplication)
|
||||
@@ -100,7 +101,8 @@ namespace ServiceHost.Areas.Client.Pages
|
||||
profilePicture = account.ProfilePhoto;
|
||||
AccountFullName = account.Fullname;
|
||||
var todayGr = DateTime.Now;
|
||||
HasApkToDownload = _androidApkVersionApplication.HasAndroidApkToDownload();
|
||||
HasApkToDownload = _androidApkVersionApplication.HasAndroidApkToDownload(ApkType.WebView);
|
||||
HasFaceDetectionApkToDownload = _androidApkVersionApplication.HasAndroidApkToDownload(ApkType.FaceDetection);
|
||||
|
||||
|
||||
#region Mahan
|
||||
|
||||
@@ -19,29 +19,23 @@ 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 IFinancialInvoiceApplication _financialInvoiceApplication;
|
||||
private readonly IInstitutionContractApplication _institutionContractApplication;
|
||||
private readonly IOnlinePayment _onlinePayment;
|
||||
|
||||
public GeneralController(IPaymentTransactionApplication paymentTransactionApplication,
|
||||
IHttpClientFactory clientFactory, IFinancialStatmentApplication financialStatmentApplication,
|
||||
IFinancialInvoiceApplication financialInvoiceApplication,
|
||||
IInstitutionContractApplication institutionContractApplication)
|
||||
public GeneralController(IPaymentTransactionApplication paymentTransactionApplication,IHttpClientFactory clientFactory, IFinancialStatmentApplication financialStatmentApplication, IOptions<AppSettingConfiguration> appSetting, IOnlinePayment onlinePayment)
|
||||
{
|
||||
_paymentTransactionApplication = paymentTransactionApplication;
|
||||
_paymentGateway = new SepehrPaymentGateway(clientFactory);
|
||||
_financialStatmentApplication = financialStatmentApplication;
|
||||
_financialInvoiceApplication = financialInvoiceApplication;
|
||||
_institutionContractApplication = institutionContractApplication;
|
||||
_onlinePayment = onlinePayment;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -69,135 +63,101 @@ 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 (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 (payResponse.respcode != 0)
|
||||
{
|
||||
return await HandleFailedTransaction(transaction);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 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 financialInvoice = _financialInvoiceApplication.GetDetails(financialInvoiceId);
|
||||
//var data = JsonConvert.SerializeObject(invoice.AdditionalData);
|
||||
//var statics =
|
||||
//JsonConvert.SerializeObject(res);
|
||||
|
||||
if (financialInvoice == null)
|
||||
{
|
||||
return BadRequest("فاکتور مالی نامعتبر است");
|
||||
}
|
||||
//await _onlinePayment.CancelAsync(invoice);
|
||||
//return new JsonResult(new
|
||||
//{
|
||||
// data,
|
||||
// statics
|
||||
//});
|
||||
|
||||
if (financialInvoice.Status != FinancialInvoiceStatus.Unpaid)
|
||||
{
|
||||
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.Amount != transaction.Amount)
|
||||
{
|
||||
return await HandleFailedTransaction(transaction);
|
||||
}
|
||||
// return Content("The payment was not successful.");
|
||||
//}
|
||||
|
||||
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);
|
||||
//// Note: Save the verifyResult.TransactionCode in your database.
|
||||
|
||||
|
||||
//var data = JsonConvert.SerializeObject(invoice.AdditionalData);
|
||||
//var statics =
|
||||
//JsonConvert.SerializeObject(res);
|
||||
|
||||
//await _onlinePayment.CancelAsync(invoice);
|
||||
//return new JsonResult(new
|
||||
//{
|
||||
// data,
|
||||
// statics
|
||||
//});
|
||||
}
|
||||
|
||||
//// Check if the invoice is new, or it's already processed before.
|
||||
//if (invoice.Status != PaymentFetchResultStatus.ReadyForVerifying)
|
||||
//{
|
||||
// // You can also see if the invoice is already verified before.
|
||||
// var isAlreadyVerified = invoice.IsAlreadyVerified;
|
||||
|
||||
// return Content("The payment was not successful.");
|
||||
//}
|
||||
|
||||
//// Note: Save the verifyResult.TransactionCode in your database.
|
||||
}
|
||||
|
||||
[HttpPost("/api/callback3232")]
|
||||
public async Task<IActionResult> OnGetCallBack(string? transid, string? cardnumber, string? tracking_number,
|
||||
string bank, string invoice_id, string? status, CancellationToken cancellationToken)
|
||||
[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))
|
||||
{
|
||||
@@ -223,10 +183,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)
|
||||
@@ -240,6 +200,7 @@ public class GeneralController : GeneralBaseController
|
||||
TypeOfTransaction = "credit",
|
||||
DescriptionOption = "بابت قرارداد مابین (روابط کار)",
|
||||
Description = "درگاه بانکی",
|
||||
|
||||
};
|
||||
var statementResult = _financialStatmentApplication.CreateFromBankGateway(command);
|
||||
if (!statementResult.IsSuccedded)
|
||||
@@ -247,14 +208,12 @@ 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));
|
||||
}
|
||||
|
||||
@@ -278,83 +237,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; }
|
||||
}
|
||||
@@ -13,9 +13,11 @@ public class AndroidApk : Controller
|
||||
}
|
||||
|
||||
[Route("Apk/Android")]
|
||||
public async Task<IActionResult> Index()
|
||||
public async Task<IActionResult> Index([FromQuery] string type = "WebView")
|
||||
{
|
||||
var path = await _androidApkVersionApplication.GetLatestActiveVersionPath();
|
||||
return PhysicalFile(path,"application/vnd.android.package-archive","Gozareshgir.apk");
|
||||
ApkType apkType = type.ToLower() == "facedetection" ? ApkType.FaceDetection : ApkType.WebView;
|
||||
var path = await _androidApkVersionApplication.GetLatestActiveVersionPath(apkType);
|
||||
var fileName = apkType == ApkType.WebView ? "Gozareshgir.apk" : "Gozareshgir-FaceDetection.apk";
|
||||
return PhysicalFile(path,"application/vnd.android.package-archive", fileName);
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ public class IndexModel : PageModel
|
||||
[BindProperty] public string Password { get; set; }
|
||||
[BindProperty] public string CaptchaResponse { get; set; }
|
||||
public bool HasApkToDownload { get; set; }
|
||||
public bool HasFaceDetectionApkToDownload { get; set; }
|
||||
private static Timer aTimer;
|
||||
public Login login;
|
||||
public AccountViewModel Search;
|
||||
@@ -76,7 +77,8 @@ public class IndexModel : PageModel
|
||||
|
||||
//_context.SaveChanges();
|
||||
|
||||
HasApkToDownload = _androidApkVersionApplication.HasAndroidApkToDownload();
|
||||
HasApkToDownload = _androidApkVersionApplication.HasAndroidApkToDownload(ApkType.WebView);
|
||||
HasFaceDetectionApkToDownload = _androidApkVersionApplication.HasAndroidApkToDownload(ApkType.FaceDetection);
|
||||
if (User.Identity is { IsAuthenticated: true })
|
||||
{
|
||||
if (User.FindFirstValue("IsCamera") == "true")
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"sqlDebugging": true,
|
||||
"dotnetRunMessages": "true",
|
||||
"nativeDebugging": true,
|
||||
"applicationUrl": "https://localhost:5004;http://localhost:5003;",
|
||||
"applicationUrl": "https://localhost:5004;http://localhost:5003;https://192.168.0.117:5005;http://192.168.0.117:5006;",
|
||||
"jsWebView2Debugging": false,
|
||||
"hotReloadEnabled": true
|
||||
},
|
||||
|
||||
@@ -41,9 +41,7 @@
|
||||
},
|
||||
"SmsSettings": {
|
||||
"IsTestMode": true,
|
||||
"TestNumbers": [ "09116967898"
|
||||
//, "09116067106", "09114221321"
|
||||
]
|
||||
"TestNumbers": [ "09116967898", "09116067106", "09114221321" ]
|
||||
},
|
||||
"SepehrGateWayTerminalId": 99213700
|
||||
|
||||
|
||||
184
plan-addApkTypeToAndroidApkVersion.prompt.md
Normal file
184
plan-addApkTypeToAndroidApkVersion.prompt.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# Plan: Add ApkType to AndroidApkVersion for WebView and FaceDetection separation
|
||||
|
||||
## Overview
|
||||
|
||||
The user wants to integrate the `ApkType` enum (WebView/FaceDetection) into the `AndroidApkVersion` entity to distinguish between the two different APK types. Currently, all APKs are treated as WebView. The system needs to be updated to support both types with separate handling.
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Update AndroidApkVersion.cs domain entity
|
||||
**File:** `Company.Domain\AndroidApkVersionAgg\AndroidApkVersion.cs`
|
||||
|
||||
- Add `ApkType` property to the class
|
||||
- Update constructor to accept `ApkType` parameter
|
||||
- Modify `Title` property generation to include APK type information
|
||||
- Update the constructor logic to handle both WebView and FaceDetection types
|
||||
|
||||
### 2. Update AndroidApkVersionMapping.cs EF configuration
|
||||
**File:** `CompanyManagment.EFCore\Mapping\AndroidApkVersionMapping.cs`
|
||||
|
||||
- Add mapping configuration for `ApkType` property
|
||||
- Use enum-to-string conversion (similar to existing `IsActive` mapping)
|
||||
- Set appropriate column max length for the enum value
|
||||
|
||||
### 3. Create database migration
|
||||
**Files:** Generated migration files in `CompanyManagment.EFCore\Migrations\`
|
||||
|
||||
- Generate new migration to add `ApkType` column to `AndroidApkVersions` table
|
||||
- Set default value to `ApkType.WebView` for existing records
|
||||
- Apply migration to update database schema
|
||||
|
||||
### 4. Update IAndroidApkVersionRepository.cs interface
|
||||
**File:** `Company.Domain\AndroidApkVersionAgg\IAndroidApkVersionRepository.cs`
|
||||
|
||||
- Modify `GetActives()` to accept `ApkType` parameter for filtering
|
||||
- Modify `GetLatestActiveVersionPath()` to accept `ApkType` parameter
|
||||
- Add methods to handle type-specific queries
|
||||
|
||||
### 5. Update AndroidApkVersionRepository.cs implementation
|
||||
**File:** `CompanyManagment.EFCore\Repository\AndroidApkVersionRepository.cs`
|
||||
|
||||
- Implement type-based filtering in `GetActives()` method
|
||||
- Implement type-based filtering in `GetLatestActiveVersionPath()` method
|
||||
- Add appropriate WHERE clauses to filter by `ApkType`
|
||||
|
||||
### 6. Update IAndroidApkVersionApplication.cs interface
|
||||
**File:** `CompanyManagment.App.Contracts\AndroidApkVersion\IAndroidApkVersionApplication.cs`
|
||||
|
||||
- Add `ApkType` parameter to `CreateAndActive()` method
|
||||
- Add `ApkType` parameter to `CreateAndDeActive()` method
|
||||
- Add `ApkType` parameter to `GetLatestActiveVersionPath()` method
|
||||
- Add `ApkType` parameter to `HasAndroidApkToDownload()` method
|
||||
|
||||
### 7. Update AndroidApkVersionApplication.cs implementation
|
||||
**File:** `CompanyManagment.Application\AndroidApkVersionApplication.cs`
|
||||
|
||||
- Update `CreateAndActive()` method:
|
||||
- Accept `ApkType` parameter
|
||||
- Change storage path from hardcoded "GozreshgirWebView" to dynamic based on type
|
||||
- Use "GozreshgirWebView" for `ApkType.WebView`
|
||||
- Use "GozreshgirFaceDetection" for `ApkType.FaceDetection`
|
||||
- Pass `ApkType` to repository methods when getting/deactivating existing APKs
|
||||
- Pass `ApkType` to entity constructor
|
||||
|
||||
- Update `CreateAndDeActive()` method:
|
||||
- Accept `ApkType` parameter
|
||||
- Update storage path logic similar to `CreateAndActive()`
|
||||
- Pass `ApkType` to entity constructor
|
||||
|
||||
- Update `GetLatestActiveVersionPath()` method:
|
||||
- Accept `ApkType` parameter
|
||||
- Pass type to repository method
|
||||
|
||||
- Update `HasAndroidApkToDownload()` method:
|
||||
- Accept `ApkType` parameter
|
||||
- Filter by type when checking for active APKs
|
||||
|
||||
### 8. Update AndroidApk.cs controller
|
||||
**File:** `ServiceHost\Pages\Apk\AndroidApk.cs`
|
||||
|
||||
- Modify the download endpoint to accept `ApkType` parameter
|
||||
- Options:
|
||||
- Add query string parameter: `/Apk/Android?type=WebView` or `/Apk/Android?type=FaceDetection`
|
||||
- Create separate routes: `/Apk/Android/WebView` and `/Apk/Android/FaceDetection`
|
||||
- Pass the type parameter to `GetLatestActiveVersionPath()` method
|
||||
- Maintain backward compatibility by defaulting to `ApkType.WebView` if no type specified
|
||||
|
||||
### 9. Update admin UI Index.cshtml.cs
|
||||
**File:** `ServiceHost\Areas\AdminNew\Pages\Company\AndroidApk\Index.cshtml.cs`
|
||||
|
||||
- Add property to store selected `ApkType`
|
||||
- Add `[BindProperty]` for ApkType selection
|
||||
- Modify `OnPostUpload()` to pass selected `ApkType` to application method
|
||||
- Create corresponding UI changes in Index.cshtml (if exists) to allow type selection
|
||||
|
||||
### 10. Update client-facing pages
|
||||
**Files:**
|
||||
- `ServiceHost\Pages\login\Index.cshtml.cs`
|
||||
- `ServiceHost\Areas\Client\Pages\Index.cshtml.cs`
|
||||
|
||||
- Update calls to `HasAndroidApkToDownload()` to specify which APK type to check
|
||||
- Consider showing different download buttons/links for WebView vs FaceDetection apps
|
||||
- Update download links to include APK type parameter
|
||||
|
||||
## Migration Strategy
|
||||
|
||||
### Handling Existing Data
|
||||
- All existing `AndroidApkVersion` records should be marked as `ApkType.WebView` by default
|
||||
- Use migration to set default value
|
||||
- No manual data update required if migration includes default value
|
||||
|
||||
### Database Schema Change
|
||||
```sql
|
||||
ALTER TABLE AndroidApkVersions
|
||||
ADD ApkType NVARCHAR(20) NOT NULL DEFAULT 'WebView';
|
||||
```
|
||||
|
||||
## UI Design Considerations
|
||||
|
||||
### Admin Upload Page
|
||||
**Recommended approach:** Single form with radio buttons or dropdown
|
||||
|
||||
- Add radio buttons or dropdown to select APK type before upload
|
||||
- Labels: "WebView Application" and "Face Detection Application"
|
||||
- Group uploads by type in the list/table view
|
||||
- Show type column in the APK list
|
||||
|
||||
### Client Download Pages
|
||||
**Recommended approach:** Separate download buttons
|
||||
|
||||
- Show "Download Gozareshgir WebView" button (existing functionality)
|
||||
- Show "Download Gozareshgir FaceDetection" button (new functionality)
|
||||
- Only show buttons if corresponding APK type is available
|
||||
- Use different icons or colors to distinguish between types
|
||||
|
||||
## Download URL Structure
|
||||
|
||||
**Recommended approach:** Single endpoint with query parameter
|
||||
|
||||
- Current: `/Apk/Android` (defaults to WebView for backward compatibility)
|
||||
- New WebView: `/Apk/Android?type=WebView`
|
||||
- New FaceDetection: `/Apk/Android?type=FaceDetection`
|
||||
|
||||
**Alternative approach:** Separate endpoints
|
||||
- `/Apk/Android/WebView`
|
||||
- `/Apk/Android/FaceDetection`
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
1. ✅ Upload WebView APK successfully
|
||||
2. ✅ Upload FaceDetection APK successfully
|
||||
3. ✅ Both types can coexist in database
|
||||
4. ✅ Activating WebView APK doesn't affect FaceDetection APK
|
||||
5. ✅ Activating FaceDetection APK doesn't affect WebView APK
|
||||
6. ✅ Download correct APK based on type parameter
|
||||
7. ✅ Admin UI shows type information correctly
|
||||
8. ✅ Client pages show correct download availability
|
||||
9. ✅ Backward compatibility maintained (existing links still work)
|
||||
10. ✅ Migration applies successfully to existing database
|
||||
|
||||
## File Summary
|
||||
|
||||
**Files to modify:**
|
||||
1. `Company.Domain\AndroidApkVersionAgg\AndroidApkVersion.cs`
|
||||
2. `CompanyManagment.EFCore\Mapping\AndroidApkVersionMapping.cs`
|
||||
3. `Company.Domain\AndroidApkVersionAgg\IAndroidApkVersionRepository.cs`
|
||||
4. `CompanyManagment.EFCore\Repository\AndroidApkVersionRepository.cs`
|
||||
5. `CompanyManagment.App.Contracts\AndroidApkVersion\IAndroidApkVersionApplication.cs`
|
||||
6. `CompanyManagment.Application\AndroidApkVersionApplication.cs`
|
||||
7. `ServiceHost\Pages\Apk\AndroidApk.cs`
|
||||
8. `ServiceHost\Areas\AdminNew\Pages\Company\AndroidApk\Index.cshtml.cs`
|
||||
9. `ServiceHost\Pages\login\Index.cshtml.cs`
|
||||
10. `ServiceHost\Areas\Client\Pages\Index.cshtml.cs`
|
||||
|
||||
**Files to create:**
|
||||
1. New migration file (auto-generated)
|
||||
2. Possibly `ServiceHost\Areas\AdminNew\Pages\Company\AndroidApk\Index.cshtml` (if doesn't exist)
|
||||
|
||||
## Notes
|
||||
|
||||
- The `ApkType` enum is already defined in `AndroidApkVersion.cs`
|
||||
- Storage folders will be separate: `Storage/Apk/Android/GozreshgirWebView` and `Storage/Apk/Android/GozreshgirFaceDetection`
|
||||
- Each APK type maintains its own active/inactive state independently
|
||||
- Consider adding validation to ensure APK file matches selected type (optional enhancement)
|
||||
|
||||
151
plan-addIsForceToAndroidApkVersion.prompt.md
Normal file
151
plan-addIsForceToAndroidApkVersion.prompt.md
Normal file
@@ -0,0 +1,151 @@
|
||||
# Plan: Add IsForce Field to Android APK Version Management
|
||||
|
||||
## Overview
|
||||
Add support for force update functionality to the Android APK version management system. This allows administrators to specify whether an APK update is mandatory (force update) or optional when uploading new versions. The system now supports two separate APK types: WebView and FaceDetection.
|
||||
|
||||
## Context
|
||||
- The system manages Android APK versions for two different application types
|
||||
- Previously, all updates were treated as optional
|
||||
- Need to add ability to mark certain updates as mandatory
|
||||
- Force update flag should be stored in database and returned via API
|
||||
|
||||
## Requirements
|
||||
1. Add `IsForce` boolean field to the `AndroidApkVersion` entity
|
||||
2. Allow administrators to specify force update status when uploading APK
|
||||
3. Store force update status in database
|
||||
4. Return force update status via API endpoint
|
||||
5. Separate handling for WebView and FaceDetection APK types
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### 1. Domain Layer Updates
|
||||
- ✅ Add `IsForce` property to `AndroidApkVersion` entity
|
||||
- ✅ Update constructor to accept `isForce` parameter with default value of `false`
|
||||
- ✅ File: `Company.Domain/AndroidApkVersionAgg/AndroidApkVersion.cs`
|
||||
|
||||
### 2. Database Mapping
|
||||
- ✅ Add `IsForce` property mapping in `AndroidApkVersionMapping`
|
||||
- ✅ File: `CompanyManagment.EFCore/Mapping/AndroidApkVersionMapping.cs`
|
||||
|
||||
### 3. Application Layer Updates
|
||||
- ✅ Update `IAndroidApkVersionApplication` interface:
|
||||
- Add `isForce` parameter to `CreateAndActive` method
|
||||
- Add `isForce` parameter to `CreateAndDeActive` method
|
||||
- Remove `isForceUpdate` parameter from `GetLatestActiveInfo` method
|
||||
- ✅ File: `CompanyManagment.App.Contracts/AndroidApkVersion/IAndroidApkVersionApplication.cs`
|
||||
|
||||
### 4. Application Implementation
|
||||
- ✅ Update `AndroidApkVersionApplication`:
|
||||
- Pass `isForce` to `AndroidApkVersion` constructor in `CreateAndActive`
|
||||
- Pass `isForce` to `AndroidApkVersion` constructor in `CreateAndDeActive`
|
||||
- Update `GetLatestActiveInfo` to return `IsForce` from database entity instead of parameter
|
||||
- ✅ File: `CompanyManagment.Application/AndroidApkVersionApplication.cs`
|
||||
|
||||
### 5. API Controller Updates
|
||||
- ✅ Update `AndroidApkController`:
|
||||
- Remove `force` parameter from `CheckUpdate` endpoint
|
||||
- API now returns `IsForce` from database
|
||||
- ✅ File: `ServiceHost/Areas/Admin/Controllers/AndroidApkController.cs`
|
||||
|
||||
### 6. Admin UI Updates
|
||||
- ✅ Add `IsForce` property to `IndexModel`
|
||||
- ✅ Add checkbox for force update in upload form
|
||||
- ✅ Pass `IsForce` value to `CreateAndActive` method
|
||||
- ✅ Files:
|
||||
- `ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs`
|
||||
- `ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml`
|
||||
|
||||
### 7. Database Migration (To Be Done)
|
||||
- ⚠️ **REQUIRED**: Create and run migration to add `IsForce` column to `AndroidApkVersions` table
|
||||
- Command: `Add-Migration AddIsForceToAndroidApkVersion`
|
||||
- Then: `Update-Database`
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Check for Updates
|
||||
```http
|
||||
GET /api/android-apk/check-update?type={ApkType}¤tVersionCode={int}
|
||||
```
|
||||
|
||||
**Parameters:**
|
||||
- `type`: Enum value - `WebView` or `FaceDetection`
|
||||
- `currentVersionCode`: Current version code of installed app (integer)
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"latestVersionCode": 120,
|
||||
"latestVersionName": "1.2.0",
|
||||
"shouldUpdate": true,
|
||||
"isForceUpdate": false,
|
||||
"downloadUrl": "/Apk/Android?type=WebView",
|
||||
"releaseNotes": "Bug fixes and improvements"
|
||||
}
|
||||
```
|
||||
|
||||
## APK Type Separation
|
||||
|
||||
The system now fully supports two separate APK types:
|
||||
1. **WebView**: Original web-view based application
|
||||
- Stored in: `Storage/Apk/Android/GozreshgirWebView/`
|
||||
- Title format: `Gozareshgir-WebView-{version}-{date}`
|
||||
|
||||
2. **FaceDetection**: New face detection application
|
||||
- Stored in: `Storage/Apk/Android/GozreshgirFaceDetection/`
|
||||
- Title format: `Gozareshgir-FaceDetection-{version}-{date}`
|
||||
|
||||
Each APK type maintains its own:
|
||||
- Version history
|
||||
- Active version
|
||||
- Force update settings
|
||||
- Download endpoint
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Admin Upload with Force Update
|
||||
1. Navigate to admin APK upload page
|
||||
2. Select APK file
|
||||
3. Choose APK type (WebView or FaceDetection)
|
||||
4. Check "آپدیت اجباری (Force Update)" if update should be mandatory
|
||||
5. Click Upload
|
||||
|
||||
### Client Check for Update (WebView)
|
||||
```http
|
||||
GET /api/android-apk/check-update?type=WebView¤tVersionCode=100
|
||||
```
|
||||
|
||||
### Client Check for Update (FaceDetection)
|
||||
```http
|
||||
GET /api/android-apk/check-update?type=FaceDetection¤tVersionCode=50
|
||||
```
|
||||
|
||||
## Testing Checklist
|
||||
- [ ] Test uploading APK with force update enabled for WebView
|
||||
- [ ] Test uploading APK with force update disabled for WebView
|
||||
- [ ] Test uploading APK with force update enabled for FaceDetection
|
||||
- [ ] Test uploading APK with force update disabled for FaceDetection
|
||||
- [ ] Verify API returns correct `isForceUpdate` value for WebView
|
||||
- [ ] Verify API returns correct `isForceUpdate` value for FaceDetection
|
||||
- [ ] Verify only one active version exists per APK type
|
||||
- [ ] Test migration creates `IsForce` column correctly
|
||||
- [ ] Verify existing records default to `false` for `IsForce`
|
||||
|
||||
## Notes
|
||||
- Default value for `IsForce` is `false` (optional update)
|
||||
- When uploading new active APK, all previous active versions of same type are deactivated
|
||||
- Each APK type is managed independently
|
||||
- Force update flag is stored per version, not globally
|
||||
- API returns force update status from the latest active version in database
|
||||
|
||||
## Files Modified
|
||||
1. `Company.Domain/AndroidApkVersionAgg/AndroidApkVersion.cs`
|
||||
2. `CompanyManagment.EFCore/Mapping/AndroidApkVersionMapping.cs`
|
||||
3. `CompanyManagment.App.Contracts/AndroidApkVersion/IAndroidApkVersionApplication.cs`
|
||||
4. `CompanyManagment.Application/AndroidApkVersionApplication.cs`
|
||||
5. `ServiceHost/Areas/Admin/Controllers/AndroidApkController.cs`
|
||||
6. `ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml.cs`
|
||||
7. `ServiceHost/Areas/AdminNew/Pages/Company/AndroidApk/Index.cshtml`
|
||||
|
||||
## Migration Required
|
||||
⚠️ **Important**: Don't forget to create and run the database migration to add the `IsForce` column.
|
||||
|
||||
Reference in New Issue
Block a user