Compare commits
234 Commits
Feature/ad
...
Feature/ro
| Author | SHA1 | Date | |
|---|---|---|---|
| b3f42af77c | |||
| eb49bf771d | |||
| ea896c4c11 | |||
| 167b2bce09 | |||
| 3c0ec01f77 | |||
| 343f830d0d | |||
| 87ff7976fb | |||
| a533850f24 | |||
| b5c1a4c29d | |||
| 28607dec66 | |||
| 4a041ca8e2 | |||
|
|
de0de6fde8 | ||
|
|
70447a74ef | ||
| 90aa6058f0 | |||
| 3df296f205 | |||
| 6a2e4405de | |||
| 88c10ac141 | |||
|
|
8de3939675 | ||
| e78c838cab | |||
|
|
5e4b8a3a80 | ||
|
|
a18984fec1 | ||
| a178fcd202 | |||
| 9e92d2215f | |||
| c63eb23b22 | |||
| 238926118f | |||
| c874164ca2 | |||
| d2f0ed46ae | |||
| 40dd90074b | |||
| 452b0b6277 | |||
| 720e998a54 | |||
| 626722e805 | |||
| 5e5910e0fd | |||
| 5d81731512 | |||
| 511932fa58 | |||
| 95891d5bae | |||
| f3fa76c292 | |||
| ac6bbc3587 | |||
| 947d7590f4 | |||
| 91403a52a3 | |||
| 7e80342f80 | |||
| 5e92207778 | |||
|
|
29484e9565 | ||
| ba640494d2 | |||
| 6974a505b4 | |||
| 6d3d599449 | |||
| 2d28bd1f98 | |||
| 75ae3efb65 | |||
| eb53fd67ef | |||
| 8ec717916c | |||
| 64bdbcbd2d | |||
| 7e9ba23b97 | |||
|
|
e6640a1636 | ||
|
|
e9665c190b | ||
| ea3baf14e8 | |||
| 36f104f316 | |||
| 42cae1295f | |||
| 95b281c3a4 | |||
|
|
c239b094d7 | ||
| 9e61bd3f55 | |||
| 7025478417 | |||
|
|
b5ee4f01c7 | ||
| 3937cd8a9f | |||
|
|
3ed14bf2bd | ||
| 933dd3d937 | |||
| 90d7de4901 | |||
| 37aa57d773 | |||
| cce903f2ae | |||
| 873ad2f41f | |||
| 2035b6fff8 | |||
|
|
d31cf8470f | ||
|
|
5a34c9a6c9 | ||
|
|
4eb78996d5 | ||
|
|
9d8e40c841 | ||
|
|
4ba21db7c7 | ||
| 164388dac3 | |||
| e81a44dd2f | |||
| f238b5af6b | |||
|
|
f5cb6b276e | ||
| ed746cb60a | |||
| 07b2596a6a | |||
| 7dce7f5bc8 | |||
| 7ac078c631 | |||
| 265d5f8b22 | |||
| cf5c9f29cf | |||
| 7448ddc79c | |||
| 3f1a6f3387 | |||
| 95d4dfe568 | |||
|
|
a481e941c5 | ||
|
|
58637ab038 | ||
|
|
d10eff3dd5 | ||
| 3258deeb2c | |||
| 6d3526fb30 | |||
|
|
ed35067ecc | ||
|
|
488ce6041a | ||
|
|
0f261684e9 | ||
|
|
a2c0cf126a | ||
|
|
09a1d6df38 | ||
|
|
39bacdf8d6 | ||
| ba2b402c04 | |||
| f3470de8b6 | |||
| 783fffa0c2 | |||
| 16c29bc2d0 | |||
|
|
dad334a9bd | ||
|
|
57ef47473b | ||
|
|
193e9f587f | ||
|
|
e00c93b23d | ||
| 8bd248c6a7 | |||
|
|
2164aeb5bc | ||
|
|
7e08b44d4d | ||
|
|
eec53c8024 | ||
|
|
8c37826367 | ||
| 7f9531f07b | |||
| 4a8f76c473 | |||
| 3e5520d8a0 | |||
| 0b439d0268 | |||
|
|
861b214b0c | ||
|
|
690f574240 | ||
|
|
05abc67cdd | ||
| 3282825719 | |||
| 76666b3da7 | |||
| cd1cf93ad1 | |||
| adef1fc15a | |||
| 597f54c062 | |||
| c0ead0a917 | |||
| 59284ffd29 | |||
| 5c7dd76e3f | |||
| dff6bc2541 | |||
| 22b67b344a | |||
|
|
d8b432ca1e | ||
| f4853b6f39 | |||
| 6ab418c4ab | |||
|
|
74dca1d2d2 | ||
|
|
a9b4eb6195 | ||
|
|
2125e15fb9 | ||
| b7f7d3b223 | |||
| 752c7c72ab | |||
| 18c27d7a9a | |||
| 73da938bc9 | |||
|
|
c080e11fe0 | ||
|
|
0eb9ecc373 | ||
| 470651cb76 | |||
| 2a9d9574e3 | |||
|
|
7b1542d5c6 | ||
|
|
981fd2d4ee | ||
|
|
7f3f785e39 | ||
| ca1ef420af | |||
| d7baf358cc | |||
|
|
676c8d2fa6 | ||
|
|
632ab3631b | ||
| 595b2c8a2d | |||
| c7bace728e | |||
| 08574b5bb5 | |||
| 288e3a8988 | |||
| 8134216a4a | |||
|
|
3d013cfa60 | ||
| 30bfc96cbe | |||
| 5d55118c3c | |||
| 280db87408 | |||
| c5a1e5c274 | |||
| 4c6de6a76f | |||
| 25c7b67eb5 | |||
| 19b390b17d | |||
| 026d8da74a | |||
| 6b6b0767e3 | |||
| 3d86ba401f | |||
| 6a6e2e532a | |||
| ca6638d6a3 | |||
| 608fb824dc | |||
| 4686151bbb | |||
| d7fae42e4f | |||
| 2cfe480733 | |||
|
|
c574ce534d | ||
| 174edbf87d | |||
| a827470831 | |||
| c9b61c3fc6 | |||
| 45002b88c4 | |||
| 0bacb24aa2 | |||
| 7fd8851f71 | |||
| bc6ae854f8 | |||
| 68f1f81b53 | |||
| d4c2ab939e | |||
| 5822005b68 | |||
| 53aeb60861 | |||
| c2a08d9c33 | |||
| 85e2481680 | |||
| b711e803a9 | |||
| 232a834dc9 | |||
| 55f7b4f7c0 | |||
| c5b521bc50 | |||
| acdd7de4f6 | |||
| 78458f24e5 | |||
| fde58a7c75 | |||
|
|
dbddccf011 | ||
| 488454d354 | |||
| 4126a7370f | |||
| 7aff8ba59f | |||
| 7d6b57affd | |||
| 950f2884ac | |||
| 2edf150ef6 | |||
| df9c268959 | |||
| 3c6303e817 | |||
| 23386fda76 | |||
| 119f4496cd | |||
| ce4fc33daa | |||
| f5d95b21b0 | |||
| 6e83904e11 | |||
| 1f7785581c | |||
| 9140f1ea0b | |||
| 81e6094817 | |||
| e5c0a7db58 | |||
| d44a9224be | |||
| c8018948c2 | |||
| a5e68cbd90 | |||
| 37a6920a74 | |||
| db40ab567c | |||
| 5f324a6fa1 | |||
| d1703ad20e | |||
| 2f38470746 | |||
| 23c02abe65 | |||
| 475142744f | |||
| 13a2cd78cd | |||
| 4aa3c10466 | |||
| 91fc560355 | |||
| 9297bdefb5 | |||
| 61b326aed4 | |||
| 756e06cc2f | |||
|
|
2f15c2d54b | ||
|
|
9d9f0e14d3 | ||
|
|
4d45ee36b6 | ||
|
|
7ae08fe023 | ||
|
|
117b5df447 | ||
|
|
fee14c65ec | ||
|
|
31defcde7e | ||
|
|
a4dbb016d2 |
@@ -0,0 +1,22 @@
|
|||||||
|
namespace _0_Framework.Application.Enums;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// وضعیت تایید قرادا مالی
|
||||||
|
/// </summary>
|
||||||
|
public enum InstitutionContractVerificationStatus
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// در انتظار تایید
|
||||||
|
/// </summary>
|
||||||
|
PendingForVerify = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// در انتظار کارپوشه
|
||||||
|
/// </summary>
|
||||||
|
PendingWorkflow = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// تایید شده
|
||||||
|
/// </summary>
|
||||||
|
Verified = 2
|
||||||
|
}
|
||||||
15
0_Framework/Application/Enums/TypeOfCheckoutWarning.cs
Normal file
15
0_Framework/Application/Enums/TypeOfCheckoutWarning.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace _0_Framework.Application.Enums;
|
||||||
|
|
||||||
|
public enum TypeOfCheckoutWarning
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// هشدار های متفرقه
|
||||||
|
/// </summary>
|
||||||
|
OthersWarning,
|
||||||
|
/// <summary>
|
||||||
|
/// هشدار سهم بیمه کارگر
|
||||||
|
/// </summary>
|
||||||
|
InsuranceEmployeeShare,
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
36
0_Framework/Application/Enums/TypeOfSmsSetting.cs
Normal file
36
0_Framework/Application/Enums/TypeOfSmsSetting.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
namespace _0_Framework.Application.Enums;
|
||||||
|
|
||||||
|
public enum TypeOfSmsSetting
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پیامک
|
||||||
|
/// یادآور بدهی ماهیانه قرارداد مالی
|
||||||
|
/// </summary>
|
||||||
|
InstitutionContractDebtReminder,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پیامک
|
||||||
|
/// صورت حساب ماهانه قرارداد مالی
|
||||||
|
/// </summary>
|
||||||
|
MonthlyInstitutionContract,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پیامک
|
||||||
|
/// اعلام مسدودی طرف حساب
|
||||||
|
/// </summary>
|
||||||
|
BlockContractingParty,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پیامک
|
||||||
|
/// هشدار اول
|
||||||
|
/// </summary>
|
||||||
|
Warning,
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///پیامک اقدام قضائی
|
||||||
|
/// </summary>
|
||||||
|
LegalAction,
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace _0_Framework.Application.FaceEmbedding;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// سرویس اطلاعرسانی تغییرات Face Embedding
|
||||||
|
/// </summary>
|
||||||
|
public interface IFaceEmbeddingNotificationService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// اطلاعرسانی ایجاد یا بهروزرسانی Embedding
|
||||||
|
/// </summary>
|
||||||
|
Task NotifyEmbeddingCreatedAsync(long workshopId, long employeeId, string employeeFullName);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// اطلاعرسانی حذف Embedding
|
||||||
|
/// </summary>
|
||||||
|
Task NotifyEmbeddingDeletedAsync(long workshopId, long employeeId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// اطلاعرسانی بهبود Embedding
|
||||||
|
/// </summary>
|
||||||
|
Task NotifyEmbeddingRefinedAsync(long workshopId, long employeeId);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace _0_Framework.Application.FaceEmbedding;
|
||||||
|
|
||||||
|
public interface IFaceEmbeddingService
|
||||||
|
{
|
||||||
|
Task<OperationResult> GenerateEmbeddingsAsync(long employeeId, long workshopId, string employeeFullName, string picture1Path, string picture2Path);
|
||||||
|
Task<OperationResult> GenerateEmbeddingsFromStreamAsync(long employeeId, long workshopId, string employeeFullName, Stream picture1Stream, Stream picture2Stream);
|
||||||
|
Task<OperationResult> RefineEmbeddingAsync(long employeeId, long workshopId, float[] embedding, float confidence, Dictionary<string, object> metadata = null);
|
||||||
|
Task<OperationResult> DeleteEmbeddingAsync(long employeeId, long workshopId);
|
||||||
|
Task<OperationResult<FaceEmbeddingResponse>> GetEmbeddingAsync(long employeeId, long workshopId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FaceEmbeddingResponse
|
||||||
|
{
|
||||||
|
public long EmployeeId { get; set; }
|
||||||
|
public long WorkshopId { get; set; }
|
||||||
|
public string EmployeeFullName { get; set; }
|
||||||
|
public float[] Embedding { get; set; }
|
||||||
|
public float Confidence { get; set; }
|
||||||
|
public Dictionary<string, object> Metadata { get; set; }
|
||||||
|
}
|
||||||
@@ -39,7 +39,7 @@ public class AqayePardakhtPaymentGateway:IPaymentGateway
|
|||||||
amount = command.Amount,
|
amount = command.Amount,
|
||||||
callback = command.CallBackUrl,
|
callback = command.CallBackUrl,
|
||||||
card_number = command.CardNumber,
|
card_number = command.CardNumber,
|
||||||
invoice_id = command.InvoiceId,
|
invoice_id = command.TransactionId,
|
||||||
mobile = command.Mobile,
|
mobile = command.Mobile,
|
||||||
email = command.Email??"",
|
email = command.Email??"",
|
||||||
description = command.Description,
|
description = command.Description,
|
||||||
@@ -73,7 +73,7 @@ public class AqayePardakhtPaymentGateway:IPaymentGateway
|
|||||||
amount = command.Amount,
|
amount = command.Amount,
|
||||||
callback = command.CallBackUrl,
|
callback = command.CallBackUrl,
|
||||||
card_number = command.Amount,
|
card_number = command.Amount,
|
||||||
invoice_id = command.InvoiceId,
|
invoice_id = command.TransactionId,
|
||||||
mobile = command.Mobile,
|
mobile = command.Mobile,
|
||||||
email = command.Email,
|
email = command.Email,
|
||||||
description = command.Email,
|
description = command.Email,
|
||||||
|
|||||||
@@ -29,9 +29,11 @@ public class PaymentGatewayResponse
|
|||||||
public int? ErrorCode { get; set; }
|
public int? ErrorCode { get; set; }
|
||||||
|
|
||||||
[JsonPropertyName("transid")]
|
[JsonPropertyName("transid")]
|
||||||
public string TransactionId { get; set; }
|
public string Token { get; set; }
|
||||||
|
|
||||||
public bool IsSuccess => Status == "success";
|
public bool IsSuccess { get; set; }
|
||||||
|
|
||||||
|
public string Message { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class WalletAmountResponse
|
public class WalletAmountResponse
|
||||||
@@ -47,16 +49,19 @@ public class WalletAmountResponse
|
|||||||
public class CreatePaymentGatewayRequest
|
public class CreatePaymentGatewayRequest
|
||||||
{
|
{
|
||||||
public double Amount { get; set; }
|
public double Amount { get; set; }
|
||||||
|
public string TransactionId { get; set; }
|
||||||
public string CallBackUrl { get; set; }
|
public string CallBackUrl { get; set; }
|
||||||
public string InvoiceId { get; set; }
|
|
||||||
public string CardNumber { get; set; }
|
public string CardNumber { get; set; }
|
||||||
public string Mobile { get; set; }
|
public string Mobile { get; set; }
|
||||||
public string Email { get; set; }
|
public string Email { get; set; }
|
||||||
public string Description { get; set; }
|
public string Description { get; set; }
|
||||||
|
public long FinancialInvoiceId { get; set; }
|
||||||
|
public IDictionary<string, object> ExtraData { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class VerifyPaymentGateWayRequest
|
public class VerifyPaymentGateWayRequest
|
||||||
{
|
{
|
||||||
public string TransactionId { get; set; }
|
public string DigitalReceipt { get; set; }
|
||||||
|
public string TransactionId { get; set; }
|
||||||
public double Amount { get; set; }
|
public double Amount { get; set; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace _0_Framework.Application.PaymentGateway;
|
||||||
|
|
||||||
|
public class SepehrPaymentGateway:IPaymentGateway
|
||||||
|
{
|
||||||
|
private readonly HttpClient _httpClient;
|
||||||
|
private const long TerminalId = 99213700;
|
||||||
|
|
||||||
|
public SepehrPaymentGateway(IHttpClientFactory httpClient)
|
||||||
|
{
|
||||||
|
_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,
|
||||||
|
callbackURL = command.CallBackUrl,
|
||||||
|
payload = extraData
|
||||||
|
}, cancellationToken: cancellationToken);
|
||||||
|
// خواندن محتوای پاسخ
|
||||||
|
var content = await res.Content.ReadAsStringAsync(cancellationToken);
|
||||||
|
|
||||||
|
// تبدیل پاسخ JSON به آبجکت داتنت
|
||||||
|
var json = System.Text.Json.JsonDocument.Parse(content);
|
||||||
|
|
||||||
|
// گرفتن مقدار AccessToken
|
||||||
|
var accessToken = json.RootElement.GetProperty("Accesstoken").ToString();
|
||||||
|
var status = json.RootElement.GetProperty("Status").ToString();
|
||||||
|
|
||||||
|
return new PaymentGatewayResponse
|
||||||
|
{
|
||||||
|
Status = status,
|
||||||
|
IsSuccess = status == "0",
|
||||||
|
Token = accessToken
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetStartPayUrl(string token)=>
|
||||||
|
$"https://sepehr.shaparak.ir/Payment/Pay?token={token}&terminalId={TerminalId}";
|
||||||
|
|
||||||
|
public async Task<PaymentGatewayResponse> Verify(VerifyPaymentGateWayRequest command, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var res = await _httpClient.PostAsJsonAsync("Advice", new
|
||||||
|
{
|
||||||
|
digitalreceipt = command.DigitalReceipt,
|
||||||
|
Tid = TerminalId,
|
||||||
|
}, cancellationToken: cancellationToken);
|
||||||
|
|
||||||
|
// خواندن محتوای پاسخ
|
||||||
|
var content = await res.Content.ReadAsStringAsync(cancellationToken);
|
||||||
|
|
||||||
|
// تبدیل پاسخ JSON به آبجکت داتنت
|
||||||
|
var json = System.Text.Json.JsonDocument.Parse(content);
|
||||||
|
|
||||||
|
|
||||||
|
var message = json.RootElement.GetProperty("Message").GetString();
|
||||||
|
var status = json.RootElement.GetProperty("Status").GetString();
|
||||||
|
return new PaymentGatewayResponse
|
||||||
|
{
|
||||||
|
Status = status,
|
||||||
|
IsSuccess = status.ToLower() == "ok",
|
||||||
|
Message = message
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<PaymentGatewayResponse> CreateSandBox(CreatePaymentGatewayRequest command, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
throw new System.NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetStartPaySandBoxUrl(string transactionId)
|
||||||
|
{
|
||||||
|
throw new System.NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<WalletAmountResponse> GetWalletAmount(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
throw new System.NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,9 +27,64 @@ public interface ISmsService
|
|||||||
|
|
||||||
Task<double> GetCreditAmount();
|
Task<double> GetCreditAmount();
|
||||||
|
|
||||||
public Task<bool> SendInstitutionVerificationLink(string number,string fullName, Guid institutionId);
|
public Task<bool> SendInstitutionCreationVerificationLink(string number, string fullName, Guid institutionId, long contractingPartyId, long institutionContractId);
|
||||||
|
|
||||||
public Task<bool> SendInstitutionVerificationCode(string number, string code);
|
public Task<bool> SendInstitutionVerificationCode(string number, string code, string contractingPartyFullName,
|
||||||
|
long contractingPartyId, long institutionContractId);
|
||||||
|
|
||||||
|
SmsResult TaskReminderSms(string number, string taskCount);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
#region InstitutionContractSMS
|
||||||
|
/// <summary>
|
||||||
|
/// پیامک اهانه جدید
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <param name="tamplateId"></param>
|
||||||
|
/// <param name="fullname"></param>
|
||||||
|
/// <param name="amount"></param>
|
||||||
|
/// <param name="code1"></param>
|
||||||
|
/// <param name="code2"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<(byte status, string message, int messaeId, bool isSucceded)> MonthlyBillNew(string number, int tamplateId, string fullname, string amount, string code1,
|
||||||
|
string code2);
|
||||||
|
/// <summary>
|
||||||
|
/// پیامک ماهانه قدیم
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <param name="tamplateId"></param>
|
||||||
|
/// <param name="fullname"></param>
|
||||||
|
/// <param name="amount"></param>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <param name="aprove"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<(byte status, string message, int messaeId, bool isSucceded)> MonthlyBill(string number, int tamplateId, string fullname, string amount, string id, string aprove);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پیامک مسدودی طرف حساب
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <param name="fullname"></param>
|
||||||
|
/// <param name="amount"></param>
|
||||||
|
/// <param name="accountType"></param>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <param name="aprove"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<(byte status, string message, int messaeId, bool isSucceded)> BlockMessage(string number, string fullname, string amount, string accountType, string id, string aprove);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region AlarmMessage
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ارسال پیامک های خطا یا اعمال ارسال
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="number"></param>
|
||||||
|
/// <param name="message"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<bool> Alarm(string number, string message);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
32
0_Framework/Application/Sms/SmsResult.cs
Normal file
32
0_Framework/Application/Sms/SmsResult.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
namespace _0_Framework.Application.Sms;
|
||||||
|
|
||||||
|
public class SmsResult
|
||||||
|
{
|
||||||
|
public SmsResult()
|
||||||
|
{
|
||||||
|
IsSuccedded = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSuccedded { get; set; }
|
||||||
|
public string Message { get; set; }
|
||||||
|
public byte StatusCode { get; set; }
|
||||||
|
public int MessageId { get; set; }
|
||||||
|
|
||||||
|
public SmsResult Succedded(byte statusCode, string message, int messageId)
|
||||||
|
{
|
||||||
|
IsSuccedded = true;
|
||||||
|
Message = message;
|
||||||
|
StatusCode = statusCode;
|
||||||
|
MessageId = messageId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SmsResult Failed(byte statusCode, string message, int messageId)
|
||||||
|
{
|
||||||
|
IsSuccedded = false;
|
||||||
|
Message = message;
|
||||||
|
StatusCode = statusCode;
|
||||||
|
MessageId = messageId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,358 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Runtime.InteropServices.ComTypes;
|
|
||||||
using System.Security.AccessControl;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using IPE.SmsIrClient;
|
|
||||||
using IPE.SmsIrClient.Models.Requests;
|
|
||||||
using IPE.SmsIrClient.Models.Results;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
|
||||||
|
|
||||||
|
|
||||||
namespace _0_Framework.Application.Sms;
|
|
||||||
|
|
||||||
public class SmsService : ISmsService
|
|
||||||
{
|
|
||||||
private readonly IConfiguration _configuration;
|
|
||||||
public SmsIr SmsIr { get; set; }
|
|
||||||
|
|
||||||
|
|
||||||
public SmsService(IConfiguration configuration)
|
|
||||||
{
|
|
||||||
_configuration = configuration;
|
|
||||||
SmsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Send(string number, string message)
|
|
||||||
{
|
|
||||||
//var token = GetToken();
|
|
||||||
//var lines = new SmsLine().GetSmsLines(token);
|
|
||||||
//if (lines == null) return;
|
|
||||||
|
|
||||||
//var line = lines.SMSLines.Last().LineNumber.ToString();
|
|
||||||
//var data = new MessageSendObject
|
|
||||||
//{
|
|
||||||
// Messages = new List<string>
|
|
||||||
// {message}.ToArray(),
|
|
||||||
// MobileNumbers = new List<string> {number}.ToArray(),
|
|
||||||
// LineNumber = line,
|
|
||||||
// SendDateTime = DateTime.Now,
|
|
||||||
// CanContinueInCaseOfError = true
|
|
||||||
//};
|
|
||||||
//var messageSendResponseObject =
|
|
||||||
// new MessageSend().Send(token, data);
|
|
||||||
|
|
||||||
//if (messageSendResponseObject.IsSuccessful) return;
|
|
||||||
|
|
||||||
//line = lines.SMSLines.First().LineNumber.ToString();
|
|
||||||
//data.LineNumber = line;
|
|
||||||
//new MessageSend().Send(token, data);
|
|
||||||
}
|
|
||||||
public bool VerifySend(string number, string message)
|
|
||||||
{
|
|
||||||
|
|
||||||
SmsIr smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa");
|
|
||||||
|
|
||||||
//var bulkSendResult = smsIr.BulkSendAsync(95007079000006, "your text message", new string[] { "9120000000" });
|
|
||||||
|
|
||||||
var verificationSendResult = smsIr.VerifySendAsync(number, 768382, new VerifySendParameter[] { new VerifySendParameter("VerificationCode", message) });
|
|
||||||
Thread.Sleep(2000);
|
|
||||||
if (verificationSendResult.IsCompletedSuccessfully)
|
|
||||||
{
|
|
||||||
|
|
||||||
var resStartStatus = verificationSendResult.Result;
|
|
||||||
var b = resStartStatus.Status;
|
|
||||||
var resResult = verificationSendResult.Status;
|
|
||||||
var a = verificationSendResult.IsCompleted;
|
|
||||||
var reseExceptiont = verificationSendResult.Exception;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
var resStartStatus = verificationSendResult.Status;
|
|
||||||
var resResult = verificationSendResult.Status;
|
|
||||||
var reseExceptiont = verificationSendResult.Exception;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool LoginSend(string number, string message)
|
|
||||||
{
|
|
||||||
SmsIr smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa");
|
|
||||||
|
|
||||||
//var bulkSendResult = smsIr.BulkSendAsync(95007079000006, "your text message", new string[] { "9120000000" });
|
|
||||||
|
|
||||||
var verificationSendResult = smsIr.VerifySendAsync(number, 635330, new VerifySendParameter[] { new VerifySendParameter("LOGINCODE", message) });
|
|
||||||
Thread.Sleep(2000);
|
|
||||||
if (verificationSendResult.IsCompletedSuccessfully)
|
|
||||||
{
|
|
||||||
|
|
||||||
var resStartStatus = verificationSendResult.Result;
|
|
||||||
var b = resStartStatus.Status;
|
|
||||||
var resResult = verificationSendResult.Status;
|
|
||||||
var a = verificationSendResult.IsCompleted;
|
|
||||||
var reseExceptiont = verificationSendResult.Exception;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
var resStartStatus = verificationSendResult.Status;
|
|
||||||
var resResult = verificationSendResult.Status;
|
|
||||||
var reseExceptiont = verificationSendResult.Exception;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<SentSmsViewModel> SendVerifyCodeToClient(string number, string code)
|
|
||||||
{
|
|
||||||
SmsIr smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa");
|
|
||||||
var result = new SentSmsViewModel();
|
|
||||||
//var bulkSendResult = smsIr.BulkSendAsync(95007079000006, "your text message", new string[] { "9120000000" });
|
|
||||||
|
|
||||||
var sendResult = await smsIr.VerifySendAsync(number, 768382, new VerifySendParameter[] { new VerifySendParameter("VerificationCode", code) });
|
|
||||||
Thread.Sleep(2000);
|
|
||||||
|
|
||||||
if (sendResult.Message == "موفق")
|
|
||||||
{
|
|
||||||
var status = sendResult.Status;
|
|
||||||
var message = sendResult.Message;
|
|
||||||
var messaeId = sendResult.Data.MessageId;
|
|
||||||
return result.Succedded(status, message, messaeId);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var status = sendResult.Status;
|
|
||||||
var message = sendResult.Message;
|
|
||||||
var messaeId = sendResult.Data.MessageId;
|
|
||||||
return result.Failed(status, message, messaeId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SendAccountsInfo(string number, string fullName, string userName)
|
|
||||||
{
|
|
||||||
|
|
||||||
var checkLength = fullName.Length;
|
|
||||||
if (checkLength > 25)
|
|
||||||
fullName = fullName.Substring(0, 24);
|
|
||||||
SmsIr smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa");
|
|
||||||
|
|
||||||
var sendResult = smsIr.VerifySendAsync(number, 725814, new VerifySendParameter[] { new VerifySendParameter("FULLNAME", fullName), new VerifySendParameter("USERNAME", userName), new VerifySendParameter("PASSWORD", userName) });
|
|
||||||
|
|
||||||
|
|
||||||
Console.WriteLine(userName + " - " + sendResult.Result.Status);
|
|
||||||
if (sendResult.IsCompletedSuccessfully)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<ApiResultViewModel> GetByMessageId(int messId)
|
|
||||||
{
|
|
||||||
|
|
||||||
SmsIr smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa");
|
|
||||||
var response = await smsIr.GetReportAsync(messId);
|
|
||||||
MessageReportResult messages = response.Data;
|
|
||||||
|
|
||||||
var appendData = new ApiResultViewModel()
|
|
||||||
{
|
|
||||||
MessageId = messages.MessageId,
|
|
||||||
LineNumber = messages.LineNumber,
|
|
||||||
Mobile = messages.Mobile,
|
|
||||||
MessageText = messages.MessageText,
|
|
||||||
SendUnixTime = UnixTimeStampToDateTime(messages.SendDateTime),
|
|
||||||
DeliveryState = DeliveryStatus(messages.DeliveryState),
|
|
||||||
DeliveryUnixTime = UnixTimeStampToDateTime(messages.DeliveryDateTime),
|
|
||||||
DeliveryColor = DeliveryColorStatus(messages.DeliveryState),
|
|
||||||
};
|
|
||||||
return appendData;
|
|
||||||
}
|
|
||||||
public async Task<List<ApiResultViewModel>> GetApiResult(string startDate, string endDate)
|
|
||||||
{
|
|
||||||
var st = new DateTime(2024, 6, 2);
|
|
||||||
var ed = new DateTime(2024, 7, 1);
|
|
||||||
if (!string.IsNullOrWhiteSpace(startDate) && startDate.Length == 10)
|
|
||||||
{
|
|
||||||
st = startDate.ToGeorgianDateTime();
|
|
||||||
}
|
|
||||||
if (!string.IsNullOrWhiteSpace(endDate) && endDate.Length == 10)
|
|
||||||
{
|
|
||||||
ed = endDate.ToGeorgianDateTime();
|
|
||||||
}
|
|
||||||
var res = new List<ApiResultViewModel>();
|
|
||||||
Int32 unixTimestamp = (int)st.Subtract(new DateTime(1970,1,1)).TotalSeconds;
|
|
||||||
Int32 unixTimestamp2 = (int)ed.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
|
|
||||||
// int? fromDateUnixTime = null; // unix time - for instance: 1700598600
|
|
||||||
//int? toDateUnixTime = null; // unix time - for instance: 1703190600
|
|
||||||
int pageNumber = 2;
|
|
||||||
int pageSize = 100; // max: 100
|
|
||||||
SmsIr smsIr = new SmsIr("Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa");
|
|
||||||
var response = await smsIr.GetArchivedReportAsync(pageNumber, pageSize, unixTimestamp, unixTimestamp2);
|
|
||||||
|
|
||||||
|
|
||||||
MessageReportResult[] messages = response.Data;
|
|
||||||
foreach (var message in messages)
|
|
||||||
{
|
|
||||||
var appendData = new ApiResultViewModel()
|
|
||||||
{
|
|
||||||
MessageId = message.MessageId,
|
|
||||||
LineNumber = message.LineNumber,
|
|
||||||
Mobile = message.Mobile,
|
|
||||||
MessageText = message.MessageText,
|
|
||||||
SendUnixTime = UnixTimeStampToDateTime(message.SendDateTime),
|
|
||||||
DeliveryState = DeliveryStatus(message.DeliveryState),
|
|
||||||
DeliveryUnixTime = UnixTimeStampToDateTime(message.DeliveryDateTime),
|
|
||||||
DeliveryColor = DeliveryColorStatus(message.DeliveryState),
|
|
||||||
};
|
|
||||||
res.Add(appendData);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string DeliveryStatus(byte? dv)
|
|
||||||
{
|
|
||||||
string mess = "";
|
|
||||||
switch (dv)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
mess = "رسیده به گوشی";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
mess = "نرسیده به گوشی";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
mess = "پردازش در مخابرات";
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
mess = "نرسیده به مخابرات";
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
mess = "سیده به مخابرات";
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
mess = "خطا";
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
mess = "لیست سیاه";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
mess="";
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return mess;
|
|
||||||
}
|
|
||||||
public string DeliveryColorStatus(byte? dv)
|
|
||||||
{
|
|
||||||
string mess = "";
|
|
||||||
switch (dv)
|
|
||||||
{
|
|
||||||
case 1:
|
|
||||||
mess = "successSend";
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
mess = "errSend";
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
mess = "pSend";
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
mess = "noSend";
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
mess = "itcSend";
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
mess = "redSend";
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
mess = "blockSend";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
mess = "";
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return mess;
|
|
||||||
}
|
|
||||||
public string UnixTimeStampToDateTime(int? unixTimeStamp)
|
|
||||||
{
|
|
||||||
if (unixTimeStamp != null)
|
|
||||||
{
|
|
||||||
// Unix timestamp is seconds past epoch
|
|
||||||
DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
|
|
||||||
dateTime = dateTime.AddSeconds(Convert.ToDouble(unixTimeStamp)).ToLocalTime();
|
|
||||||
var time = dateTime.ToFarsiFull();
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
private string GetToken()
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
//var smsSecrets = _configuration.GetSection("SmsSecrets");
|
|
||||||
//var tokenService = new Token();
|
|
||||||
//return tokenService.GetToken("x-api-key", "Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa");
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Mahan
|
|
||||||
|
|
||||||
public async Task<double> GetCreditAmount()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var credit = await SmsIr.GetCreditAsync();
|
|
||||||
return (double)credit.Data;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
public async Task<bool> SendInstitutionVerificationLink(string number,string fullName, Guid institutionId)
|
|
||||||
{
|
|
||||||
var guidStr=institutionId.ToString();
|
|
||||||
var firstPart = guidStr.Substring(0, 15);
|
|
||||||
var secondPart = guidStr.Substring(15);
|
|
||||||
var verificationSendResult =await SmsIr.VerifySendAsync(number, 527519, new VerifySendParameter[]
|
|
||||||
{
|
|
||||||
new("FULLNAME", fullName),
|
|
||||||
new("CODE1",firstPart),
|
|
||||||
new("CODE2",secondPart)
|
|
||||||
});
|
|
||||||
return verificationSendResult.Status == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<bool> SendInstitutionVerificationCode(string number, string code)
|
|
||||||
{
|
|
||||||
var verificationSendResult =await SmsIr.VerifySendAsync(number, 965348, new VerifySendParameter[]
|
|
||||||
{
|
|
||||||
new("VERIFYCODE", code)
|
|
||||||
});
|
|
||||||
return verificationSendResult.Status == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
@@ -32,7 +32,7 @@ public static class StaticWorkshopAccounts
|
|||||||
/// 392 - عمار حسن دوست
|
/// 392 - عمار حسن دوست
|
||||||
/// 20 - سمیرا الهی نیا
|
/// 20 - سمیرا الهی نیا
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static List<long> StaticAccountIds = [2, 3, 380, 381, 392, 20];
|
public static List<long> StaticAccountIds = [2, 3, 380, 381, 392, 20, 476];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// این تاریخ در جدول اکانت لفت ورک به این معنیست
|
/// این تاریخ در جدول اکانت لفت ورک به این معنیست
|
||||||
|
|||||||
@@ -1512,6 +1512,14 @@ public static class Tools
|
|||||||
#region Mahan
|
#region Mahan
|
||||||
|
|
||||||
|
|
||||||
|
public static bool IsvalidIban(this string iban)
|
||||||
|
{
|
||||||
|
return Regex.IsMatch(iban, @"^IR[0-9]{24}$");
|
||||||
|
}
|
||||||
|
public static bool IsValidCardNumber(this string cardNumber)
|
||||||
|
{
|
||||||
|
return Regex.IsMatch(cardNumber, @"^[0-9]{16}$");
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// این متد حروف عربی را به فارسی در میاورد. مثال: علي را به علی تبدیل میکند
|
/// این متد حروف عربی را به فارسی در میاورد. مثال: علي را به علی تبدیل میکند
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -110,6 +110,53 @@ public interface IUidService
|
|||||||
{
|
{
|
||||||
Task<PersonalInfoResponse> GetPersonalInfo(string nationalCode , string birthDate);
|
Task<PersonalInfoResponse> GetPersonalInfo(string nationalCode , string birthDate);
|
||||||
Task<MatchMobileWithNationalCodeResponse> IsMachPhoneWithNationalCode(string nationalCode , string phoneNumber);
|
Task<MatchMobileWithNationalCodeResponse> IsMachPhoneWithNationalCode(string nationalCode , string phoneNumber);
|
||||||
|
Task<IbanInquiryResponse> IbanInquiry (string iban);
|
||||||
|
Task<AccountToIbanResponse> AccountToIban(string accountNumber, UidBanks bank);
|
||||||
|
Task<CardToNumberResponse> CardToIban(string cardNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CardToNumberResponse:UidBaseResponse
|
||||||
|
{
|
||||||
|
public string Iban { get; set; }
|
||||||
|
public string CardNumber { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AccountToIbanResponse:UidBaseResponse
|
||||||
|
{
|
||||||
|
public string Iban { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IbanInquiryResponse:UidBaseResponse
|
||||||
|
{
|
||||||
|
public IbanInquiryAccountBasicInformation AccountBasicInformation { get; set; }
|
||||||
|
[JsonProperty("owners")]
|
||||||
|
public List<IbanInquiryOwner> Owners { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IbanInquiryAccountBasicInformation
|
||||||
|
{
|
||||||
|
public string Iban { get; set; }
|
||||||
|
public string AccountNumber { get; set; }
|
||||||
|
public IbanInquiryBankInformation BankInformation { get; set; }
|
||||||
|
public string AccountStatus { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IbanInquiryBankInformation
|
||||||
|
{
|
||||||
|
public string BankName { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class IbanInquiryOwner
|
||||||
|
{
|
||||||
|
[JsonProperty("firstName")]
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
[JsonProperty("lastName")]
|
||||||
|
public string LastName { get; set; }
|
||||||
|
[JsonProperty("nationalIdentifier")]
|
||||||
|
public string NationalIdentifier { get; set; }
|
||||||
|
[JsonProperty("customerType")]
|
||||||
|
public string CustomerType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MatchMobileWithNationalCodeResponse
|
public class MatchMobileWithNationalCodeResponse
|
||||||
@@ -118,4 +165,7 @@ public class MatchMobileWithNationalCodeResponse
|
|||||||
|
|
||||||
public ResponseContext ResponseContext { get; set; }
|
public ResponseContext ResponseContext { get; set; }
|
||||||
}
|
}
|
||||||
|
public class UidBaseResponse
|
||||||
|
{
|
||||||
|
public ResponseContext ResponseContext { get; set; }
|
||||||
|
}
|
||||||
|
|||||||
117
0_Framework/Application/UID/UidBanks.cs
Normal file
117
0_Framework/Application/UID/UidBanks.cs
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace _0_Framework.Application.UID;
|
||||||
|
|
||||||
|
public enum UidBanks
|
||||||
|
{
|
||||||
|
[Description("بانک دی")]
|
||||||
|
BANK_DEY = 66,
|
||||||
|
|
||||||
|
[Description("بانک سپه")]
|
||||||
|
BANK_SEPAH = 15,
|
||||||
|
|
||||||
|
[Description("بانک شهر")]
|
||||||
|
BANK_SHAHR = 61,
|
||||||
|
|
||||||
|
[Description("بانک ملت")]
|
||||||
|
BANK_MELAT = 12,
|
||||||
|
|
||||||
|
[Description("بانک ملی")]
|
||||||
|
BANK_MELLI = 17,
|
||||||
|
|
||||||
|
[Description("بانک رفاه کارگران")]
|
||||||
|
BANK_REFAH = 13,
|
||||||
|
|
||||||
|
[Description("بانک سینا")]
|
||||||
|
BANK_SINA = 59,
|
||||||
|
|
||||||
|
[Description("بانک مسکن")]
|
||||||
|
BANK_MASKAN = 14,
|
||||||
|
|
||||||
|
[Description("بانک آینده")]
|
||||||
|
BANK_AYANDEH = 62,
|
||||||
|
|
||||||
|
[Description("بانک انصار")]
|
||||||
|
BANK_ANSAR = 63,
|
||||||
|
|
||||||
|
[Description("بانک تجارت")]
|
||||||
|
BANK_TEJARAT = 18,
|
||||||
|
|
||||||
|
[Description("بانک رسالت")]
|
||||||
|
BANK_RESALAT = 70,
|
||||||
|
|
||||||
|
[Description("بانک سامان")]
|
||||||
|
BANK_SAMAN = 56,
|
||||||
|
|
||||||
|
[Description("بانک مرکزی")]
|
||||||
|
BANK_MARKAZI = 10,
|
||||||
|
|
||||||
|
[Description("بانک سرمایه")]
|
||||||
|
BANK_SARMAYEH = 58,
|
||||||
|
|
||||||
|
[Description("بانک صادرات")]
|
||||||
|
BANK_SADERAT = 19,
|
||||||
|
|
||||||
|
[Description("بانک قوامین")]
|
||||||
|
BANK_GHAVAMIN = 52,
|
||||||
|
|
||||||
|
[Description("بانک پارسیان")]
|
||||||
|
BANK_PARSIAN = 54,
|
||||||
|
|
||||||
|
[Description("بانک کشاورزی")]
|
||||||
|
BANK_KESHAVARZI = 16,
|
||||||
|
|
||||||
|
[Description("بانک گردشگری")]
|
||||||
|
BANK_GARDESHGARI = 64,
|
||||||
|
|
||||||
|
[Description("پست بانک")]
|
||||||
|
BANK_POST_BANK = 21,
|
||||||
|
|
||||||
|
[Description("بانک پاسارگاد")]
|
||||||
|
BANK_PASARGAD = 57,
|
||||||
|
|
||||||
|
[Description("بانک کارآفرین")]
|
||||||
|
BANK_KARAFARIN = 53,
|
||||||
|
|
||||||
|
[Description("بانک خاورمیانه")]
|
||||||
|
BANK_KHAVARMIANEH = 78,
|
||||||
|
|
||||||
|
[Description("بانک ایران زمین")]
|
||||||
|
BANK_IRAN_ZAMIN = 69,
|
||||||
|
|
||||||
|
[Description("بانک مهر اقتصاد")]
|
||||||
|
BANK_MEHR_EQTESAD = 79,
|
||||||
|
|
||||||
|
[Description("بانک صنعت و معدن")]
|
||||||
|
BANK_SANAT_MADAN = 11,
|
||||||
|
|
||||||
|
[Description("بانک اقتصاد نوین")]
|
||||||
|
BANK_EGHTESAD_NOVIN = 55,
|
||||||
|
|
||||||
|
[Description("بانک توسعه تعاون")]
|
||||||
|
BANK_TOSSE_TAAVON = 22,
|
||||||
|
|
||||||
|
[Description("بانک توسعه صادرات")]
|
||||||
|
BANK_TOSSE_SADERAT = 20,
|
||||||
|
|
||||||
|
[Description("بانک ایران و ونزوئلا")]
|
||||||
|
BANK_IRAN_VENEZUELA = 95,
|
||||||
|
|
||||||
|
[Description("بانک حکمت ایرانیان")]
|
||||||
|
BANK_HEKMAT_IRANIAN = 65,
|
||||||
|
|
||||||
|
[Description("بانک قرض الحسنه مهر")]
|
||||||
|
BANK_GHARZOLHASANEH_MEHR = 60,
|
||||||
|
|
||||||
|
[Description("موسسه مالی و اعتباری ملل")]
|
||||||
|
BANK_MOASSASE_MELLAL = 75,
|
||||||
|
|
||||||
|
[Description("موسسه مالی و اعتباری نور")]
|
||||||
|
BANK_MOASSASE_NOOR = 80,
|
||||||
|
|
||||||
|
[Description("موسسه مالی و اعتباری کوثر")]
|
||||||
|
BANK_MOASSASE_KOSAR = 73,
|
||||||
|
|
||||||
|
[Description("موسسه مالی و اعتباری توسعه")]
|
||||||
|
BANK_MOASSASE_TOSSE = 51
|
||||||
|
}
|
||||||
27
0_Framework/Application/UID/UidBanksExtension.cs
Normal file
27
0_Framework/Application/UID/UidBanksExtension.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace _0_Framework.Application.UID
|
||||||
|
{
|
||||||
|
public static class UidBanksExtension
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت نام فارسی بانک
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bank">بانک</param>
|
||||||
|
/// <returns>نام فارسی بانک</returns>
|
||||||
|
public static string GetPersianName(this UidBanks bank)
|
||||||
|
{
|
||||||
|
var fieldInfo = bank.GetType().GetField(bank.ToString());
|
||||||
|
|
||||||
|
if (fieldInfo == null)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
var attribute = (DescriptionAttribute)Attribute.GetCustomAttribute(
|
||||||
|
fieldInfo, typeof(DescriptionAttribute));
|
||||||
|
|
||||||
|
return attribute?.Description ?? bank.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace _0_Framework.Application.Enums
|
||||||
|
{
|
||||||
|
public class CheckoutDynamicDeductionItem
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public int Count { get; set; }
|
||||||
|
public string Amount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
346
0_Framework/InfraStructure/FaceEmbeddingService.cs
Normal file
346
0_Framework/InfraStructure/FaceEmbeddingService.cs
Normal file
@@ -0,0 +1,346 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Net.Http.Json;
|
||||||
|
using System.Text.Json;
|
||||||
|
using _0_Framework.Application;
|
||||||
|
using _0_Framework.Application.FaceEmbedding;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace _0_Framework.Infrastructure;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پیادهسازی سرویس ارتباط با API پایتون برای مدیریت Embeddings چهره
|
||||||
|
/// </summary>
|
||||||
|
public class FaceEmbeddingService : IFaceEmbeddingService
|
||||||
|
{
|
||||||
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
|
private readonly ILogger<FaceEmbeddingService> _logger;
|
||||||
|
private readonly IFaceEmbeddingNotificationService _notificationService;
|
||||||
|
private readonly string _apiBaseUrl;
|
||||||
|
|
||||||
|
public FaceEmbeddingService(IHttpClientFactory httpClientFactory, ILogger<FaceEmbeddingService> logger,
|
||||||
|
IFaceEmbeddingNotificationService notificationService = null)
|
||||||
|
{
|
||||||
|
_httpClientFactory = httpClientFactory;
|
||||||
|
_logger = logger;
|
||||||
|
_notificationService = notificationService;
|
||||||
|
_apiBaseUrl = "http://localhost:8000";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<OperationResult> GenerateEmbeddingsAsync(long employeeId, long workshopId,
|
||||||
|
string employeeFullName, string picture1Path, string picture2Path)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var httpClient = _httpClientFactory.CreateClient();
|
||||||
|
httpClient.BaseAddress = new Uri(_apiBaseUrl);
|
||||||
|
httpClient.Timeout = TimeSpan.FromSeconds(30);
|
||||||
|
|
||||||
|
using var content = new MultipartFormDataContent();
|
||||||
|
|
||||||
|
// Add form fields
|
||||||
|
content.Add(new StringContent(employeeId.ToString()), "employee_id");
|
||||||
|
content.Add(new StringContent(workshopId.ToString()), "workshop_id");
|
||||||
|
content.Add(new StringContent(employeeFullName ?? ""), "employee_full_name");
|
||||||
|
|
||||||
|
// Add picture files
|
||||||
|
if (File.Exists(picture1Path))
|
||||||
|
{
|
||||||
|
var picture1Bytes = await File.ReadAllBytesAsync(picture1Path);
|
||||||
|
var picture1Content = new ByteArrayContent(picture1Bytes);
|
||||||
|
picture1Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
|
||||||
|
content.Add(picture1Content, "picture1", "1.jpg");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Picture1 not found at path: {Path}", picture1Path);
|
||||||
|
return new OperationResult { IsSuccedded = false, Message = "تصویر اول یافت نشد" };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.Exists(picture2Path))
|
||||||
|
{
|
||||||
|
var picture2Bytes = await File.ReadAllBytesAsync(picture2Path);
|
||||||
|
var picture2Content = new ByteArrayContent(picture2Bytes);
|
||||||
|
picture2Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
|
||||||
|
content.Add(picture2Content, "picture2", "2.jpg");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Picture2 not found at path: {Path}", picture2Path);
|
||||||
|
return new OperationResult { IsSuccedded = false, Message = "تصویر دوم یافت نشد" };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send request to Python API
|
||||||
|
var response = await httpClient.PostAsync("embeddings", content);
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
var responseContent = await response.Content.ReadAsStringAsync();
|
||||||
|
_logger.LogInformation("Embeddings generated successfully for Employee {EmployeeId}, Workshop {WorkshopId}",
|
||||||
|
employeeId, workshopId);
|
||||||
|
|
||||||
|
// ارسال اطلاعرسانی به سایر سیستمها
|
||||||
|
if (_notificationService != null)
|
||||||
|
{
|
||||||
|
await _notificationService.NotifyEmbeddingCreatedAsync(workshopId, employeeId, employeeFullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OperationResult
|
||||||
|
{
|
||||||
|
IsSuccedded = true,
|
||||||
|
Message = "Embedding با موفقیت ایجاد شد"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var errorContent = await response.Content.ReadAsStringAsync();
|
||||||
|
_logger.LogError("Failed to generate embeddings. Status: {StatusCode}, Error: {Error}",
|
||||||
|
response.StatusCode, errorContent);
|
||||||
|
|
||||||
|
return new OperationResult
|
||||||
|
{
|
||||||
|
IsSuccedded = false,
|
||||||
|
Message = $"خطا در تولید Embedding: {response.StatusCode}"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (HttpRequestException ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "HTTP error while calling embeddings API for Employee {EmployeeId}", employeeId);
|
||||||
|
return new OperationResult
|
||||||
|
{
|
||||||
|
IsSuccedded = false,
|
||||||
|
Message = "خطا در ارتباط با سرور Embedding"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error while calling embeddings API for Employee {EmployeeId}", employeeId);
|
||||||
|
return new OperationResult
|
||||||
|
{
|
||||||
|
IsSuccedded = false,
|
||||||
|
Message = "خطای غیرمنتظره در تولید Embedding"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<OperationResult> GenerateEmbeddingsFromStreamAsync(long employeeId, long workshopId,
|
||||||
|
string employeeFullName, Stream picture1Stream, Stream picture2Stream)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var httpClient = _httpClientFactory.CreateClient();
|
||||||
|
httpClient.BaseAddress = new Uri(_apiBaseUrl);
|
||||||
|
httpClient.Timeout = TimeSpan.FromSeconds(30);
|
||||||
|
|
||||||
|
using var content = new MultipartFormDataContent();
|
||||||
|
|
||||||
|
// Add form fields
|
||||||
|
content.Add(new StringContent(employeeId.ToString()), "employee_id");
|
||||||
|
content.Add(new StringContent(workshopId.ToString()), "workshop_id");
|
||||||
|
content.Add(new StringContent(employeeFullName ?? ""), "employee_full_name");
|
||||||
|
|
||||||
|
// Add picture streams
|
||||||
|
var picture1Content = new StreamContent(picture1Stream);
|
||||||
|
picture1Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
|
||||||
|
content.Add(picture1Content, "picture1", "1.jpg");
|
||||||
|
|
||||||
|
var picture2Content = new StreamContent(picture2Stream);
|
||||||
|
picture2Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg");
|
||||||
|
content.Add(picture2Content, "picture2", "2.jpg");
|
||||||
|
|
||||||
|
// Send request to Python API
|
||||||
|
var response = await httpClient.PostAsync("embeddings", content);
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Embeddings generated successfully from streams for Employee {EmployeeId}", employeeId);
|
||||||
|
|
||||||
|
// ارسال اطلاعرسانی به سایر سیستمها
|
||||||
|
if (_notificationService != null)
|
||||||
|
{
|
||||||
|
await _notificationService.NotifyEmbeddingCreatedAsync(workshopId, employeeId, employeeFullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OperationResult { IsSuccedded = true, Message = "Embedding با موفقیت ایجاد شد" };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var errorContent = await response.Content.ReadAsStringAsync();
|
||||||
|
_logger.LogError("Failed to generate embeddings from streams. Status: {StatusCode}, Error: {Error}",
|
||||||
|
response.StatusCode, errorContent);
|
||||||
|
|
||||||
|
return new OperationResult
|
||||||
|
{
|
||||||
|
IsSuccedded = false,
|
||||||
|
Message = $"خطا در تولید Embedding: {response.StatusCode}"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error while generating embeddings from streams for Employee {EmployeeId}", employeeId);
|
||||||
|
return new OperationResult
|
||||||
|
{
|
||||||
|
IsSuccedded = false,
|
||||||
|
Message = "خطا در تولید Embedding"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<OperationResult> RefineEmbeddingAsync(long employeeId, long workshopId, float[] embedding,
|
||||||
|
float confidence, Dictionary<string, object> metadata = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var httpClient = _httpClientFactory.CreateClient();
|
||||||
|
httpClient.BaseAddress = new Uri(_apiBaseUrl);
|
||||||
|
httpClient.Timeout = TimeSpan.FromSeconds(30);
|
||||||
|
|
||||||
|
var requestBody = new
|
||||||
|
{
|
||||||
|
employeeId,
|
||||||
|
workshopId,
|
||||||
|
embedding,
|
||||||
|
confidence,
|
||||||
|
metadata = metadata ?? new Dictionary<string, object>()
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await httpClient.PostAsJsonAsync("embeddings/refine", requestBody);
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Embedding refined successfully for Employee {EmployeeId}", employeeId);
|
||||||
|
|
||||||
|
// ارسال اطلاعرسانی به سایر سیستمها
|
||||||
|
if (_notificationService != null)
|
||||||
|
{
|
||||||
|
await _notificationService.NotifyEmbeddingRefinedAsync(workshopId, employeeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OperationResult { IsSuccedded = true, Message = "Embedding بهبود یافت" };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var errorContent = await response.Content.ReadAsStringAsync();
|
||||||
|
_logger.LogError("Failed to refine embedding. Status: {StatusCode}, Error: {Error}",
|
||||||
|
response.StatusCode, errorContent);
|
||||||
|
|
||||||
|
return new OperationResult
|
||||||
|
{
|
||||||
|
IsSuccedded = false,
|
||||||
|
Message = $"خطا در بهبود Embedding: {response.StatusCode}"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error while refining embedding for Employee {EmployeeId}", employeeId);
|
||||||
|
return new OperationResult
|
||||||
|
{
|
||||||
|
IsSuccedded = false,
|
||||||
|
Message = "خطا در بهبود Embedding"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<OperationResult> DeleteEmbeddingAsync(long employeeId, long workshopId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var httpClient = _httpClientFactory.CreateClient();
|
||||||
|
httpClient.BaseAddress = new Uri(_apiBaseUrl);
|
||||||
|
httpClient.Timeout = TimeSpan.FromSeconds(30);
|
||||||
|
|
||||||
|
var response = await httpClient.DeleteAsync($"embeddings/{workshopId}/{employeeId}");
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Embedding deleted successfully for Employee {EmployeeId}", employeeId);
|
||||||
|
|
||||||
|
// ارسال اطلاعرسانی به سایر سیستمها
|
||||||
|
if (_notificationService != null)
|
||||||
|
{
|
||||||
|
await _notificationService.NotifyEmbeddingDeletedAsync(workshopId, employeeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new OperationResult { IsSuccedded = true, Message = "Embedding حذف شد" };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var errorContent = await response.Content.ReadAsStringAsync();
|
||||||
|
_logger.LogError("Failed to delete embedding. Status: {StatusCode}, Error: {Error}",
|
||||||
|
response.StatusCode, errorContent);
|
||||||
|
|
||||||
|
return new OperationResult
|
||||||
|
{
|
||||||
|
IsSuccedded = false,
|
||||||
|
Message = $"خطا در حذف Embedding: {response.StatusCode}"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error while deleting embedding for Employee {EmployeeId}", employeeId);
|
||||||
|
return new OperationResult
|
||||||
|
{
|
||||||
|
IsSuccedded = false,
|
||||||
|
Message = "خطا در حذف Embedding"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<OperationResult<FaceEmbeddingResponse>> GetEmbeddingAsync(long employeeId, long workshopId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var httpClient = _httpClientFactory.CreateClient();
|
||||||
|
httpClient.BaseAddress = new Uri(_apiBaseUrl);
|
||||||
|
httpClient.Timeout = TimeSpan.FromSeconds(30);
|
||||||
|
|
||||||
|
var response = await httpClient.GetAsync($"embeddings/{workshopId}/{employeeId}");
|
||||||
|
|
||||||
|
if (response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
var content = await response.Content.ReadAsStringAsync();
|
||||||
|
var embeddingData = JsonSerializer.Deserialize<FaceEmbeddingResponse>(content,
|
||||||
|
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||||
|
|
||||||
|
_logger.LogInformation("Embedding retrieved successfully for Employee {EmployeeId}", employeeId);
|
||||||
|
|
||||||
|
return new OperationResult<FaceEmbeddingResponse>
|
||||||
|
{
|
||||||
|
IsSuccedded = true,
|
||||||
|
Message = "Embedding دریافت شد",
|
||||||
|
Data = embeddingData
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var errorContent = await response.Content.ReadAsStringAsync();
|
||||||
|
_logger.LogError("Failed to get embedding. Status: {StatusCode}, Error: {Error}",
|
||||||
|
response.StatusCode, errorContent);
|
||||||
|
|
||||||
|
return new OperationResult<FaceEmbeddingResponse>
|
||||||
|
{
|
||||||
|
IsSuccedded = false,
|
||||||
|
Message = $"خطا در دریافت Embedding: {response.StatusCode}"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error while getting embedding for Employee {EmployeeId}", employeeId);
|
||||||
|
return new OperationResult<FaceEmbeddingResponse>
|
||||||
|
{
|
||||||
|
IsSuccedded = false,
|
||||||
|
Message = "خطا در دریافت Embedding"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using _0_Framework.Application.FaceEmbedding;
|
||||||
|
|
||||||
|
namespace _0_Framework.InfraStructure;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پیادهسازی پیشفرض (بدون عملیات) برای IFaceEmbeddingNotificationService
|
||||||
|
/// این کلاس زمانی استفاده میشود که SignalR در دسترس نباشد
|
||||||
|
/// </summary>
|
||||||
|
public class NullFaceEmbeddingNotificationService : IFaceEmbeddingNotificationService
|
||||||
|
{
|
||||||
|
public Task NotifyEmbeddingCreatedAsync(long workshopId, long employeeId, string employeeFullName)
|
||||||
|
{
|
||||||
|
// هیچ عملیاتی انجام نمیدهد
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task NotifyEmbeddingDeletedAsync(long workshopId, long employeeId)
|
||||||
|
{
|
||||||
|
// هیچ عملیاتی انجام نمیدهد
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task NotifyEmbeddingRefinedAsync(long workshopId, long employeeId)
|
||||||
|
{
|
||||||
|
// هیچ عملیاتی انجام نمیدهد
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
624
ANDROID_SIGNALR_GUIDE.md
Normal file
624
ANDROID_SIGNALR_GUIDE.md
Normal file
@@ -0,0 +1,624 @@
|
|||||||
|
# راهنمای اتصال اپلیکیشن Android به SignalR برای Face Embedding
|
||||||
|
|
||||||
|
## 1. افزودن کتابخانه SignalR به پروژه Android
|
||||||
|
|
||||||
|
در فایل `build.gradle` (Module: app) خود، dependency زیر را اضافه کنید:
|
||||||
|
|
||||||
|
```gradle
|
||||||
|
dependencies {
|
||||||
|
// SignalR for Android
|
||||||
|
implementation 'com.microsoft.signalr:signalr:7.0.0'
|
||||||
|
|
||||||
|
// اگر از Kotlin استفاده میکنید:
|
||||||
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1'
|
||||||
|
|
||||||
|
// برای JSON پردازش:
|
||||||
|
implementation 'com.google.code.gson:gson:2.10.1'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. اضافه کردن Permission در AndroidManifest.xml
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. کد Java/Kotlin برای اتصال به SignalR
|
||||||
|
|
||||||
|
### نسخه Java:
|
||||||
|
|
||||||
|
```java
|
||||||
|
import com.microsoft.signalr.HubConnection;
|
||||||
|
import com.microsoft.signalr.HubConnectionBuilder;
|
||||||
|
import com.microsoft.signalr.HubConnectionState;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
public class FaceEmbeddingSignalRClient {
|
||||||
|
private static final String TAG = "FaceEmbeddingHub";
|
||||||
|
private HubConnection hubConnection;
|
||||||
|
private String serverUrl = "http://YOUR_SERVER_IP:PORT/trackingFaceEmbeddingHub"; // آدرس سرور خود را وارد کنید
|
||||||
|
private long workshopId;
|
||||||
|
|
||||||
|
public FaceEmbeddingSignalRClient(long workshopId) {
|
||||||
|
this.workshopId = workshopId;
|
||||||
|
initializeSignalR();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initializeSignalR() {
|
||||||
|
// ایجاد اتصال SignalR
|
||||||
|
hubConnection = HubConnectionBuilder
|
||||||
|
.create(serverUrl)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// دریافت رویداد ایجاد Embedding
|
||||||
|
hubConnection.on("EmbeddingCreated", (data) -> {
|
||||||
|
JsonObject jsonData = (JsonObject) data;
|
||||||
|
long employeeId = jsonData.get("employeeId").getAsLong();
|
||||||
|
String employeeFullName = jsonData.get("employeeFullName").getAsString();
|
||||||
|
String timestamp = jsonData.get("timestamp").getAsString();
|
||||||
|
|
||||||
|
Log.d(TAG, "Embedding Created - Employee: " + employeeFullName + " (ID: " + employeeId + ")");
|
||||||
|
|
||||||
|
// اینجا میتوانید دادههای جدید را از سرور بگیرید یا UI را بروزرسانی کنید
|
||||||
|
onEmbeddingCreated(employeeId, employeeFullName, timestamp);
|
||||||
|
|
||||||
|
}, JsonObject.class);
|
||||||
|
|
||||||
|
// دریافت رویداد حذف Embedding
|
||||||
|
hubConnection.on("EmbeddingDeleted", (data) -> {
|
||||||
|
JsonObject jsonData = (JsonObject) data;
|
||||||
|
long employeeId = jsonData.get("employeeId").getAsLong();
|
||||||
|
String timestamp = jsonData.get("timestamp").getAsString();
|
||||||
|
|
||||||
|
Log.d(TAG, "Embedding Deleted - Employee ID: " + employeeId);
|
||||||
|
onEmbeddingDeleted(employeeId, timestamp);
|
||||||
|
|
||||||
|
}, JsonObject.class);
|
||||||
|
|
||||||
|
// دریافت رویداد بهبود Embedding
|
||||||
|
hubConnection.on("EmbeddingRefined", (data) -> {
|
||||||
|
JsonObject jsonData = (JsonObject) data;
|
||||||
|
long employeeId = jsonData.get("employeeId").getAsLong();
|
||||||
|
String timestamp = jsonData.get("timestamp").getAsString();
|
||||||
|
|
||||||
|
Log.d(TAG, "Embedding Refined - Employee ID: " + employeeId);
|
||||||
|
onEmbeddingRefined(employeeId, timestamp);
|
||||||
|
|
||||||
|
}, JsonObject.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect() {
|
||||||
|
if (hubConnection.getConnectionState() == HubConnectionState.DISCONNECTED) {
|
||||||
|
hubConnection.start()
|
||||||
|
.doOnComplete(() -> {
|
||||||
|
Log.d(TAG, "Connected to SignalR Hub");
|
||||||
|
joinWorkshopGroup();
|
||||||
|
})
|
||||||
|
.doOnError(error -> {
|
||||||
|
Log.e(TAG, "Error connecting to SignalR: " + error.getMessage());
|
||||||
|
})
|
||||||
|
.subscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void joinWorkshopGroup() {
|
||||||
|
// عضویت در گروه مخصوص این کارگاه
|
||||||
|
hubConnection.send("JoinWorkshopGroup", workshopId);
|
||||||
|
Log.d(TAG, "Joined workshop group: " + workshopId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disconnect() {
|
||||||
|
if (hubConnection.getConnectionState() == HubConnectionState.CONNECTED) {
|
||||||
|
// خروج از گروه
|
||||||
|
hubConnection.send("LeaveWorkshopGroup", workshopId);
|
||||||
|
|
||||||
|
hubConnection.stop();
|
||||||
|
Log.d(TAG, "Disconnected from SignalR Hub");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// این متدها را در Activity/Fragment خود override کنید
|
||||||
|
protected void onEmbeddingCreated(long employeeId, String employeeFullName, String timestamp) {
|
||||||
|
// اینجا UI را بروزرسانی کنید یا داده جدید را بگیرید
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onEmbeddingDeleted(long employeeId, String timestamp) {
|
||||||
|
// اینجا UI را بروزرسانی کنید
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onEmbeddingRefined(long employeeId, String timestamp) {
|
||||||
|
// اینجا UI را بروزرسانی کنید
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### نسخه Kotlin:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
import com.microsoft.signalr.HubConnection
|
||||||
|
import com.microsoft.signalr.HubConnectionBuilder
|
||||||
|
import com.microsoft.signalr.HubConnectionState
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import android.util.Log
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class FaceEmbeddingSignalRClient(private val workshopId: Long) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "FaceEmbeddingHub"
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var hubConnection: HubConnection
|
||||||
|
private val serverUrl = "http://YOUR_SERVER_IP:PORT/trackingFaceEmbeddingHub" // آدرس سرور خود را وارد کنید
|
||||||
|
|
||||||
|
init {
|
||||||
|
initializeSignalR()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initializeSignalR() {
|
||||||
|
hubConnection = HubConnectionBuilder
|
||||||
|
.create(serverUrl)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
// دریافت رویداد ایجاد Embedding
|
||||||
|
hubConnection.on("EmbeddingCreated", { data: JsonObject ->
|
||||||
|
val employeeId = data.get("employeeId").asLong
|
||||||
|
val employeeFullName = data.get("employeeFullName").asString
|
||||||
|
val timestamp = data.get("timestamp").asString
|
||||||
|
|
||||||
|
Log.d(TAG, "Embedding Created - Employee: $employeeFullName (ID: $employeeId)")
|
||||||
|
onEmbeddingCreated(employeeId, employeeFullName, timestamp)
|
||||||
|
}, JsonObject::class.java)
|
||||||
|
|
||||||
|
// دریافت رویداد حذف Embedding
|
||||||
|
hubConnection.on("EmbeddingDeleted", { data: JsonObject ->
|
||||||
|
val employeeId = data.get("employeeId").asLong
|
||||||
|
val timestamp = data.get("timestamp").asString
|
||||||
|
|
||||||
|
Log.d(TAG, "Embedding Deleted - Employee ID: $employeeId")
|
||||||
|
onEmbeddingDeleted(employeeId, timestamp)
|
||||||
|
}, JsonObject::class.java)
|
||||||
|
|
||||||
|
// دریافت رویداد بهبود Embedding
|
||||||
|
hubConnection.on("EmbeddingRefined", { data: JsonObject ->
|
||||||
|
val employeeId = data.get("employeeId").asLong
|
||||||
|
val timestamp = data.get("timestamp").asString
|
||||||
|
|
||||||
|
Log.d(TAG, "Embedding Refined - Employee ID: $employeeId")
|
||||||
|
onEmbeddingRefined(employeeId, timestamp)
|
||||||
|
}, JsonObject::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun connect() {
|
||||||
|
if (hubConnection.connectionState == HubConnectionState.DISCONNECTED) {
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
try {
|
||||||
|
hubConnection.start().blockingAwait()
|
||||||
|
Log.d(TAG, "Connected to SignalR Hub")
|
||||||
|
joinWorkshopGroup()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Error connecting to SignalR: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun joinWorkshopGroup() {
|
||||||
|
hubConnection.send("JoinWorkshopGroup", workshopId)
|
||||||
|
Log.d(TAG, "Joined workshop group: $workshopId")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun disconnect() {
|
||||||
|
if (hubConnection.connectionState == HubConnectionState.CONNECTED) {
|
||||||
|
hubConnection.send("LeaveWorkshopGroup", workshopId)
|
||||||
|
hubConnection.stop()
|
||||||
|
Log.d(TAG, "Disconnected from SignalR Hub")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// این متدها را override کنید
|
||||||
|
open fun onEmbeddingCreated(employeeId: Long, employeeFullName: String, timestamp: String) {
|
||||||
|
// اینجا UI را بروزرسانی کنید یا داده جدید را بگیرید
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun onEmbeddingDeleted(employeeId: Long, timestamp: String) {
|
||||||
|
// اینجا UI را بروزرسانی کنید
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun onEmbeddingRefined(employeeId: Long, timestamp: String) {
|
||||||
|
// اینجا UI را بروزرسانی کنید
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4. استفاده در Activity یا Fragment
|
||||||
|
|
||||||
|
### مثال با Login و دریافت WorkshopId
|
||||||
|
|
||||||
|
#### Java:
|
||||||
|
```java
|
||||||
|
public class LoginActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_login);
|
||||||
|
|
||||||
|
Button btnLogin = findViewById(R.id.btnLogin);
|
||||||
|
btnLogin.setOnClickListener(v -> performLogin());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performLogin() {
|
||||||
|
// فراخوانی API لاگین
|
||||||
|
// فرض کنید response شامل workshopId است
|
||||||
|
|
||||||
|
// مثال ساده (باید از Retrofit یا کتابخانه مشابه استفاده کنید):
|
||||||
|
// LoginResponse response = apiService.login(username, password);
|
||||||
|
// long workshopId = response.getWorkshopId();
|
||||||
|
|
||||||
|
long workshopId = 123; // این را از response دریافت کنید
|
||||||
|
|
||||||
|
// ذخیره workshopId
|
||||||
|
SharedPreferences prefs = getSharedPreferences("AppPrefs", MODE_PRIVATE);
|
||||||
|
prefs.edit().putLong("workshopId", workshopId).apply();
|
||||||
|
|
||||||
|
// رفتن به صفحه اصلی
|
||||||
|
Intent intent = new Intent(this, MainActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
private FaceEmbeddingSignalRClient signalRClient;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
|
// دریافت workshopId از SharedPreferences
|
||||||
|
SharedPreferences prefs = getSharedPreferences("AppPrefs", MODE_PRIVATE);
|
||||||
|
long workshopId = prefs.getLong("workshopId", 0);
|
||||||
|
|
||||||
|
if (workshopId == 0) {
|
||||||
|
// اگر workshopId وجود نداره، برگرد به صفحه لاگین
|
||||||
|
Intent intent = new Intent(this, LoginActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ایجاد و اتصال SignalR
|
||||||
|
signalRClient = new FaceEmbeddingSignalRClient(workshopId) {
|
||||||
|
@Override
|
||||||
|
protected void onEmbeddingCreated(long employeeId, String employeeFullName, String timestamp) {
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
// بروزرسانی UI
|
||||||
|
Toast.makeText(MainActivity.this,
|
||||||
|
"Embedding ایجاد شد برای: " + employeeFullName,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
|
// دریافت دادههای جدید از API
|
||||||
|
refreshEmployeeList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onEmbeddingDeleted(long employeeId, String timestamp) {
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
// بروزرسانی UI
|
||||||
|
refreshEmployeeList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onEmbeddingRefined(long employeeId, String timestamp) {
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
// بروزرسانی UI
|
||||||
|
refreshEmployeeList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
signalRClient.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if (signalRClient != null) {
|
||||||
|
signalRClient.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshEmployeeList() {
|
||||||
|
// دریافت لیست جدید کارمندان از API
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Kotlin:
|
||||||
|
```kotlin
|
||||||
|
class LoginActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_login)
|
||||||
|
|
||||||
|
val btnLogin = findViewById<Button>(R.id.btnLogin)
|
||||||
|
btnLogin.setOnClickListener { performLogin() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun performLogin() {
|
||||||
|
// فراخوانی API لاگین
|
||||||
|
// فرض کنید response شامل workshopId است
|
||||||
|
|
||||||
|
// مثال ساده (باید از Retrofit یا کتابخانه مشابه استفاده کنید):
|
||||||
|
// val response = apiService.login(username, password)
|
||||||
|
// val workshopId = response.workshopId
|
||||||
|
|
||||||
|
val workshopId = 123L // این را از response دریافت کنید
|
||||||
|
|
||||||
|
// ذخیره workshopId
|
||||||
|
val prefs = getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
|
||||||
|
prefs.edit().putLong("workshopId", workshopId).apply()
|
||||||
|
|
||||||
|
// رفتن به صفحه اصلی
|
||||||
|
val intent = Intent(this, MainActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainActivity : AppCompatActivity() {
|
||||||
|
private lateinit var signalRClient: FaceEmbeddingSignalRClient
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
|
// دریافت workshopId از SharedPreferences
|
||||||
|
val prefs = getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
|
||||||
|
val workshopId = prefs.getLong("workshopId", 0L)
|
||||||
|
|
||||||
|
if (workshopId == 0L) {
|
||||||
|
// اگر workshopId وجود نداره، برگرد به صفحه لاگین
|
||||||
|
val intent = Intent(this, LoginActivity::class.java)
|
||||||
|
startActivity(intent)
|
||||||
|
finish()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ایجاد و اتصال SignalR
|
||||||
|
signalRClient = object : FaceEmbeddingSignalRClient(workshopId) {
|
||||||
|
override fun onEmbeddingCreated(employeeId: Long, employeeFullName: String, timestamp: String) {
|
||||||
|
runOnUiThread {
|
||||||
|
// بروزرسانی UI
|
||||||
|
Toast.makeText(this@MainActivity,
|
||||||
|
"Embedding ایجاد شد برای: $employeeFullName",
|
||||||
|
Toast.LENGTH_SHORT).show()
|
||||||
|
|
||||||
|
// دریافت دادههای جدید از API
|
||||||
|
refreshEmployeeList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onEmbeddingDeleted(employeeId: Long, timestamp: String) {
|
||||||
|
runOnUiThread {
|
||||||
|
// بروزرسانی UI
|
||||||
|
refreshEmployeeList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onEmbeddingRefined(employeeId: Long, timestamp: String) {
|
||||||
|
runOnUiThread {
|
||||||
|
// بروزرسانی UI
|
||||||
|
refreshEmployeeList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signalRClient.connect()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
signalRClient.disconnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshEmployeeList() {
|
||||||
|
// دریافت لیست جدید کارمندان از API
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### مثال ساده بدون Login:
|
||||||
|
اگر workshopId را از قبل میدانید:
|
||||||
|
|
||||||
|
#### Java:
|
||||||
|
```java
|
||||||
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
private FaceEmbeddingSignalRClient signalRClient;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
|
long workshopId = 123; // شناسه کارگاه خود را وارد کنید
|
||||||
|
|
||||||
|
signalRClient = new FaceEmbeddingSignalRClient(workshopId) {
|
||||||
|
@Override
|
||||||
|
protected void onEmbeddingCreated(long employeeId, String employeeFullName, String timestamp) {
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
// بروزرسانی UI
|
||||||
|
Toast.makeText(MainActivity.this,
|
||||||
|
"Embedding ایجاد شد برای: " + employeeFullName,
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
|
// دریافت دادههای جدید از API
|
||||||
|
refreshEmployeeList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onEmbeddingDeleted(long employeeId, String timestamp) {
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
// بروزرسانی UI
|
||||||
|
refreshEmployeeList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
signalRClient.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
if (signalRClient != null) {
|
||||||
|
signalRClient.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshEmployeeList() {
|
||||||
|
// دریافت لیست جدید کارمندان از API
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Kotlin:
|
||||||
|
```kotlin
|
||||||
|
class MainActivity : AppCompatActivity() {
|
||||||
|
private lateinit var signalRClient: FaceEmbeddingSignalRClient
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
|
val workshopId = 123L // شناسه کارگاه خود را وارد کنید
|
||||||
|
|
||||||
|
signalRClient = object : FaceEmbeddingSignalRClient(workshopId) {
|
||||||
|
override fun onEmbeddingCreated(employeeId: Long, employeeFullName: String, timestamp: String) {
|
||||||
|
runOnUiThread {
|
||||||
|
// بروزرسانی UI
|
||||||
|
Toast.makeText(this@MainActivity,
|
||||||
|
"Embedding ایجاد شد برای: $employeeFullName",
|
||||||
|
Toast.LENGTH_SHORT).show()
|
||||||
|
|
||||||
|
// دریافت دادههای جدید از API
|
||||||
|
refreshEmployeeList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onEmbeddingDeleted(employeeId: Long, timestamp: String) {
|
||||||
|
runOnUiThread {
|
||||||
|
// بروزرسانی UI
|
||||||
|
refreshEmployeeList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
signalRClient.connect()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
signalRClient.disconnect()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshEmployeeList() {
|
||||||
|
// دریافت لیست جدید کارمندان از API
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. نکات مهم
|
||||||
|
|
||||||
|
### آدرس سرور
|
||||||
|
- اگر روی شبیهساز اندروید تست میکنید و سرور روی localhost اجرا میشود، از آدرس `http://10.0.2.2:PORT` استفاده کنید
|
||||||
|
- اگر روی دستگاه فیزیکی تست میکنید، از آدرس IP شبکه محلی سرور استفاده کنید (مثل `http://192.168.1.100:PORT`)
|
||||||
|
- PORT پیشفرض معمولاً 5000 یا 5001 است (بسته به کانفیگ پروژه شما)
|
||||||
|
|
||||||
|
### دریافت WorkshopId از Login
|
||||||
|
بعد از login موفق، workshopId را از سرور دریافت کنید و در SharedPreferences یا یک Singleton ذخیره کنید:
|
||||||
|
|
||||||
|
```java
|
||||||
|
// بعد از login موفق
|
||||||
|
SharedPreferences prefs = getSharedPreferences("AppPrefs", MODE_PRIVATE);
|
||||||
|
prefs.edit().putLong("workshopId", workshopId).apply();
|
||||||
|
|
||||||
|
// استفاده در Activity
|
||||||
|
long workshopId = prefs.getLong("workshopId", 0);
|
||||||
|
```
|
||||||
|
|
||||||
|
یا در Kotlin:
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// بعد از login موفق
|
||||||
|
val prefs = getSharedPreferences("AppPrefs", Context.MODE_PRIVATE)
|
||||||
|
prefs.edit().putLong("workshopId", workshopId).apply()
|
||||||
|
|
||||||
|
// استفاده در Activity
|
||||||
|
val workshopId = prefs.getLong("workshopId", 0L)
|
||||||
|
```
|
||||||
|
|
||||||
|
### مدیریت اتصال
|
||||||
|
برای reconnection خودکار:
|
||||||
|
|
||||||
|
```java
|
||||||
|
hubConnection.onClosed(exception -> {
|
||||||
|
Log.e(TAG, "Connection closed. Attempting to reconnect...");
|
||||||
|
new Handler().postDelayed(() -> connect(), 5000); // تلاش مجدد بعد از 5 ثانیه
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Thread Safety
|
||||||
|
همیشه UI updates را در main thread انجام دهید:
|
||||||
|
|
||||||
|
```java
|
||||||
|
runOnUiThread(() -> {
|
||||||
|
// UI updates here
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## 6. تست اتصال
|
||||||
|
|
||||||
|
برای تست میتوانید:
|
||||||
|
1. اپلیکیشن را اجرا کنید
|
||||||
|
2. از طریق Postman یا Swagger یک Embedding ایجاد کنید
|
||||||
|
3. باید در Logcat پیام "Embedding Created" را ببینید
|
||||||
|
|
||||||
|
## 7. خطایابی (Debugging)
|
||||||
|
|
||||||
|
برای دیدن جزئیات بیشتر:
|
||||||
|
|
||||||
|
```java
|
||||||
|
hubConnection = HubConnectionBuilder
|
||||||
|
.create(serverUrl)
|
||||||
|
.withHttpConnectionOptions(options -> {
|
||||||
|
options.setLogging(LogLevel.TRACE);
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## خلاصه Endpoints
|
||||||
|
|
||||||
|
| نوع رویداد | متد SignalR | پارامترهای دریافتی |
|
||||||
|
|-----------|-------------|---------------------|
|
||||||
|
| ایجاد Embedding | `EmbeddingCreated` | workshopId, employeeId, employeeFullName, timestamp |
|
||||||
|
| حذف Embedding | `EmbeddingDeleted` | workshopId, employeeId, timestamp |
|
||||||
|
| بهبود Embedding | `EmbeddingRefined` | workshopId, employeeId, timestamp |
|
||||||
|
|
||||||
|
| متد ارسالی | پارامتر | توضیحات |
|
||||||
|
|-----------|---------|---------|
|
||||||
|
| `JoinWorkshopGroup` | workshopId | عضویت در گروه کارگاه |
|
||||||
|
| `LeaveWorkshopGroup` | workshopId | خروج از گروه کارگاه |
|
||||||
|
|
||||||
@@ -66,4 +66,11 @@ public interface IAccountApplication
|
|||||||
public bool CheckExistClientAccount(string userName);
|
public bool CheckExistClientAccount(string userName);
|
||||||
List<AccountViewModel> GetAdminAccountsNew();
|
List<AccountViewModel> GetAdminAccountsNew();
|
||||||
|
|
||||||
|
void CameraLogin(CameraLoginRequest request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CameraLoginRequest
|
||||||
|
{
|
||||||
|
public string UserName { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,7 @@ using Microsoft.AspNetCore.Mvc.Rendering;
|
|||||||
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
|
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
|
||||||
using Company.Domain.WorkshopAgg;
|
using Company.Domain.WorkshopAgg;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using _0_Framework.Exceptions;
|
||||||
using AccountManagement.Domain.PositionAgg;
|
using AccountManagement.Domain.PositionAgg;
|
||||||
using AccountManagement.Domain.SubAccountAgg;
|
using AccountManagement.Domain.SubAccountAgg;
|
||||||
using AccountManagement.Domain.SubAccountPermissionSubtitle1Agg;
|
using AccountManagement.Domain.SubAccountPermissionSubtitle1Agg;
|
||||||
@@ -803,4 +804,29 @@ public class AccountApplication : IAccountApplication
|
|||||||
{
|
{
|
||||||
return _accountRepository.GetAdminAccountsNew();
|
return _accountRepository.GetAdminAccountsNew();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CameraLogin(CameraLoginRequest request)
|
||||||
|
{
|
||||||
|
var cameraAccount = _cameraAccountRepository.GetBy(request.UserName);
|
||||||
|
|
||||||
|
if (cameraAccount == null)
|
||||||
|
{
|
||||||
|
throw new BadRequestException(ApplicationMessages.WrongUserPass);
|
||||||
|
}
|
||||||
|
|
||||||
|
(bool Verified, bool NeedUpgrade) result = _passwordHasher.Check(cameraAccount.Password, request.Password);
|
||||||
|
|
||||||
|
if (!result.Verified)
|
||||||
|
throw new BadRequestException(ApplicationMessages.WrongUserPass);
|
||||||
|
|
||||||
|
var mobile = string.IsNullOrWhiteSpace(cameraAccount.Mobile) ? " " : cameraAccount.Mobile;
|
||||||
|
|
||||||
|
var authViewModel = new CameraAuthViewModel(cameraAccount.id, cameraAccount.WorkshopId,
|
||||||
|
cameraAccount.Username, mobile, cameraAccount.WorkshopName, cameraAccount.AccountId,
|
||||||
|
cameraAccount.IsActiveSting);
|
||||||
|
if (cameraAccount.IsActiveSting != "true")
|
||||||
|
throw new BadRequestException(ApplicationMessages.WrongUserPass);
|
||||||
|
|
||||||
|
_authHelper.CameraSignIn(authViewModel);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using AccountManagement.Domain.AccountAgg;
|
using AccountManagement.Domain.AccountAgg;
|
||||||
using AccountMangement.Infrastructure.EFCore.Mappings;
|
using AccountMangement.Infrastructure.EFCore.Mappings;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System;
|
using System;
|
||||||
@@ -26,7 +26,6 @@ using AccountManagement.Domain.SubAccountPermissionSubtitle2Agg;
|
|||||||
using AccountManagement.Domain.SubAccountPermissionSubtitle3Agg;
|
using AccountManagement.Domain.SubAccountPermissionSubtitle3Agg;
|
||||||
using AccountManagement.Domain.SubAccountPermissionSubtitle4Agg;
|
using AccountManagement.Domain.SubAccountPermissionSubtitle4Agg;
|
||||||
using AccountManagement.Domain.SubAccountRoleAgg;
|
using AccountManagement.Domain.SubAccountRoleAgg;
|
||||||
using AccountMangement.Infrastructure.EFCore.Seed;
|
|
||||||
using AccountManagement.Domain.TaskScheduleAgg;
|
using AccountManagement.Domain.TaskScheduleAgg;
|
||||||
|
|
||||||
namespace AccountMangement.Infrastructure.EFCore
|
namespace AccountMangement.Infrastructure.EFCore
|
||||||
@@ -60,9 +59,10 @@ namespace AccountMangement.Infrastructure.EFCore
|
|||||||
|
|
||||||
public DbSet<TaskSchedule> TaskSchedules { get; set; }
|
public DbSet<TaskSchedule> TaskSchedules { get; set; }
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region Pooya
|
#region Pooya
|
||||||
public DbSet<SubAccount> SubAccounts { get; set; }
|
public DbSet<SubAccount> SubAccounts { get; set; }
|
||||||
public DbSet<SubAccountRole> SubAccountRoles { get; set; }
|
public DbSet<SubAccountRole> SubAccountRoles { get; set; }
|
||||||
|
|||||||
@@ -18,4 +18,8 @@
|
|||||||
<ProjectReference Include="..\Company.Domain\Company.Domain.csproj" />
|
<ProjectReference Include="..\Company.Domain\Company.Domain.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="Mappings\BugReportMapping.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
175
BUG_REPORT_SYSTEM.md
Normal file
175
BUG_REPORT_SYSTEM.md
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
# سیستم گزارش خرابی (Bug Report System)
|
||||||
|
|
||||||
|
## نمای کلی
|
||||||
|
|
||||||
|
این سیستم برای جمعآوری، ذخیره و مدیریت گزارشهای خرابی از تطبیق موبایلی طراحی شده است.
|
||||||
|
|
||||||
|
## ساختار فایلها
|
||||||
|
|
||||||
|
### Domain Layer
|
||||||
|
- `AccountManagement.Domain/BugReportAgg/`
|
||||||
|
- `BugReport.cs` - موجودیت اصلی
|
||||||
|
- `BugReportLog.cs` - لاگهای گزارش
|
||||||
|
- `BugReportScreenshot.cs` - تصاویر ضمیمه شده
|
||||||
|
|
||||||
|
### Application Contracts
|
||||||
|
- `AccountManagement.Application.Contracts/BugReport/`
|
||||||
|
- `IBugReportApplication.cs` - اینترفیس سرویس
|
||||||
|
- `CreateBugReportCommand.cs` - درخواست ایجاد
|
||||||
|
- `EditBugReportCommand.cs` - درخواست ویرایش
|
||||||
|
- `BugReportViewModel.cs` - نمایش لیست
|
||||||
|
- `BugReportDetailViewModel.cs` - نمایش جزئیات
|
||||||
|
- `IBugReportRepository.cs` - اینترفیس Repository
|
||||||
|
|
||||||
|
### Application Service
|
||||||
|
- `AccountManagement.Application/BugReportApplication.cs` - پیادهسازی سرویس
|
||||||
|
|
||||||
|
### Infrastructure
|
||||||
|
- `AccountMangement.Infrastructure.EFCore/`
|
||||||
|
- `Mappings/BugReportMapping.cs`
|
||||||
|
- `Mappings/BugReportLogMapping.cs`
|
||||||
|
- `Mappings/BugReportScreenshotMapping.cs`
|
||||||
|
- `Repository/BugReportRepository.cs`
|
||||||
|
|
||||||
|
### API Controller
|
||||||
|
- `ServiceHost/Controllers/BugReportController.cs`
|
||||||
|
|
||||||
|
### Admin Pages
|
||||||
|
- `ServiceHost/Areas/AdminNew/Pages/BugReport/`
|
||||||
|
- `BugReportPageModel.cs` - base model
|
||||||
|
- `Index.cshtml.cs / Index.cshtml` - لیست گزارشها
|
||||||
|
- `Details.cshtml.cs / Details.cshtml` - جزئیات کامل
|
||||||
|
- `Edit.cshtml.cs / Edit.cshtml` - ویرایش وضعیت/اولویت
|
||||||
|
- `Delete.cshtml.cs / Delete.cshtml` - حذف
|
||||||
|
|
||||||
|
## روش استفاده
|
||||||
|
|
||||||
|
### 1. ثبت گزارش از موبایل
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
POST /api/bugreport/submit
|
||||||
|
|
||||||
|
{
|
||||||
|
"title": "برنامه هنگام ورود خراب میشود",
|
||||||
|
"description": "هنگام وارد کردن نام کاربری، برنامه کرش میکند",
|
||||||
|
"userEmail": "user@example.com",
|
||||||
|
"deviceModel": "Samsung Galaxy S21",
|
||||||
|
"osVersion": "Android 12",
|
||||||
|
"platform": "Android",
|
||||||
|
"manufacturer": "Samsung",
|
||||||
|
"deviceId": "device-unique-id",
|
||||||
|
"screenResolution": "1440x3200",
|
||||||
|
"memoryInMB": 8000,
|
||||||
|
"storageInMB": 256000,
|
||||||
|
"batteryLevel": 75,
|
||||||
|
"isCharging": false,
|
||||||
|
"networkType": "4G",
|
||||||
|
"appVersion": "1.0.0",
|
||||||
|
"buildNumber": "100",
|
||||||
|
"packageName": "com.example.app",
|
||||||
|
"installTime": "2024-01-01T10:00:00Z",
|
||||||
|
"lastUpdateTime": "2024-12-01T14:30:00Z",
|
||||||
|
"flavor": "production",
|
||||||
|
"type": 1, // Crash = 1
|
||||||
|
"priority": 2, // High = 2
|
||||||
|
"stackTrace": "...",
|
||||||
|
"logs": ["log1", "log2"],
|
||||||
|
"screenshots": ["base64-encoded-image-1"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. دسترسی به Admin Panel
|
||||||
|
|
||||||
|
```
|
||||||
|
https://yourdomain.com/AdminNew/BugReport
|
||||||
|
```
|
||||||
|
|
||||||
|
**صفحات موجود:**
|
||||||
|
- **Index** - لیست تمام گزارشها با فیلترها
|
||||||
|
- **Details** - نمایش جزئیات کامل شامل:
|
||||||
|
- معلومات کاربر و گزارش
|
||||||
|
- معلومات دستگاه
|
||||||
|
- معلومات برنامه
|
||||||
|
- لاگها
|
||||||
|
- تصاویر
|
||||||
|
- Stack Trace
|
||||||
|
- **Edit** - تغییر وضعیت و اولویت
|
||||||
|
- **Delete** - حذف گزارش
|
||||||
|
|
||||||
|
### 3. درخواستهای API
|
||||||
|
|
||||||
|
#### دریافت لیست
|
||||||
|
```
|
||||||
|
GET /api/bugreport/list?type=1&priority=2&status=1&searchTerm=crash&pageNumber=1&pageSize=10
|
||||||
|
```
|
||||||
|
|
||||||
|
#### دریافت جزئیات
|
||||||
|
```
|
||||||
|
GET /api/bugreport/{id}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ویرایش
|
||||||
|
```
|
||||||
|
PUT /api/bugreport/{id}
|
||||||
|
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"priority": 2,
|
||||||
|
"status": 3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### حذف
|
||||||
|
```
|
||||||
|
DELETE /api/bugreport/{id}
|
||||||
|
```
|
||||||
|
|
||||||
|
## انواع (Enums)
|
||||||
|
|
||||||
|
### BugReportType
|
||||||
|
- `1` - Crash (کرش)
|
||||||
|
- `2` - UI (مشکل رابط)
|
||||||
|
- `3` - Performance (عملکرد)
|
||||||
|
- `4` - Feature (فیچر)
|
||||||
|
- `5` - Network (شبکه)
|
||||||
|
- `6` - Camera (دوربین)
|
||||||
|
- `7` - FaceRecognition (تشخیص چهره)
|
||||||
|
- `8` - Database (دیتابیس)
|
||||||
|
- `9` - Login (ورود)
|
||||||
|
- `10` - Other (سایر)
|
||||||
|
|
||||||
|
### BugPriority
|
||||||
|
- `1` - Critical (بحرانی)
|
||||||
|
- `2` - High (بالا)
|
||||||
|
- `3` - Medium (متوسط)
|
||||||
|
- `4` - Low (پایین)
|
||||||
|
|
||||||
|
### BugReportStatus
|
||||||
|
- `1` - Open (باز)
|
||||||
|
- `2` - InProgress (در حال بررسی)
|
||||||
|
- `3` - Fixed (رفع شده)
|
||||||
|
- `4` - Closed (بسته شده)
|
||||||
|
- `5` - Reopened (مجدداً باز)
|
||||||
|
|
||||||
|
## Migration
|
||||||
|
|
||||||
|
برای اعمال تغییرات دیتابیس:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
Add-Migration AddBugReportTables
|
||||||
|
Update-Database
|
||||||
|
```
|
||||||
|
|
||||||
|
## نکات مهم
|
||||||
|
|
||||||
|
1. **تصاویر**: تصاویر به صورت Base64 encoded ذخیره میشوند
|
||||||
|
2. **لاگها**: تمام لاگها به صورت جدا ذخیره میشوند
|
||||||
|
3. **وضعیت پیشفرض**: وقتی گزارش ثبت میشود، وضعیت آن "Open" است
|
||||||
|
4. **تاریخ**: تاریخ ایجاد و بروزرسانی خودکار ثبت میشود
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- API endpoints از `authentication` محافظت میشوند
|
||||||
|
- Admin pages تنها برای کاربرانی با دسترسی AdminArea قابل دسترس هستند
|
||||||
|
- حذف و ویرایش نیاز به تأیید دارد
|
||||||
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<AssemblyName>BackgroundInstitutionContract.Task</AssemblyName>
|
||||||
|
<RootNamespace>BackgroundInstitutionContract.Task</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\0_Framework\0_Framework.csproj" />
|
||||||
|
<ProjectReference Include="..\..\AccountManagement.Configuration\AccountManagement.Configuration.csproj" />
|
||||||
|
<ProjectReference Include="..\..\PersonalContractingParty.Config\PersonalContractingParty.Config.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Query.Bootstrapper\Query.Bootstrapper.csproj" />
|
||||||
|
<ProjectReference Include="..\..\WorkFlow\Infrastructure\WorkFlow.Infrastructure.Config\WorkFlow.Infrastructure.Config.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
using _0_Framework.Application;
|
||||||
|
|
||||||
|
namespace BackgroundInstitutionContract.Task
|
||||||
|
{
|
||||||
|
public class FileUploader : IFileUploader
|
||||||
|
{
|
||||||
|
private readonly IWebHostEnvironment _webHostEnvironment;
|
||||||
|
|
||||||
|
public FileUploader(IWebHostEnvironment webHostEnvironment)
|
||||||
|
{
|
||||||
|
_webHostEnvironment = webHostEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Upload(IFormFile file, string path)
|
||||||
|
{
|
||||||
|
if (file == null) return "";
|
||||||
|
|
||||||
|
var directoryPath = $"{_webHostEnvironment.WebRootPath}\\ProductPictures\\{path}";
|
||||||
|
|
||||||
|
if (!Directory.Exists(directoryPath))
|
||||||
|
Directory.CreateDirectory(directoryPath);
|
||||||
|
|
||||||
|
var fileName = $"{DateTime.Now.ToFileName()}-{file.FileName}";
|
||||||
|
var filePath = $"{directoryPath}\\{fileName}";
|
||||||
|
var output = System.IO.File.Create(filePath);
|
||||||
|
file.CopyTo(output);
|
||||||
|
return $"{path}/{fileName}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
|
||||||
|
using _0_Framework.Application;
|
||||||
|
using Company.Domain.ContarctingPartyAgg;
|
||||||
|
using Company.Domain.InstitutionContractAgg;
|
||||||
|
using Hangfire;
|
||||||
|
|
||||||
|
namespace BackgroundInstitutionContract.Task.Jobs;
|
||||||
|
|
||||||
|
public class JobSchedulerRegistrator
|
||||||
|
{
|
||||||
|
private readonly IBackgroundJobClient _backgroundJobClient;
|
||||||
|
private readonly SmsReminder _smsReminder;
|
||||||
|
private readonly IInstitutionContractRepository _institutionContractRepository;
|
||||||
|
private static DateTime? _lastRunCreateTransaction;
|
||||||
|
private static DateTime? _lastRunSendMonthlySms;
|
||||||
|
|
||||||
|
|
||||||
|
public JobSchedulerRegistrator(SmsReminder smsReminder, IBackgroundJobClient backgroundJobClient, IInstitutionContractRepository institutionContractRepository)
|
||||||
|
{
|
||||||
|
_smsReminder = smsReminder;
|
||||||
|
_backgroundJobClient = backgroundJobClient;
|
||||||
|
_institutionContractRepository = institutionContractRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Register()
|
||||||
|
{
|
||||||
|
|
||||||
|
RecurringJob.AddOrUpdate(
|
||||||
|
"InstitutionContract.CreateFinancialTransaction",
|
||||||
|
() => CreateFinancialTransaction(),
|
||||||
|
"*/30 * * * *" // هر 30 دقیقه یکبار چک کن
|
||||||
|
);
|
||||||
|
|
||||||
|
RecurringJob.AddOrUpdate(
|
||||||
|
"InstitutionContract.SendMonthlySms",
|
||||||
|
() => SendFirstDayOfMonthSms(),
|
||||||
|
"*/20 * * * *" // هر 30 دقیقه یکبار چک کن
|
||||||
|
);
|
||||||
|
|
||||||
|
RecurringJob.AddOrUpdate(
|
||||||
|
"InstitutionContract.SendReminderSms",
|
||||||
|
() => SendReminderSms(),
|
||||||
|
"*/1 * * * *" // هر 1 دقیقه یکبار چک کن
|
||||||
|
);
|
||||||
|
RecurringJob.AddOrUpdate(
|
||||||
|
"InstitutionContract.SendBlockSms",
|
||||||
|
() => SendBlockSms(),
|
||||||
|
"*/1 * * * *" // هر 1 دقیقه یکبار چک کن
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ایجاد سند بدهی ماهیانه برای قراداد مالی
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[DisableConcurrentExecution(timeoutInSeconds: 1200)]
|
||||||
|
public async System.Threading.Tasks.Task CreateFinancialTransaction()
|
||||||
|
{
|
||||||
|
var now =DateTime.Now;
|
||||||
|
var endOfMonth = now.ToFarsi().FindeEndOfMonth();
|
||||||
|
var endOfMonthGr = endOfMonth.ToGeorgianDateTime();
|
||||||
|
|
||||||
|
if (now.Date == endOfMonthGr.Date && now.Hour >= 2 && now.Hour < 4 &&
|
||||||
|
now.Date != _lastRunCreateTransaction?.Date)
|
||||||
|
{
|
||||||
|
|
||||||
|
var month = endOfMonth.Substring(5, 2);
|
||||||
|
var year = endOfMonth.Substring(0, 4);
|
||||||
|
var monthName = month.ToFarsiMonthByNumber();
|
||||||
|
var description = $"{monthName} {year}";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var endnew = ($"{endOfMonth.Substring(0, 8)}01").FindeEndOfMonth();
|
||||||
|
|
||||||
|
var endNewGr = endnew.ToGeorgianDateTime();
|
||||||
|
var endNewFa = endNewGr.ToFarsi();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _institutionContractRepository.CreateTransactionForInstitutionContracts(endNewGr, endNewFa, description);
|
||||||
|
_lastRunCreateTransaction = now;
|
||||||
|
Console.WriteLine("CreateTransAction executed");
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
//_smsService.Alarm("09114221321", "خطا-ایجاد سند مالی");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ارسال پیامک صورت حساب ماهانه
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[DisableConcurrentExecution(timeoutInSeconds: 600)]
|
||||||
|
public async System.Threading.Tasks.Task SendFirstDayOfMonthSms()
|
||||||
|
{
|
||||||
|
//var now = new DateTime(2025,11,21, 10,30,0);
|
||||||
|
var now = DateTime.Now;
|
||||||
|
var endOfMonth = now.ToFarsi().FindeEndOfMonth();
|
||||||
|
var endOfMonthGr = endOfMonth.ToGeorgianDateTime();
|
||||||
|
|
||||||
|
if (now.Date == endOfMonthGr.Date && now.Hour >= 10 && now.Hour < 11 &&
|
||||||
|
now.Date != _lastRunSendMonthlySms?.Date)
|
||||||
|
{
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _institutionContractRepository.SendMonthlySms(now);
|
||||||
|
_lastRunSendMonthlySms = now;
|
||||||
|
Console.WriteLine("Send Monthly sms executed");
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
//_smsService.Alarm("09114221321", "خطا-ایجاد سند مالی");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ارسال پیامک یاد آور بدهی
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[DisableConcurrentExecution(timeoutInSeconds: 1200)]
|
||||||
|
public async System.Threading.Tasks.Task SendReminderSms()
|
||||||
|
{
|
||||||
|
await _institutionContractRepository.SendReminderSmsForBackgroundTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ارسال پیامک مسدودی
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[DisableConcurrentExecution(timeoutInSeconds: 100)]
|
||||||
|
public async System.Threading.Tasks.Task SendBlockSms()
|
||||||
|
{
|
||||||
|
await _institutionContractRepository.SendBlockSmsForBackgroundTask();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
using _0_Framework.Application.Sms;
|
||||||
|
using AccountManagement.Application.Contracts.Account;
|
||||||
|
using AccountMangement.Infrastructure.EFCore;
|
||||||
|
using Company.Domain.SmsResultAgg;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SmsResult = Company.Domain.SmsResultAgg.SmsResult;
|
||||||
|
|
||||||
|
namespace BackgroundInstitutionContract.Task.Jobs;
|
||||||
|
public class SmsReminder
|
||||||
|
{
|
||||||
|
private readonly AccountContext _accountContext;
|
||||||
|
private readonly ISmsService _smsService;
|
||||||
|
private readonly ISmsResultRepository _smsResultRepository;
|
||||||
|
|
||||||
|
public SmsReminder(ISmsService smsService, AccountContext accountContext, ISmsResultRepository smsResultRepository)
|
||||||
|
{
|
||||||
|
_smsService = smsService;
|
||||||
|
_accountContext = accountContext;
|
||||||
|
_smsResultRepository = smsResultRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
//var accounts = _accountContext.Accounts.Where(x => x.PositionId > 0 && x.IsActiveString == "true").Select(x => new AccountViewModel() { Id = x.id, Mobile = x.Mobile, Fullname = x.Fullname }).ToList();
|
||||||
|
//Thread.Sleep(300);
|
||||||
|
//var accounts = new List<AccountViewModel>() { new AccountViewModel() { Mobile = "09114221321", Id = 2 } };
|
||||||
|
var accounts= _accountContext.Accounts.Where(x => x.Username.ToLower()=="mahan").Select(x => new AccountViewModel() { Id = x.id, Mobile = x.Mobile, Fullname = x.Fullname }).ToList();
|
||||||
|
var smsVM = accounts.Select(x => new AccountSmsTaskViewModel()
|
||||||
|
{
|
||||||
|
Mobile = x.Mobile,
|
||||||
|
AccountId = x.Id,
|
||||||
|
FullName = x.Fullname,
|
||||||
|
TaskCount = GetLateTasksCount(x.Id)
|
||||||
|
}).Where(x => x.TaskCount > 0 && !string.IsNullOrEmpty(x.Mobile) && x.Mobile.Length == 11).ToList();
|
||||||
|
Thread.Sleep(300);
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var viewmodel in smsVM)
|
||||||
|
{
|
||||||
|
var smsResult = _smsService.TaskReminderSms(viewmodel.Mobile, $"{viewmodel.TaskCount}");
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
var createSmsResult = new SmsResult(smsResult.MessageId, smsResult.Message, "یادآور وظایف",
|
||||||
|
viewmodel.FullName, viewmodel.Mobile, viewmodel.AccountId, viewmodel.AccountId);
|
||||||
|
_smsResultRepository.Create(createSmsResult);
|
||||||
|
_smsResultRepository.SaveChanges();
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private int GetLateTasksCount(long accountId)
|
||||||
|
{
|
||||||
|
var positionValue = _accountContext.Accounts
|
||||||
|
.Where(x => x.id == accountId)
|
||||||
|
.Include(p => p.Position)
|
||||||
|
.Select(x => x.Position.PositionValue)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (positionValue == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
DateTime now = DateTime.Now;
|
||||||
|
int overdueTasksCount;
|
||||||
|
|
||||||
|
if (positionValue == 1)
|
||||||
|
{
|
||||||
|
overdueTasksCount = _accountContext.Assigns.Include(x => x.Task).Where(x => x.AssignedId == accountId &&
|
||||||
|
x.AssignerId == accountId && x.Task.Assigns.Count == 1 &&
|
||||||
|
!x.IsCancel && !x.IsCanceledRequest &&
|
||||||
|
!x.IsDone && !x.TimeRequest && !x.IsDoneRequest && x.EndTaskDate.Date <= DateTime.Now.Date && x.Task.IsActiveString == "true")
|
||||||
|
.GroupBy(x => x.TaskId).Select(x => x.First()).Count();
|
||||||
|
|
||||||
|
//overdueTasksCount = _accountContext.Tasks.Include(x =>
|
||||||
|
// x.Assigns).Count(x => !x.Assigns.Any(a => a.IsCancel) && !x.Assigns.Any(a => a.IsCanceledRequest) &&
|
||||||
|
// !x.Assigns.Any(a => a.IsDone) && !x.Assigns.Any(a => a.IsDoneRequest) &&
|
||||||
|
// !x.Assigns.Any(a => a.TimeRequest)
|
||||||
|
// && x.Assigns.Any(a => a.AssignedId == accountId && a.AssignerId == accountId) &&
|
||||||
|
// (x.Assigns.First(a => a.AssignedId == accountId && a.AssignerId == accountId)
|
||||||
|
// .EndTaskDate.Date <= DateTime.Now.Date) && x.Assigns.Count == 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
overdueTasksCount = _accountContext.Assigns
|
||||||
|
.Include(x => x.Task)
|
||||||
|
.Where(x => x.AssignedId == accountId &&
|
||||||
|
!x.IsCancel && !x.IsCanceledRequest &&
|
||||||
|
!x.IsDone && !x.TimeRequest && !x.IsDoneRequest && x.EndTaskDate.Date <= DateTime.Now.Date && x.Task.IsActiveString == "true")
|
||||||
|
.GroupBy(x => x.TaskId).Select(x => x.First()).Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//overdueTasksCount = _accountContext.Tasks.Include(x =>
|
||||||
|
// x.Assigns).Count(x => !x.Assigns.Any(a => a.IsCancel) && !x.Assigns.Any(a => a.IsCanceledRequest) &&
|
||||||
|
// !x.Assigns.Any(a => a.IsDone) && !x.Assigns.Any(a => a.IsDoneRequest) &&
|
||||||
|
// !x.Assigns.Any(a => a.TimeRequest)
|
||||||
|
// && x.Assigns.Any(a => a.AssignedId == accountId) &&
|
||||||
|
// (x.Assigns.First(a => a.AssignedId == accountId).EndTaskDate.Date <= DateTime.Now.Date));
|
||||||
|
|
||||||
|
|
||||||
|
var overdueRequestsCount = _accountContext.Assigns.Include(x => x.Task)
|
||||||
|
.Where(x => (x.IsCanceledRequest
|
||||||
|
|| x.IsDoneRequest || x.TimeRequest) && !x.IsCancel && !x.IsDone &&
|
||||||
|
x.Task.IsActiveString == "true" &&
|
||||||
|
x.Task.SenderId == accountId).GroupBy(x => x.TaskId).Select(x => x.First()).Count();
|
||||||
|
|
||||||
|
return overdueTasksCount + overdueRequestsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public class AccountSmsTaskViewModel
|
||||||
|
{
|
||||||
|
public int TaskCount { get; set; }
|
||||||
|
public long AccountId { get; set; }
|
||||||
|
public string Mobile { get; set; }
|
||||||
|
public string FullName { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using BackgroundInstitutionContract.Task.Jobs;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BackgroundInstitutionContract.Task;
|
||||||
|
|
||||||
|
public class JobsBootstrapper
|
||||||
|
{
|
||||||
|
public static void Configure(IServiceCollection services)
|
||||||
|
{
|
||||||
|
var currentNamespace = typeof(JobSchedulerRegistrator).Namespace; // همون namespace کلاس
|
||||||
|
|
||||||
|
var assembly = typeof(JobSchedulerRegistrator).Assembly;
|
||||||
|
|
||||||
|
var jobTypes = assembly.GetTypes()
|
||||||
|
.Where(t =>
|
||||||
|
t is { IsClass: true, IsAbstract: false, Namespace: not null } &&
|
||||||
|
t.Namespace.StartsWith(currentNamespace, StringComparison.Ordinal))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var jobType in jobTypes)
|
||||||
|
{
|
||||||
|
services.AddTransient(jobType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
using _0_Framework.Application;
|
||||||
|
using _0_Framework.Application.Sms;
|
||||||
|
using _0_Framework.Application.UID;
|
||||||
|
using _0_Framework.InfraStructure.Mongo;
|
||||||
|
using AccountManagement.Configuration;
|
||||||
|
using BackgroundInstitutionContract.Task;
|
||||||
|
using BackgroundInstitutionContract.Task.Jobs;
|
||||||
|
using CompanyManagment.App.Contracts.Hubs;
|
||||||
|
using CompanyManagment.EFCore.Services;
|
||||||
|
using Hangfire;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using PersonalContractingParty.Config;
|
||||||
|
using Query.Bootstrapper;
|
||||||
|
using WorkFlow.Infrastructure.Config;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
var hangfireConnectionString = builder.Configuration.GetConnectionString("HangfireDb");
|
||||||
|
builder.Services.AddHangfire(x => x.UseSqlServerStorage(hangfireConnectionString));
|
||||||
|
builder.Services.AddHangfireServer();
|
||||||
|
var connectionString = builder.Configuration.GetConnectionString("MesbahDb");
|
||||||
|
var connectionStringTestDb = builder.Configuration.GetConnectionString("TestDb");
|
||||||
|
builder.Services.AddSingleton<IPasswordHasher, PasswordHasher>();
|
||||||
|
builder.Services.AddTransient<IAuthHelper, AuthHelper>();
|
||||||
|
builder.Services.AddTransient<ISmsService, SmsService>();
|
||||||
|
builder.Services.AddTransient<IUidService, UidService>();
|
||||||
|
builder.Services.AddTransient<IFileUploader, FileUploader>();
|
||||||
|
builder.Services.Configure<AppSettingConfiguration>(builder.Configuration);
|
||||||
|
|
||||||
|
#region MongoDb
|
||||||
|
|
||||||
|
var mongoConnectionSection = builder.Configuration.GetSection("MongoDb");
|
||||||
|
var mongoDbSettings = mongoConnectionSection.Get<MongoDbConfig>();
|
||||||
|
var mongoClient = new MongoClient(mongoDbSettings.ConnectionString);
|
||||||
|
var mongoDatabase = mongoClient.GetDatabase(mongoDbSettings.DatabaseName);
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<IMongoDatabase>(mongoDatabase);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
PersonalBootstrapper.Configure(builder.Services, connectionString);
|
||||||
|
TestDbBootStrapper.Configure(builder.Services, connectionStringTestDb);
|
||||||
|
AccountManagementBootstrapper.Configure(builder.Services, connectionString);
|
||||||
|
WorkFlowBootstrapper.Configure(builder.Services, connectionString);
|
||||||
|
QueryBootstrapper.Configure(builder.Services);
|
||||||
|
JobsBootstrapper.Configure(builder.Services);
|
||||||
|
builder.Services.AddHttpClient();
|
||||||
|
builder.Services.AddHttpContextAccessor();
|
||||||
|
builder.Services.AddSignalR();
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
app.MapHub<SendSmsHub>("/sendSmsHub");
|
||||||
|
|
||||||
|
app.MapHangfireDashboard();
|
||||||
|
app.MapGet("/", () => "Hello World!");
|
||||||
|
|
||||||
|
using (var scope = app.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var jobScheduler = scope.ServiceProvider.GetRequiredService<JobSchedulerRegistrator>();
|
||||||
|
jobScheduler.Register();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Run();
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:56492",
|
||||||
|
"sslPort": 44378
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"applicationUrl": "http://localhost:5216",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"https": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"applicationUrl": "https://localhost:7223;http://localhost:5217",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
{
|
||||||
|
"DetailedErrors": true,
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
//تست
|
||||||
|
//"MesbahDb": "Data Source=DESKTOP-NUE119G\\MSNEW;Initial Catalog=Mesbah_db;Integrated Security=True"
|
||||||
|
|
||||||
|
//server
|
||||||
|
//"MesbahDb": "Data Source=171.22.24.15;Initial Catalog=mesbah_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]18[3019]#@ATt;TrustServerCertificate=true;",
|
||||||
|
|
||||||
|
|
||||||
|
//local
|
||||||
|
"MesbahDb": "Data Source=.;Initial Catalog=mesbah_db;Integrated Security=True;TrustServerCertificate=true;",
|
||||||
|
|
||||||
|
//dad-mehr
|
||||||
|
//"MesbahDb": "Data Source=.;Initial Catalog=teamWork;Integrated Security=True;TrustServerCertificate=true;",
|
||||||
|
|
||||||
|
"TestDb": "Data Source=.;Initial Catalog=TestDb;Integrated Security=True;TrustServerCertificate=true;",
|
||||||
|
|
||||||
|
//mahan Docker
|
||||||
|
//"MesbahDb": "Data Source=localhost,5069;Initial Catalog=mesbah_db;User ID=sa;Password=YourPassword123;TrustServerCertificate=True;",
|
||||||
|
//"HangfireDb": "Data Source=.;Initial Catalog=hangfire_db;Integrated Security=True;TrustServerCertificate=true;",
|
||||||
|
"HangfireDb": "Data Source=185.208.175.186;Initial Catalog=hangfire_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]18[3019]#@ATt;TrustServerCertificate=true;"
|
||||||
|
},
|
||||||
|
|
||||||
|
"GoogleRecaptchaV3": {
|
||||||
|
"SiteKey": "6Lfhp_AnAAAAAB79WkrMoHd1k8ir4m8VvfjE7FTH",
|
||||||
|
"SecretKey": "6Lfhp_AnAAAAANjDDY6DPrbbUQS7k6ZCRmrVP5Lb"
|
||||||
|
},
|
||||||
|
"SmsSecrets": {
|
||||||
|
"ApiKey": "Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa",
|
||||||
|
"SecretKey": "dadmehr"
|
||||||
|
},
|
||||||
|
"Domain": ".gozareshgir.ir",
|
||||||
|
"MongoDb": {
|
||||||
|
"ConnectionString": "mongodb://localhost:27017",
|
||||||
|
"DatabaseName": "Gozareshgir"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
|
||||||
|
//local
|
||||||
|
//"MesbahDb": "Data Source=.;Initial Catalog=mesbah_db;Integrated Security=True;TrustServerCertificate=true;",
|
||||||
|
"MesbahDb": "Data Source=185.208.175.186;Initial Catalog=mesbah_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]18[3019]#@ATt;TrustServerCertificate=true;",
|
||||||
|
//dad-mehr
|
||||||
|
//"MesbahDb": "Data Source=.;Initial Catalog=teamWork;Integrated Security=True;TrustServerCertificate=true;",
|
||||||
|
|
||||||
|
//"TestDb": "Data Source=.;Initial Catalog=TestDb;Integrated Security=True;TrustServerCertificate=true;",
|
||||||
|
"TestDb": "Data Source=185.208.175.186;Initial Catalog=TestDb;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]18[3019]#@ATt;TrustServerCertificate=true;",
|
||||||
|
//"MesbahDb": "Data Source=.\\MSSQLSERVER2019;Initial Catalog=mesbah_db;Persist Security Info=False;User ID=mesbah_db;Password=sa142857$@;"
|
||||||
|
//"HangfireDb": "Data Source=.;Initial Catalog=hangfire_db;Integrated Security=True;TrustServerCertificate=true;",
|
||||||
|
"HangfireDb": "Data Source=185.208.175.186;Initial Catalog=hangfire_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]18[3019]#@ATt;TrustServerCertificate=true;"
|
||||||
|
},
|
||||||
|
"MongoDb": {
|
||||||
|
"ConnectionString": "mongodb://localhost:27017",
|
||||||
|
"DatabaseName": "Gozareshgir"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\0_Framework\0_Framework.csproj" />
|
||||||
|
<ProjectReference Include="..\..\AccountManagement.Configuration\AccountManagement.Configuration.csproj" />
|
||||||
|
<ProjectReference Include="..\..\PersonalContractingParty.Config\PersonalContractingParty.Config.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Query.Bootstrapper\Query.Bootstrapper.csproj" />
|
||||||
|
<ProjectReference Include="..\..\WorkFlow\Infrastructure\WorkFlow.Infrastructure.Config\WorkFlow.Infrastructure.Config.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
32
BackgroundJobs/BackgroundJobs.Task/FileUploader.cs
Normal file
32
BackgroundJobs/BackgroundJobs.Task/FileUploader.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using _0_Framework.Application;
|
||||||
|
|
||||||
|
namespace BackgroundJobs.Task
|
||||||
|
{
|
||||||
|
public class FileUploader : IFileUploader
|
||||||
|
{
|
||||||
|
private readonly IWebHostEnvironment _webHostEnvironment;
|
||||||
|
|
||||||
|
public FileUploader(IWebHostEnvironment webHostEnvironment)
|
||||||
|
{
|
||||||
|
_webHostEnvironment = webHostEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Upload(IFormFile file, string path)
|
||||||
|
{
|
||||||
|
if (file == null) return "";
|
||||||
|
|
||||||
|
var directoryPath = $"{_webHostEnvironment.WebRootPath}\\ProductPictures\\{path}";
|
||||||
|
|
||||||
|
if (!Directory.Exists(directoryPath))
|
||||||
|
Directory.CreateDirectory(directoryPath);
|
||||||
|
|
||||||
|
var fileName = $"{DateTime.Now.ToFileName()}-{file.FileName}";
|
||||||
|
var filePath = $"{directoryPath}\\{fileName}";
|
||||||
|
var output = System.IO.File.Create(filePath);
|
||||||
|
file.CopyTo(output);
|
||||||
|
return $"{path}/{fileName}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using Hangfire;
|
||||||
|
|
||||||
|
namespace BackgroundJobs.Task.Jobs;
|
||||||
|
|
||||||
|
public class JobSchedulerRegistrator
|
||||||
|
{
|
||||||
|
private readonly IBackgroundJobClient _backgroundJobClient;
|
||||||
|
private readonly SmsReminder _smsReminder;
|
||||||
|
private static DateTime? _lastRunDateMorning;
|
||||||
|
private static DateTime? _lastRunDateEvening;
|
||||||
|
|
||||||
|
public JobSchedulerRegistrator(SmsReminder smsReminder, IBackgroundJobClient backgroundJobClient)
|
||||||
|
{
|
||||||
|
_smsReminder = smsReminder;
|
||||||
|
_backgroundJobClient = backgroundJobClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Register()
|
||||||
|
{
|
||||||
|
RecurringJob.AddOrUpdate(
|
||||||
|
"Task.SmsReminderChecker",
|
||||||
|
() => SmsReminderCheckAndSchedule(),
|
||||||
|
"*/5 * * * *" // هر 5 دقیقه یکبار چک کن
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SmsReminderCheckAndSchedule()
|
||||||
|
{
|
||||||
|
var now = DateTime.Now;
|
||||||
|
|
||||||
|
var startMorning = new TimeSpan(9, 0, 0);
|
||||||
|
var endMorning = new TimeSpan(9, 40, 0);
|
||||||
|
|
||||||
|
var startEvening = new TimeSpan(15, 30, 0);
|
||||||
|
var endEvening = new TimeSpan(15, 40, 0);
|
||||||
|
|
||||||
|
// صبح
|
||||||
|
if (now.DayOfWeek != DayOfWeek.Friday &&
|
||||||
|
now.TimeOfDay >= startMorning &&
|
||||||
|
now.TimeOfDay < endMorning)
|
||||||
|
{
|
||||||
|
if (_lastRunDateMorning?.Date != now.Date)
|
||||||
|
{
|
||||||
|
_backgroundJobClient.Enqueue(() => _smsReminder.Execute());
|
||||||
|
_lastRunDateMorning = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// عصر - پنجشنبه و جمعه تعطیل است
|
||||||
|
if (now.DayOfWeek != DayOfWeek.Friday &&
|
||||||
|
now.DayOfWeek != DayOfWeek.Thursday &&
|
||||||
|
now.TimeOfDay >= startEvening &&
|
||||||
|
now.TimeOfDay < endEvening)
|
||||||
|
{
|
||||||
|
if (_lastRunDateEvening?.Date != now.Date)
|
||||||
|
{
|
||||||
|
_backgroundJobClient.Enqueue(() => _smsReminder.Execute());
|
||||||
|
_lastRunDateEvening = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
116
BackgroundJobs/BackgroundJobs.Task/Jobs/SmsReminder.cs
Normal file
116
BackgroundJobs/BackgroundJobs.Task/Jobs/SmsReminder.cs
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
using _0_Framework.Application.Sms;
|
||||||
|
using AccountManagement.Application.Contracts.Account;
|
||||||
|
using AccountMangement.Infrastructure.EFCore;
|
||||||
|
using Company.Domain.SmsResultAgg;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using SmsResult = Company.Domain.SmsResultAgg.SmsResult;
|
||||||
|
|
||||||
|
namespace BackgroundJobs.Task.Jobs;
|
||||||
|
public class SmsReminder
|
||||||
|
{
|
||||||
|
private readonly AccountContext _accountContext;
|
||||||
|
private readonly ISmsService _smsService;
|
||||||
|
private readonly ISmsResultRepository _smsResultRepository;
|
||||||
|
|
||||||
|
public SmsReminder(ISmsService smsService, AccountContext accountContext, ISmsResultRepository smsResultRepository)
|
||||||
|
{
|
||||||
|
_smsService = smsService;
|
||||||
|
_accountContext = accountContext;
|
||||||
|
_smsResultRepository = smsResultRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
//var accounts = _accountContext.Accounts.Where(x => x.PositionId > 0 && x.IsActiveString == "true").Select(x => new AccountViewModel() { Id = x.id, Mobile = x.Mobile, Fullname = x.Fullname }).ToList();
|
||||||
|
//Thread.Sleep(300);
|
||||||
|
//var accounts = new List<AccountViewModel>() { new AccountViewModel() { Mobile = "09114221321", Id = 2 } };
|
||||||
|
var accounts= _accountContext.Accounts.Where(x => x.Username.ToLower()=="mahan").Select(x => new AccountViewModel() { Id = x.id, Mobile = x.Mobile, Fullname = x.Fullname }).ToList();
|
||||||
|
var smsVM = accounts.Select(x => new AccountSmsTaskViewModel()
|
||||||
|
{
|
||||||
|
Mobile = x.Mobile,
|
||||||
|
AccountId = x.Id,
|
||||||
|
FullName = x.Fullname,
|
||||||
|
TaskCount = GetLateTasksCount(x.Id)
|
||||||
|
}).Where(x => x.TaskCount > 0 && !string.IsNullOrEmpty(x.Mobile) && x.Mobile.Length == 11).ToList();
|
||||||
|
Thread.Sleep(300);
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var viewmodel in smsVM)
|
||||||
|
{
|
||||||
|
var smsResult = _smsService.TaskReminderSms(viewmodel.Mobile, $"{viewmodel.TaskCount}");
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
var createSmsResult = new SmsResult(smsResult.MessageId, smsResult.Message, "یادآور وظایف",
|
||||||
|
viewmodel.FullName, viewmodel.Mobile, viewmodel.AccountId, viewmodel.AccountId);
|
||||||
|
_smsResultRepository.Create(createSmsResult);
|
||||||
|
_smsResultRepository.SaveChanges();
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private int GetLateTasksCount(long accountId)
|
||||||
|
{
|
||||||
|
var positionValue = _accountContext.Accounts
|
||||||
|
.Where(x => x.id == accountId)
|
||||||
|
.Include(p => p.Position)
|
||||||
|
.Select(x => x.Position.PositionValue)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (positionValue == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
DateTime now = DateTime.Now;
|
||||||
|
int overdueTasksCount;
|
||||||
|
|
||||||
|
if (positionValue == 1)
|
||||||
|
{
|
||||||
|
overdueTasksCount = _accountContext.Assigns.Include(x => x.Task).Where(x => x.AssignedId == accountId &&
|
||||||
|
x.AssignerId == accountId && x.Task.Assigns.Count == 1 &&
|
||||||
|
!x.IsCancel && !x.IsCanceledRequest &&
|
||||||
|
!x.IsDone && !x.TimeRequest && !x.IsDoneRequest && x.EndTaskDate.Date <= DateTime.Now.Date && x.Task.IsActiveString == "true")
|
||||||
|
.GroupBy(x => x.TaskId).Select(x => x.First()).Count();
|
||||||
|
|
||||||
|
//overdueTasksCount = _accountContext.Tasks.Include(x =>
|
||||||
|
// x.Assigns).Count(x => !x.Assigns.Any(a => a.IsCancel) && !x.Assigns.Any(a => a.IsCanceledRequest) &&
|
||||||
|
// !x.Assigns.Any(a => a.IsDone) && !x.Assigns.Any(a => a.IsDoneRequest) &&
|
||||||
|
// !x.Assigns.Any(a => a.TimeRequest)
|
||||||
|
// && x.Assigns.Any(a => a.AssignedId == accountId && a.AssignerId == accountId) &&
|
||||||
|
// (x.Assigns.First(a => a.AssignedId == accountId && a.AssignerId == accountId)
|
||||||
|
// .EndTaskDate.Date <= DateTime.Now.Date) && x.Assigns.Count == 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
overdueTasksCount = _accountContext.Assigns
|
||||||
|
.Include(x => x.Task)
|
||||||
|
.Where(x => x.AssignedId == accountId &&
|
||||||
|
!x.IsCancel && !x.IsCanceledRequest &&
|
||||||
|
!x.IsDone && !x.TimeRequest && !x.IsDoneRequest && x.EndTaskDate.Date <= DateTime.Now.Date && x.Task.IsActiveString == "true")
|
||||||
|
.GroupBy(x => x.TaskId).Select(x => x.First()).Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//overdueTasksCount = _accountContext.Tasks.Include(x =>
|
||||||
|
// x.Assigns).Count(x => !x.Assigns.Any(a => a.IsCancel) && !x.Assigns.Any(a => a.IsCanceledRequest) &&
|
||||||
|
// !x.Assigns.Any(a => a.IsDone) && !x.Assigns.Any(a => a.IsDoneRequest) &&
|
||||||
|
// !x.Assigns.Any(a => a.TimeRequest)
|
||||||
|
// && x.Assigns.Any(a => a.AssignedId == accountId) &&
|
||||||
|
// (x.Assigns.First(a => a.AssignedId == accountId).EndTaskDate.Date <= DateTime.Now.Date));
|
||||||
|
|
||||||
|
|
||||||
|
var overdueRequestsCount = _accountContext.Assigns.Include(x => x.Task)
|
||||||
|
.Where(x => (x.IsCanceledRequest
|
||||||
|
|| x.IsDoneRequest || x.TimeRequest) && !x.IsCancel && !x.IsDone &&
|
||||||
|
x.Task.IsActiveString == "true" &&
|
||||||
|
x.Task.SenderId == accountId).GroupBy(x => x.TaskId).Select(x => x.First()).Count();
|
||||||
|
|
||||||
|
return overdueTasksCount + overdueRequestsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public class AccountSmsTaskViewModel
|
||||||
|
{
|
||||||
|
public int TaskCount { get; set; }
|
||||||
|
public long AccountId { get; set; }
|
||||||
|
public string Mobile { get; set; }
|
||||||
|
public string FullName { get; set; }
|
||||||
|
}
|
||||||
24
BackgroundJobs/BackgroundJobs.Task/JobsBootstrapper.cs
Normal file
24
BackgroundJobs/BackgroundJobs.Task/JobsBootstrapper.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using BackgroundJobs.Task.Jobs;
|
||||||
|
|
||||||
|
namespace BackgroundJobs.Task;
|
||||||
|
|
||||||
|
public class JobsBootstrapper
|
||||||
|
{
|
||||||
|
public static void Configure(IServiceCollection services)
|
||||||
|
{
|
||||||
|
var currentNamespace = typeof(JobSchedulerRegistrator).Namespace; // همون namespace کلاس
|
||||||
|
|
||||||
|
var assembly = typeof(JobSchedulerRegistrator).Assembly;
|
||||||
|
|
||||||
|
var jobTypes = assembly.GetTypes()
|
||||||
|
.Where(t =>
|
||||||
|
t is { IsClass: true, IsAbstract: false, Namespace: not null } &&
|
||||||
|
t.Namespace.StartsWith(currentNamespace, StringComparison.Ordinal))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var jobType in jobTypes)
|
||||||
|
{
|
||||||
|
services.AddTransient(jobType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
59
BackgroundJobs/BackgroundJobs.Task/Program.cs
Normal file
59
BackgroundJobs/BackgroundJobs.Task/Program.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
using _0_Framework.Application;
|
||||||
|
using _0_Framework.Application.Sms;
|
||||||
|
using _0_Framework.Application.UID;
|
||||||
|
using _0_Framework.InfraStructure.Mongo;
|
||||||
|
using AccountManagement.Configuration;
|
||||||
|
using BackgroundJobs.Task;
|
||||||
|
using BackgroundJobs.Task.Jobs;
|
||||||
|
using CompanyManagment.EFCore.Services;
|
||||||
|
using Hangfire;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
using PersonalContractingParty.Config;
|
||||||
|
using Query.Bootstrapper;
|
||||||
|
using WorkFlow.Infrastructure.Config;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
var hangfireConnectionString = builder.Configuration.GetConnectionString("HangfireDb");
|
||||||
|
builder.Services.AddHangfire(x => x.UseSqlServerStorage(hangfireConnectionString));
|
||||||
|
builder.Services.AddHangfireServer();
|
||||||
|
var connectionString = builder.Configuration.GetConnectionString("MesbahDb");
|
||||||
|
var connectionStringTestDb = builder.Configuration.GetConnectionString("TestDb");
|
||||||
|
builder.Services.AddSingleton<IPasswordHasher, PasswordHasher>();
|
||||||
|
builder.Services.AddTransient<IAuthHelper, AuthHelper>();
|
||||||
|
builder.Services.AddTransient<ISmsService, SmsService>();
|
||||||
|
builder.Services.AddTransient<IUidService, UidService>();
|
||||||
|
builder.Services.AddTransient<IFileUploader, FileUploader>();
|
||||||
|
builder.Services.Configure<AppSettingConfiguration>(builder.Configuration);
|
||||||
|
|
||||||
|
#region MongoDb
|
||||||
|
|
||||||
|
var mongoConnectionSection = builder.Configuration.GetSection("MongoDb");
|
||||||
|
var mongoDbSettings = mongoConnectionSection.Get<MongoDbConfig>();
|
||||||
|
var mongoClient = new MongoClient(mongoDbSettings.ConnectionString);
|
||||||
|
var mongoDatabase = mongoClient.GetDatabase(mongoDbSettings.DatabaseName);
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<IMongoDatabase>(mongoDatabase);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
PersonalBootstrapper.Configure(builder.Services, connectionString);
|
||||||
|
TestDbBootStrapper.Configure(builder.Services, connectionStringTestDb);
|
||||||
|
AccountManagementBootstrapper.Configure(builder.Services, connectionString);
|
||||||
|
WorkFlowBootstrapper.Configure(builder.Services, connectionString);
|
||||||
|
QueryBootstrapper.Configure(builder.Services);
|
||||||
|
JobsBootstrapper.Configure(builder.Services);
|
||||||
|
builder.Services.AddHttpClient();
|
||||||
|
builder.Services.AddHttpContextAccessor();
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
app.MapHangfireDashboard();
|
||||||
|
app.MapGet("/", () => "Hello World!");
|
||||||
|
|
||||||
|
using (var scope = app.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var jobScheduler = scope.ServiceProvider.GetRequiredService<JobSchedulerRegistrator>();
|
||||||
|
jobScheduler.Register();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.Run();
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:56492",
|
||||||
|
"sslPort": 44378
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"applicationUrl": "http://localhost:5216",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"https": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"applicationUrl": "https://localhost:7222;http://localhost:5216",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"DetailedErrors": true,
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
//تست
|
||||||
|
//"MesbahDb": "Data Source=DESKTOP-NUE119G\\MSNEW;Initial Catalog=Mesbah_db;Integrated Security=True"
|
||||||
|
|
||||||
|
//server
|
||||||
|
//"MesbahDb": "Data Source=171.22.24.15;Initial Catalog=mesbah_db;Persist Security Info=False;User ID=ir_db;Password=R2rNp[170]18[3019]#@ATt;TrustServerCertificate=true;",
|
||||||
|
|
||||||
|
|
||||||
|
//local
|
||||||
|
"MesbahDb": "Data Source=.;Initial Catalog=mesbah_db;Integrated Security=True;TrustServerCertificate=true;",
|
||||||
|
|
||||||
|
//dad-mehr
|
||||||
|
//"MesbahDb": "Data Source=.;Initial Catalog=teamWork;Integrated Security=True;TrustServerCertificate=true;",
|
||||||
|
|
||||||
|
"TestDb": "Data Source=.;Initial Catalog=TestDb;Integrated Security=True;TrustServerCertificate=true;",
|
||||||
|
|
||||||
|
//mahan Docker
|
||||||
|
//"MesbahDb": "Data Source=localhost,5069;Initial Catalog=mesbah_db;User ID=sa;Password=YourPassword123;TrustServerCertificate=True;",
|
||||||
|
"HangfireDb": "Data Source=.;Initial Catalog=hangfire_db;Integrated Security=True;TrustServerCertificate=true;"
|
||||||
|
},
|
||||||
|
|
||||||
|
"GoogleRecaptchaV3": {
|
||||||
|
"SiteKey": "6Lfhp_AnAAAAAB79WkrMoHd1k8ir4m8VvfjE7FTH",
|
||||||
|
"SecretKey": "6Lfhp_AnAAAAANjDDY6DPrbbUQS7k6ZCRmrVP5Lb"
|
||||||
|
},
|
||||||
|
"SmsSecrets": {
|
||||||
|
"ApiKey": "Og5M562igmzJRhQPnq0GdtieYdLgtfikjzxOmeQBPxJjZtyge5Klc046Lfw1mxSa",
|
||||||
|
"SecretKey": "dadmehr"
|
||||||
|
},
|
||||||
|
"Domain": ".gozareshgir.ir",
|
||||||
|
"MongoDb": {
|
||||||
|
"ConnectionString": "mongodb://localhost:27017",
|
||||||
|
"DatabaseName": "Gozareshgir"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
9
BackgroundJobs/BackgroundJobs.Task/appsettings.json
Normal file
9
BackgroundJobs/BackgroundJobs.Task/appsettings.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
||||||
314
CHANGELOG.md
Normal file
314
CHANGELOG.md
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
# خلاصه تغییرات سیستم گزارش خرابی
|
||||||
|
|
||||||
|
## 📝 فایلهای اضافه شده (23 فایل)
|
||||||
|
|
||||||
|
### 1️⃣ Domain Layer (3 فایل)
|
||||||
|
```
|
||||||
|
✓ AccountManagement.Domain/BugReportAgg/
|
||||||
|
├── BugReport.cs
|
||||||
|
├── BugReportLog.cs
|
||||||
|
└── BugReportScreenshot.cs
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2️⃣ Application Contracts (6 فایل)
|
||||||
|
```
|
||||||
|
✓ AccountManagement.Application.Contracts/BugReport/
|
||||||
|
├── IBugReportRepository.cs
|
||||||
|
├── IBugReportApplication.cs
|
||||||
|
├── CreateBugReportCommand.cs
|
||||||
|
├── EditBugReportCommand.cs
|
||||||
|
├── BugReportViewModel.cs
|
||||||
|
└── BugReportDetailViewModel.cs
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3️⃣ Application Service (1 فایل)
|
||||||
|
```
|
||||||
|
✓ AccountManagement.Application/
|
||||||
|
└── BugReportApplication.cs
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4️⃣ Infrastructure EFCore (4 فایل)
|
||||||
|
```
|
||||||
|
✓ AccountMangement.Infrastructure.EFCore/
|
||||||
|
├── Mappings/
|
||||||
|
│ ├── BugReportMapping.cs
|
||||||
|
│ ├── BugReportLogMapping.cs
|
||||||
|
│ └── BugReportScreenshotMapping.cs
|
||||||
|
└── Repository/
|
||||||
|
└── BugReportRepository.cs
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5️⃣ API Controller (1 فایل)
|
||||||
|
```
|
||||||
|
✓ ServiceHost/Controllers/
|
||||||
|
└── BugReportController.cs
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6️⃣ Admin Pages (8 فایل)
|
||||||
|
```
|
||||||
|
✓ ServiceHost/Areas/AdminNew/Pages/BugReport/
|
||||||
|
├── BugReportPageModel.cs
|
||||||
|
├── Index.cshtml.cs
|
||||||
|
├── Index.cshtml
|
||||||
|
├── Details.cshtml.cs
|
||||||
|
├── Details.cshtml
|
||||||
|
├── Edit.cshtml.cs
|
||||||
|
├── Edit.cshtml
|
||||||
|
├── Delete.cshtml.cs
|
||||||
|
└── Delete.cshtml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7️⃣ Documentation (2 فایل)
|
||||||
|
```
|
||||||
|
✓ BUG_REPORT_SYSTEM.md
|
||||||
|
✓ FLUTTER_BUG_REPORT_EXAMPLE.dart
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✏️ فایلهای اصلاح شده (2 فایل)
|
||||||
|
|
||||||
|
### 1. AccountManagement.Configuration/AccountManagementBootstrapper.cs
|
||||||
|
**تغییر:** اضافه کردن using برای BugReport
|
||||||
|
```csharp
|
||||||
|
using AccountManagement.Application.Contracts.BugReport;
|
||||||
|
```
|
||||||
|
|
||||||
|
**تغییر:** رجیستریشن سرویسها
|
||||||
|
```csharp
|
||||||
|
services.AddTransient<IBugReportApplication, BugReportApplication>();
|
||||||
|
services.AddTransient<IBugReportRepository, BugReportRepository>();
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. AccountMangement.Infrastructure.EFCore/AccountContext.cs
|
||||||
|
**تغییر:** اضافه کردن using
|
||||||
|
```csharp
|
||||||
|
using AccountManagement.Domain.BugReportAgg;
|
||||||
|
```
|
||||||
|
|
||||||
|
**تغییر:** اضافه کردن DbSets
|
||||||
|
```csharp
|
||||||
|
#region BugReport
|
||||||
|
public DbSet<BugReport> BugReports { get; set; }
|
||||||
|
public DbSet<BugReportLog> BugReportLogs { get; set; }
|
||||||
|
public DbSet<BugReportScreenshot> BugReportScreenshots { get; set; }
|
||||||
|
#endregion
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 موارد مورد نیاز قبل از استفاده
|
||||||
|
|
||||||
|
### 1. Database Migration
|
||||||
|
```powershell
|
||||||
|
# در Package Manager Console
|
||||||
|
cd AccountMangement.Infrastructure.EFCore
|
||||||
|
|
||||||
|
Add-Migration AddBugReportSystem
|
||||||
|
Update-Database
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. الگوی Enum برای Flutter
|
||||||
|
```dart
|
||||||
|
enum BugReportType {
|
||||||
|
crash, // 1
|
||||||
|
ui, // 2
|
||||||
|
performance, // 3
|
||||||
|
feature, // 4
|
||||||
|
network, // 5
|
||||||
|
camera, // 6
|
||||||
|
faceRecognition, // 7
|
||||||
|
database, // 8
|
||||||
|
login, // 9
|
||||||
|
other, // 10
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BugPriority {
|
||||||
|
critical, // 1
|
||||||
|
high, // 2
|
||||||
|
medium, // 3
|
||||||
|
low, // 4
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🚀 نقاط ورود
|
||||||
|
|
||||||
|
### API Endpoints
|
||||||
|
```
|
||||||
|
POST /api/bugreport/submit - ثبت گزارش جدید
|
||||||
|
GET /api/bugreport/list - دریافت لیست
|
||||||
|
GET /api/bugreport/{id} - دریافت جزئیات
|
||||||
|
PUT /api/bugreport/{id} - ویرایش وضعیت/اولویت
|
||||||
|
DELETE /api/bugreport/{id} - حذف گزارش
|
||||||
|
```
|
||||||
|
|
||||||
|
### Admin Pages
|
||||||
|
```
|
||||||
|
/AdminNew/BugReport - لیست گزارشها
|
||||||
|
/AdminNew/BugReport/Details/{id} - جزئیات کامل
|
||||||
|
/AdminNew/BugReport/Edit/{id} - ویرایش
|
||||||
|
/AdminNew/BugReport/Delete/{id} - حذف
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Database Schema
|
||||||
|
|
||||||
|
### BugReports جدول
|
||||||
|
```sql
|
||||||
|
- id (bigint, PK)
|
||||||
|
- Title (nvarchar(200))
|
||||||
|
- Description (ntext)
|
||||||
|
- UserEmail (nvarchar(150))
|
||||||
|
- AccountId (bigint, nullable)
|
||||||
|
- DeviceModel (nvarchar(100))
|
||||||
|
- OsVersion (nvarchar(50))
|
||||||
|
- Platform (nvarchar(50))
|
||||||
|
- Manufacturer (nvarchar(100))
|
||||||
|
- DeviceId (nvarchar(200))
|
||||||
|
- ScreenResolution (nvarchar(50))
|
||||||
|
- MemoryInMB (int)
|
||||||
|
- StorageInMB (int)
|
||||||
|
- BatteryLevel (int)
|
||||||
|
- IsCharging (bit)
|
||||||
|
- NetworkType (nvarchar(50))
|
||||||
|
- AppVersion (nvarchar(50))
|
||||||
|
- BuildNumber (nvarchar(50))
|
||||||
|
- PackageName (nvarchar(150))
|
||||||
|
- InstallTime (datetime2)
|
||||||
|
- LastUpdateTime (datetime2)
|
||||||
|
- Flavor (nvarchar(50))
|
||||||
|
- Type (int)
|
||||||
|
- Priority (int)
|
||||||
|
- Status (int)
|
||||||
|
- StackTrace (ntext, nullable)
|
||||||
|
- CreationDate (datetime2)
|
||||||
|
- UpdateDate (datetime2, nullable)
|
||||||
|
```
|
||||||
|
|
||||||
|
### BugReportLogs جدول
|
||||||
|
```sql
|
||||||
|
- id (bigint, PK)
|
||||||
|
- BugReportId (bigint, FK)
|
||||||
|
- Message (ntext)
|
||||||
|
- Timestamp (datetime2)
|
||||||
|
```
|
||||||
|
|
||||||
|
### BugReportScreenshots جدول
|
||||||
|
```sql
|
||||||
|
- id (bigint, PK)
|
||||||
|
- BugReportId (bigint, FK)
|
||||||
|
- Base64Data (ntext)
|
||||||
|
- FileName (nvarchar(255))
|
||||||
|
- UploadDate (datetime2)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✨ مثال درخواست API
|
||||||
|
|
||||||
|
```json
|
||||||
|
POST /api/bugreport/submit
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"title": "برنامه هنگام ورود خراب میشود",
|
||||||
|
"description": "هنگام فشار دادن دکمه ورود، برنامه کرش میکند",
|
||||||
|
"userEmail": "user@example.com",
|
||||||
|
"accountId": 123,
|
||||||
|
"deviceModel": "Samsung Galaxy S21",
|
||||||
|
"osVersion": "Android 12",
|
||||||
|
"platform": "Android",
|
||||||
|
"manufacturer": "Samsung",
|
||||||
|
"deviceId": "device-12345",
|
||||||
|
"screenResolution": "1440x3200",
|
||||||
|
"memoryInMB": 8000,
|
||||||
|
"storageInMB": 256000,
|
||||||
|
"batteryLevel": 75,
|
||||||
|
"isCharging": false,
|
||||||
|
"networkType": "4G",
|
||||||
|
"appVersion": "1.0.0",
|
||||||
|
"buildNumber": "100",
|
||||||
|
"packageName": "com.example.app",
|
||||||
|
"installTime": "2024-01-01T10:00:00Z",
|
||||||
|
"lastUpdateTime": "2024-12-07T14:30:00Z",
|
||||||
|
"flavor": "production",
|
||||||
|
"type": 1,
|
||||||
|
"priority": 2,
|
||||||
|
"stackTrace": "...",
|
||||||
|
"logs": ["log line 1", "log line 2"],
|
||||||
|
"screenshots": ["base64-string"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔐 Security Features
|
||||||
|
|
||||||
|
- ✅ Authorization برای Admin Pages (AdminAreaPermission required)
|
||||||
|
- ✅ API Authentication
|
||||||
|
- ✅ XSS Protection (Html.Raw محدود)
|
||||||
|
- ✅ CSRF Protection (ASP.NET Core default)
|
||||||
|
- ✅ Input Validation
|
||||||
|
- ✅ Safe Delete with Confirmation
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📚 Documentation Files
|
||||||
|
|
||||||
|
1. **BUG_REPORT_SYSTEM.md** - راهنمای کامل سیستم
|
||||||
|
2. **FLUTTER_BUG_REPORT_EXAMPLE.dart** - مثال پیادهسازی Flutter
|
||||||
|
3. **CHANGELOG.md** (این فایل) - خلاصه تغییرات
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Checklist پیادهسازی
|
||||||
|
|
||||||
|
- [x] Domain Models
|
||||||
|
- [x] Database Mappings
|
||||||
|
- [x] Repository Pattern
|
||||||
|
- [x] Application Services
|
||||||
|
- [x] API Endpoints
|
||||||
|
- [x] Admin UI Pages
|
||||||
|
- [x] Dependency Injection
|
||||||
|
- [x] Error Handling
|
||||||
|
- [x] Documentation
|
||||||
|
- [x] Flutter Example
|
||||||
|
- [ ] Database Migration (باید دستی اجرا شود)
|
||||||
|
- [ ] Testing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 مراحل بعدی
|
||||||
|
|
||||||
|
1. **اجرای Migration:**
|
||||||
|
```powershell
|
||||||
|
Add-Migration AddBugReportSystem
|
||||||
|
Update-Database
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **تست API:**
|
||||||
|
- استفاده از Postman/Thunder Client
|
||||||
|
- تست تمام endpoints
|
||||||
|
|
||||||
|
3. **تست Admin Panel:**
|
||||||
|
- دسترسی به /AdminNew/BugReport
|
||||||
|
- تست فیلترها و جستجو
|
||||||
|
- تست ویرایش و حذف
|
||||||
|
|
||||||
|
4. **Integration Flutter:**
|
||||||
|
- کپی کردن `FLUTTER_BUG_REPORT_EXAMPLE.dart`
|
||||||
|
- سازگار کردن با پروژه Flutter
|
||||||
|
- تست ثبت گزارشها
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📞 پشتیبانی
|
||||||
|
|
||||||
|
برای هر سوال یا مشکل:
|
||||||
|
1. بررسی کنید `BUG_REPORT_SYSTEM.md`
|
||||||
|
2. بررسی کنید logs و error messages
|
||||||
|
3. مطمئن شوید Migration اجرا شده است
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using _0_Framework.Application;
|
using _0_Framework.Application;
|
||||||
using _0_Framework.Domain;
|
using _0_Framework.Domain;
|
||||||
|
using CompanyManagment.App.Contracts.AndroidApkVersion;
|
||||||
|
|
||||||
namespace Company.Domain.AndroidApkVersionAgg;
|
namespace Company.Domain.AndroidApkVersionAgg;
|
||||||
|
|
||||||
@@ -8,14 +9,17 @@ public class AndroidApkVersion:EntityBase
|
|||||||
{
|
{
|
||||||
private AndroidApkVersion () { }
|
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;
|
VersionName = versionName;
|
||||||
VersionCode = versionCode;
|
VersionCode = versionCode;
|
||||||
IsActive = isActive;
|
IsActive = isActive;
|
||||||
Path = path;
|
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; }
|
public string Title { get; private set; }
|
||||||
@@ -23,6 +27,9 @@ public class AndroidApkVersion:EntityBase
|
|||||||
public string VersionCode{ get; private set; }
|
public string VersionCode{ get; private set; }
|
||||||
public IsActive IsActive { get; private set; }
|
public IsActive IsActive { get; private set; }
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
|
public ApkType ApkType { get; private set; }
|
||||||
|
public bool IsForce { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
public void Active()
|
public void Active()
|
||||||
{
|
{
|
||||||
@@ -33,4 +40,4 @@ public class AndroidApkVersion:EntityBase
|
|||||||
{
|
{
|
||||||
IsActive = IsActive.False;
|
IsActive = IsActive.False;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using _0_Framework_b.Domain;
|
using _0_Framework_b.Domain;
|
||||||
|
using CompanyManagment.App.Contracts.AndroidApkVersion;
|
||||||
|
|
||||||
namespace Company.Domain.AndroidApkVersionAgg;
|
namespace Company.Domain.AndroidApkVersionAgg;
|
||||||
|
|
||||||
public interface IAndroidApkVersionRepository:IRepository<long,AndroidApkVersion>
|
public interface IAndroidApkVersionRepository:IRepository<long,AndroidApkVersion>
|
||||||
{
|
{
|
||||||
IQueryable<AndroidApkVersion> GetActives();
|
IQueryable<AndroidApkVersion> GetActives(ApkType apkType);
|
||||||
|
AndroidApkVersion GetLatestActive(ApkType apkType);
|
||||||
void Remove(AndroidApkVersion entity);
|
void Remove(AndroidApkVersion entity);
|
||||||
System.Threading.Tasks.Task<string> GetLatestActiveVersionPath();
|
System.Threading.Tasks.Task<string> GetLatestActiveVersionPath(ApkType apkType);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using _0_Framework_b.Domain;
|
||||||
|
|
||||||
|
namespace Company.Domain.AuthorizedBankDetailsAgg
|
||||||
|
{
|
||||||
|
public class AuthorizedBankDetails : EntityBase
|
||||||
|
{
|
||||||
|
private AuthorizedBankDetails()
|
||||||
|
{
|
||||||
|
OwnersList = new List<AuthorizedBankDetailsOwner>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthorizedBankDetails(string cardNumber, string accountNumber, string ban, string bankName, List<AuthorizedBankDetailsOwner> ownersList)
|
||||||
|
{
|
||||||
|
CardNumber = cardNumber;
|
||||||
|
AccountNumber = accountNumber;
|
||||||
|
IBan = ban;
|
||||||
|
BankName = bankName;
|
||||||
|
OwnersList = ownersList ?? new List<AuthorizedBankDetailsOwner>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string CardNumber { get; private set; }
|
||||||
|
public string AccountNumber { get; private set; }
|
||||||
|
public string IBan { get; private set; }
|
||||||
|
public string BankName { get; private set; }
|
||||||
|
public List<AuthorizedBankDetailsOwner> OwnersList { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AuthorizedBankDetailsOwner // Value Object - not inheriting from EntityBase
|
||||||
|
{
|
||||||
|
private AuthorizedBankDetailsOwner() { }
|
||||||
|
|
||||||
|
public AuthorizedBankDetailsOwner(string fName, string lName, string nationalIdentifier, string customerType)
|
||||||
|
{
|
||||||
|
FName = fName;
|
||||||
|
LName = lName;
|
||||||
|
NationalIdentifier = nationalIdentifier;
|
||||||
|
CustomerType = customerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FName { get; private set; }
|
||||||
|
public string LName { get; private set; }
|
||||||
|
public string NationalIdentifier { get; private set; }
|
||||||
|
public string CustomerType { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using _0_Framework_b.Domain;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Company.Application.Contracts.AuthorizedBankDetails;
|
||||||
|
|
||||||
|
namespace Company.Domain.AuthorizedBankDetailsAgg
|
||||||
|
{
|
||||||
|
public interface IAuthorizedBankDetailsRepository : IRepository<long, AuthorizedBankDetails>
|
||||||
|
{
|
||||||
|
EditAuthorizedBankDetails GetDetails(long id);
|
||||||
|
List<AuthorizedBankDetailsViewModel> Search(AuthorizedBankDetailsSearchModel searchModel);
|
||||||
|
AuthorizedBankDetailsViewModel GetByIban(string iban);
|
||||||
|
}
|
||||||
|
}
|
||||||
190
Company.Domain/CameraBugReportAgg/CameraBugReport.cs
Normal file
190
Company.Domain/CameraBugReportAgg/CameraBugReport.cs
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using _0_Framework.Domain;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Company.Domain.CameraBugReportAgg;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// مدل دامنه برای گزارش خرابی دوربین
|
||||||
|
/// </summary>
|
||||||
|
public class CameraBugReport
|
||||||
|
{
|
||||||
|
[BsonId]
|
||||||
|
[BsonRepresentation(MongoDB.Bson.BsonType.String)]
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public CameraBugReport()
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid();
|
||||||
|
CreationDate = DateTime.Now;
|
||||||
|
Status = CameraBugReportStatus.Open;
|
||||||
|
Screenshots = new List<CameraBugReportScreenshot>();
|
||||||
|
Logs = new List<CameraBugReportLog>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CameraBugReport(
|
||||||
|
string title,
|
||||||
|
string description,
|
||||||
|
string userEmail,
|
||||||
|
string deviceModel,
|
||||||
|
string osVersion,
|
||||||
|
string manufacturer,
|
||||||
|
string buildNumber,
|
||||||
|
string appVersion,
|
||||||
|
string screenResolution,
|
||||||
|
bool isCharging,
|
||||||
|
int batteryLevel,
|
||||||
|
int storageInMB,
|
||||||
|
int memoryInMB,
|
||||||
|
string networkType,
|
||||||
|
string platform,
|
||||||
|
string deviceId,
|
||||||
|
string packageName,
|
||||||
|
DateTime installTime,
|
||||||
|
DateTime lastUpdateTime,
|
||||||
|
string flavor,
|
||||||
|
CameraBugReportType type,
|
||||||
|
CameraBugPriority priority,
|
||||||
|
long? accountId = null,
|
||||||
|
string stackTrace = null) : this()
|
||||||
|
|
||||||
|
{
|
||||||
|
Priority = priority;
|
||||||
|
Type = type;
|
||||||
|
Flavor = flavor;
|
||||||
|
LastUpdateTime = lastUpdateTime;
|
||||||
|
InstallTime = installTime;
|
||||||
|
PackageName = packageName;
|
||||||
|
BuildNumber = buildNumber;
|
||||||
|
AppVersion = appVersion;
|
||||||
|
NetworkType = networkType;
|
||||||
|
IsCharging = isCharging;
|
||||||
|
BatteryLevel = batteryLevel;
|
||||||
|
StorageInMB = storageInMB;
|
||||||
|
MemoryInMB = memoryInMB;
|
||||||
|
ScreenResolution = screenResolution;
|
||||||
|
DeviceId = deviceId;
|
||||||
|
Manufacturer = manufacturer;
|
||||||
|
Platform = platform;
|
||||||
|
OsVersion = osVersion;
|
||||||
|
DeviceModel = deviceModel;
|
||||||
|
AccountId = accountId;
|
||||||
|
UserEmail = userEmail;
|
||||||
|
Description = description;
|
||||||
|
Title = title;
|
||||||
|
StackTrace = stackTrace;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BsonElement("screenshots")]
|
||||||
|
public List<CameraBugReportScreenshot> Screenshots { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("logs")]
|
||||||
|
public List<CameraBugReportLog> Logs { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("updateDate")]
|
||||||
|
public DateTime? UpdateDate { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("creationDate")]
|
||||||
|
public DateTime CreationDate { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("stackTrace")]
|
||||||
|
public string StackTrace { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("status")]
|
||||||
|
public CameraBugReportStatus Status { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("priority")]
|
||||||
|
public CameraBugPriority Priority { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("type")]
|
||||||
|
public CameraBugReportType Type { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("flavor")]
|
||||||
|
public string Flavor { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("lastUpdateTime")]
|
||||||
|
public DateTime LastUpdateTime { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("installTime")]
|
||||||
|
public DateTime InstallTime { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("packageName")]
|
||||||
|
public string PackageName { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("buildNumber")]
|
||||||
|
public string BuildNumber { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("appVersion")]
|
||||||
|
public string AppVersion { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("networkType")]
|
||||||
|
public string NetworkType { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("isCharging")]
|
||||||
|
public bool IsCharging { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("batteryLevel")]
|
||||||
|
public int BatteryLevel { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("storageInMB")]
|
||||||
|
public int StorageInMB { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("memoryInMB")]
|
||||||
|
public int MemoryInMB { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("screenResolution")]
|
||||||
|
public string ScreenResolution { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("deviceId")]
|
||||||
|
public string DeviceId { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("manufacturer")]
|
||||||
|
public string Manufacturer { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("platform")]
|
||||||
|
public string Platform { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("osVersion")]
|
||||||
|
public string OsVersion { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("deviceModel")]
|
||||||
|
public string DeviceModel { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("accountId")]
|
||||||
|
public long? AccountId { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("userEmail")]
|
||||||
|
public string UserEmail { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("description")]
|
||||||
|
public string Description { get; private set; }
|
||||||
|
|
||||||
|
[BsonElement("title")]
|
||||||
|
public string Title { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
public void ChangeStatus(CameraBugReportStatus newStatus)
|
||||||
|
{
|
||||||
|
UpdateDate = DateTime.Now;
|
||||||
|
Status = newStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ChangePriority(CameraBugPriority newPriority)
|
||||||
|
{
|
||||||
|
Priority = newPriority;
|
||||||
|
UpdateDate = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddScreenshot(string base64Data, string fileName)
|
||||||
|
{
|
||||||
|
Screenshots.Add(new CameraBugReportScreenshot
|
||||||
|
{ Base64Data = base64Data, FileName = fileName, UploadDate = DateTime.Now });
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddLog(string logMessage)
|
||||||
|
{
|
||||||
|
Logs.Add(new CameraBugReportLog { Message = logMessage, Timestamp = DateTime.Now });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
20
Company.Domain/CameraBugReportAgg/CameraBugReportLog.cs
Normal file
20
Company.Domain/CameraBugReportAgg/CameraBugReportLog.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using _0_Framework.Domain;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Company.Domain.CameraBugReportAgg
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// لاگهای گزارش خرابی دوربین
|
||||||
|
/// </summary>
|
||||||
|
public class CameraBugReportLog : EntityBase
|
||||||
|
{
|
||||||
|
// FK و navigation property حذف شد برای MongoDB
|
||||||
|
[BsonElement("message")]
|
||||||
|
public string Message { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("timestamp")]
|
||||||
|
public DateTime Timestamp { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using _0_Framework.Domain;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Company.Domain.CameraBugReportAgg
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// عکسهای ضمیمه شده به گزارش خرابی دوربین (Base64 encoded)
|
||||||
|
/// </summary>
|
||||||
|
public class CameraBugReportScreenshot : EntityBase
|
||||||
|
{
|
||||||
|
// FK و navigation property حذف شد برای MongoDB
|
||||||
|
[BsonElement("base64Data")]
|
||||||
|
public string Base64Data { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("fileName")]
|
||||||
|
public string FileName { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("uploadDate")]
|
||||||
|
public DateTime UploadDate { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using _0_Framework.InfraStructure;
|
||||||
|
|
||||||
|
namespace Company.Domain.CameraBugReportAgg;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// رابط انبار گزارش خرابی دوربین برای MongoDB
|
||||||
|
/// </summary>
|
||||||
|
public interface ICameraBugReportRepository
|
||||||
|
{
|
||||||
|
// Async methods for MongoDB operations
|
||||||
|
Task CreateAsync(CameraBugReport bugReport);
|
||||||
|
Task UpdateAsync(CameraBugReport bugReport);
|
||||||
|
Task<CameraBugReport> GetByIdAsync(Guid id);
|
||||||
|
Task<List<CameraBugReport>> GetAllAsync();
|
||||||
|
Task<List<CameraBugReport>> GetAllAsync(int skip, int take);
|
||||||
|
Task DeleteAsync(Guid id);
|
||||||
|
Task<bool> IsExistAsync(Guid id);
|
||||||
|
Task<List<CameraBugReport>> FilterAsync(
|
||||||
|
CameraBugReportType? type = null,
|
||||||
|
CameraBugPriority? priority = null,
|
||||||
|
CameraBugReportStatus? status = null,
|
||||||
|
string searchTerm = null,
|
||||||
|
int skip = 0,
|
||||||
|
int take = 10);
|
||||||
|
Task<int> CountAsync(
|
||||||
|
CameraBugReportType? type = null,
|
||||||
|
CameraBugPriority? priority = null,
|
||||||
|
CameraBugReportStatus? status = null,
|
||||||
|
string searchTerm = null);
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Security.AccessControl;
|
||||||
using _0_Framework.Application;
|
using _0_Framework.Application;
|
||||||
using _0_Framework.Domain;
|
using _0_Framework.Domain;
|
||||||
using _0_Framework.Domain.CustomizeCheckoutShared.Enums;
|
using _0_Framework.Domain.CustomizeCheckoutShared.Enums;
|
||||||
@@ -12,25 +13,25 @@ namespace Company.Domain.CheckoutAgg;
|
|||||||
|
|
||||||
public class Checkout : EntityBase
|
public class Checkout : EntityBase
|
||||||
{
|
{
|
||||||
private Checkout()
|
public Checkout()
|
||||||
{
|
{
|
||||||
|
}
|
||||||
}
|
|
||||||
public Checkout(string employeeFullName, string fathersName, string nationalCode, string dateOfBirth,
|
public Checkout(string employeeFullName, string fathersName, string nationalCode, string dateOfBirth,
|
||||||
long employeeId, string workshopName, long workshopId, string contractNo, DateTime contractStart,
|
long employeeId, string workshopName, long workshopId, string contractNo, DateTime contractStart,
|
||||||
DateTime contractEnd, string month, string year, long contractId, long workingHoursId,
|
DateTime contractEnd, string month, string year, long contractId, long workingHoursId,
|
||||||
double monthlySalary, double baseYearsPay, double consumableItems, double housingAllowance,
|
double monthlySalary, double baseYearsPay, double consumableItems, double housingAllowance,
|
||||||
double overtimePay, double nightworkPay, double fridayPay, double missionPay, double shiftPay,
|
double overtimePay, double nightworkPay, double fridayPay, double missionPay, double shiftPay,
|
||||||
double familyAllowance, double bonusesPay, double yearsPay, double leavePay,
|
double familyAllowance, double bonusesPay, double yearsPay, double leavePay,
|
||||||
double insuranceDeduction, double taxDeducation, double installmentDeduction,
|
double insuranceDeduction, double taxDeducation, double installmentDeduction,
|
||||||
double salaryAidDeduction, double absenceDeduction, string sumOfWorkingDays
|
double salaryAidDeduction, double absenceDeduction, string sumOfWorkingDays
|
||||||
, string archiveCode, string personnelCode,
|
, string archiveCode, string personnelCode,
|
||||||
string totalClaims, string totalDeductions, double totalPayment, string signature, double marriedAllowance, bool leaveCheckout,
|
string totalClaims, string totalDeductions, double totalPayment, string signature, double marriedAllowance, bool leaveCheckout,
|
||||||
double creditLeaves, double absencePeriod, double averageHoursPerDay, bool hasRollCall, string overTimeWorkvalue,
|
double creditLeaves, double absencePeriod, double averageHoursPerDay, bool hasRollCall, string overTimeWorkvalue,
|
||||||
string overNightWorkValue, string fridayWorkValue, string rotatingShifValue, string absenceValue,
|
string overNightWorkValue, string fridayWorkValue, string rotatingShifValue, string absenceValue,
|
||||||
string totalDayOfLeaveCompute, string totalDayOfYearsCompute, string totalDayOfBunosesCompute,
|
string totalDayOfLeaveCompute, string totalDayOfYearsCompute, string totalDayOfBunosesCompute,
|
||||||
ICollection<CheckoutLoanInstallment> loanInstallments,
|
ICollection<CheckoutLoanInstallment> loanInstallments,
|
||||||
ICollection<CheckoutSalaryAid> salaryAids,CheckoutRollCall checkoutRollCall,TimeSpan employeeMandatoryHours)
|
ICollection<CheckoutSalaryAid> salaryAids, CheckoutRollCall checkoutRollCall, TimeSpan employeeMandatoryHours, bool hasInsuranceShareTheSameAsList)
|
||||||
{
|
{
|
||||||
EmployeeFullName = employeeFullName;
|
EmployeeFullName = employeeFullName;
|
||||||
FathersName = fathersName;
|
FathersName = fathersName;
|
||||||
@@ -91,6 +92,7 @@ public class Checkout : EntityBase
|
|||||||
SalaryAids = salaryAids;
|
SalaryAids = salaryAids;
|
||||||
CheckoutRollCall = checkoutRollCall;
|
CheckoutRollCall = checkoutRollCall;
|
||||||
EmployeeMandatoryHours = employeeMandatoryHours;
|
EmployeeMandatoryHours = employeeMandatoryHours;
|
||||||
|
HasInsuranceShareTheSameAsList = hasInsuranceShareTheSameAsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -99,7 +101,7 @@ public class Checkout : EntityBase
|
|||||||
public string Signature { get; private set; }
|
public string Signature { get; private set; }
|
||||||
public string FathersName { get; private set; }
|
public string FathersName { get; private set; }
|
||||||
public string NationalCode { get; private set; }
|
public string NationalCode { get; private set; }
|
||||||
public string DateOfBirth { get; private set; }
|
public string DateOfBirth { get; private set; }
|
||||||
public long EmployeeId { get; private set; }
|
public long EmployeeId { get; private set; }
|
||||||
|
|
||||||
public string WorkshopName { get; private set; }
|
public string WorkshopName { get; private set; }
|
||||||
@@ -135,7 +137,7 @@ public class Checkout : EntityBase
|
|||||||
public double SalaryAidDeduction { get; private set; }
|
public double SalaryAidDeduction { get; private set; }
|
||||||
|
|
||||||
public double AbsenceDeduction { get; private set; }
|
public double AbsenceDeduction { get; private set; }
|
||||||
|
|
||||||
public string SumOfWorkingDays { get; private set; }
|
public string SumOfWorkingDays { get; private set; }
|
||||||
public string ArchiveCode { get; private set; }
|
public string ArchiveCode { get; private set; }
|
||||||
public string PersonnelCode { get; private set; }
|
public string PersonnelCode { get; private set; }
|
||||||
@@ -157,58 +159,70 @@ public class Checkout : EntityBase
|
|||||||
//میانگین ساعت کار در یک روز
|
//میانگین ساعت کار در یک روز
|
||||||
public double AverageHoursPerDay { get; private set; }
|
public double AverageHoursPerDay { get; private set; }
|
||||||
public bool HasRollCall { get; private set; }
|
public bool HasRollCall { get; private set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// مقدار اضافه کار
|
/// مقدار اضافه کار
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string OverTimeWorkValue { get; private set; }
|
public string OverTimeWorkValue { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// مقدار شبکاری
|
/// مقدار شبکاری
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string OverNightWorkValue { get; private set; }
|
public string OverNightWorkValue { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// مقدار جمعه کاری
|
/// مقدار جمعه کاری
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string FridayWorkValue { get; private set; }
|
public string FridayWorkValue { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// درصد نوبت کاری
|
/// درصد نوبت کاری
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string RotatingShiftValue { get; private set; }
|
public string RotatingShiftValue { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// مقدار غیبت
|
/// مقدار غیبت
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string AbsenceValue { get; private set; }
|
public string AbsenceValue { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// تعداد روزهای محاسبه شده برای مزد مرخصی
|
/// تعداد روزهای محاسبه شده برای مزد مرخصی
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TotalDayOfLeaveCompute { get; private set; }
|
public string TotalDayOfLeaveCompute { get; private set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// تعداد روزهای محاسبه شده برای سنوات
|
/// تعداد روزهای محاسبه شده برای سنوات
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TotalDayOfYearsCompute { get; private set; }
|
public string TotalDayOfYearsCompute { get; private set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// تعداد روزهای محاسبه شده برای عیدی و پاداش
|
/// تعداد روزهای محاسبه شده برای عیدی و پاداش
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string TotalDayOfBunosesCompute { get; private set; }
|
public string TotalDayOfBunosesCompute { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// دارای تداخل مبلغ است. این در زمانی اتفاق می افتد که فیش مبلغ آن تغییر کرده ولی به دلیل مسائل قانونی امکان صدور دوباره آن وجود ندارد
|
/// دارای تداخل مبلغ است. این در زمانی اتفاق می افتد که فیش مبلغ آن تغییر کرده ولی به دلیل مسائل قانونی امکان صدور دوباره آن وجود ندارد
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool HasAmountConflict { get; private set; }
|
public bool HasAmountConflict { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ساعت موظفی پرسنل در ماه
|
/// ساعت موظفی پرسنل در ماه
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TimeSpan EmployeeMandatoryHours { get; set; }
|
public TimeSpan EmployeeMandatoryHours { get; set; }
|
||||||
|
|
||||||
#region valueObjects
|
|
||||||
|
|
||||||
public ICollection<CheckoutLoanInstallment> LoanInstallments { get; set; } = [];
|
/// <summary>
|
||||||
public ICollection<CheckoutSalaryAid> SalaryAids { get; set; } = [];
|
/// آیا حق بیمه مشابه لیست بیمه حساب شده؟
|
||||||
|
/// </summary>
|
||||||
|
public bool HasInsuranceShareTheSameAsList { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// آیا فیش نیاز به بروزرسانی دارد
|
||||||
|
/// </summary>
|
||||||
|
public bool IsUpdateNeeded { get; private set; }
|
||||||
|
|
||||||
|
public List<CheckoutWarningMessage> CheckoutWarningMessageList { get; set; }
|
||||||
|
|
||||||
|
#region valueObjects
|
||||||
|
|
||||||
|
public ICollection<CheckoutLoanInstallment> LoanInstallments { get; set; } = [];
|
||||||
|
public ICollection<CheckoutSalaryAid> SalaryAids { get; set; } = [];
|
||||||
public CheckoutRollCall CheckoutRollCall { get; private set; }
|
public CheckoutRollCall CheckoutRollCall { get; private set; }
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -277,7 +291,7 @@ public class Checkout : EntityBase
|
|||||||
var year = contarctStart.ToFarsiYear();
|
var year = contarctStart.ToFarsiYear();
|
||||||
var sumYear = year.Substring(Math.Max(0, year.Length - 2));
|
var sumYear = year.Substring(Math.Max(0, year.Length - 2));
|
||||||
|
|
||||||
|
|
||||||
ContractNo = archiveCode + "/" + personnelCode + "/" + sumYear + "/" + month;
|
ContractNo = archiveCode + "/" + personnelCode + "/" + sumYear + "/" + month;
|
||||||
}
|
}
|
||||||
public void Active()
|
public void Active()
|
||||||
@@ -312,7 +326,7 @@ public class Checkout : EntityBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void SetSalaryAid(ICollection<CheckoutSalaryAid> salaryAids,double salaryAidAmount)
|
public void SetSalaryAid(ICollection<CheckoutSalaryAid> salaryAids, double salaryAidAmount)
|
||||||
{
|
{
|
||||||
SalaryAids = salaryAids;
|
SalaryAids = salaryAids;
|
||||||
SalaryAidDeduction = salaryAidAmount;
|
SalaryAidDeduction = salaryAidAmount;
|
||||||
@@ -330,30 +344,45 @@ public class Checkout : EntityBase
|
|||||||
|
|
||||||
public void SetAmountConflict(bool hasAmountConflict)
|
public void SetAmountConflict(bool hasAmountConflict)
|
||||||
{
|
{
|
||||||
HasAmountConflict = hasAmountConflict;
|
HasAmountConflict = hasAmountConflict;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetEmployeeMandatoryHours(TimeSpan employeeMandatoryHours)
|
public void SetEmployeeMandatoryHours(TimeSpan employeeMandatoryHours)
|
||||||
{
|
{
|
||||||
EmployeeMandatoryHours = employeeMandatoryHours;
|
EmployeeMandatoryHours = employeeMandatoryHours;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetInsuranceShare()
|
||||||
|
{
|
||||||
|
HasInsuranceShareTheSameAsList = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// نیاز به آپدیت
|
||||||
|
/// </summary>
|
||||||
|
public void SetUpdateNeeded()
|
||||||
|
{
|
||||||
|
IsUpdateNeeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class CheckoutRollCall
|
public class CheckoutRollCall
|
||||||
{
|
{
|
||||||
private CheckoutRollCall(){}
|
private CheckoutRollCall() { }
|
||||||
public CheckoutRollCall(TimeSpan totalMandatoryTimeSpan, TimeSpan totalPresentTimeSpan, TimeSpan totalBreakTimeSpan,
|
public CheckoutRollCall(TimeSpan totalMandatoryTimeSpan, TimeSpan totalPresentTimeSpan, TimeSpan totalBreakTimeSpan,
|
||||||
TimeSpan totalWorkingTimeSpan, TimeSpan totalPaidLeaveTmeSpan, TimeSpan totalSickLeaveTimeSpan,
|
TimeSpan totalWorkingTimeSpan, TimeSpan totalPaidLeaveTmeSpan, TimeSpan totalSickLeaveTimeSpan,
|
||||||
ICollection<CheckoutRollCallDay> rollCallDaysCollection)
|
ICollection<CheckoutRollCallDay> rollCallDaysCollection)
|
||||||
{
|
{
|
||||||
TotalMandatoryTimeSpan = totalMandatoryTimeSpan;
|
TotalMandatoryTimeSpan = totalMandatoryTimeSpan;
|
||||||
TotalPresentTimeSpan = totalPresentTimeSpan;
|
TotalPresentTimeSpan = totalPresentTimeSpan;
|
||||||
TotalBreakTimeSpan = totalBreakTimeSpan;
|
TotalBreakTimeSpan = totalBreakTimeSpan;
|
||||||
TotalWorkingTimeSpan = totalWorkingTimeSpan;
|
TotalWorkingTimeSpan = totalWorkingTimeSpan;
|
||||||
TotalPaidLeaveTmeSpan = totalPaidLeaveTmeSpan;
|
TotalPaidLeaveTmeSpan = totalPaidLeaveTmeSpan;
|
||||||
TotalSickLeaveTimeSpan = totalSickLeaveTimeSpan;
|
TotalSickLeaveTimeSpan = totalSickLeaveTimeSpan;
|
||||||
RollCallDaysCollection = rollCallDaysCollection;
|
RollCallDaysCollection = rollCallDaysCollection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -394,27 +423,27 @@ public class CheckoutRollCall
|
|||||||
|
|
||||||
public class CheckoutRollCallDay
|
public class CheckoutRollCallDay
|
||||||
{
|
{
|
||||||
private CheckoutRollCallDay(){}
|
private CheckoutRollCallDay() { }
|
||||||
public CheckoutRollCallDay(DateTime date, string firstStartDate, string firstEndDate,
|
public CheckoutRollCallDay(DateTime date, string firstStartDate, string firstEndDate,
|
||||||
string secondStartDate, string secondEndDate, TimeSpan breakTimeSpan,
|
string secondStartDate, string secondEndDate, TimeSpan breakTimeSpan,
|
||||||
bool isSliced, TimeSpan workingTimeSpan, bool isAbsent, bool isFriday,
|
bool isSliced, TimeSpan workingTimeSpan, bool isAbsent, bool isFriday,
|
||||||
bool isHoliday, string leaveType)
|
bool isHoliday, string leaveType)
|
||||||
{
|
{
|
||||||
Date = date;
|
Date = date;
|
||||||
FirstStartDate = firstStartDate;
|
FirstStartDate = firstStartDate;
|
||||||
FirstEndDate = firstEndDate;
|
FirstEndDate = firstEndDate;
|
||||||
SecondStartDate = secondStartDate;
|
SecondStartDate = secondStartDate;
|
||||||
SecondEndDate = secondEndDate;
|
SecondEndDate = secondEndDate;
|
||||||
BreakTimeSpan = breakTimeSpan;
|
BreakTimeSpan = breakTimeSpan;
|
||||||
IsSliced = isSliced;
|
IsSliced = isSliced;
|
||||||
WorkingTimeSpan = workingTimeSpan;
|
WorkingTimeSpan = workingTimeSpan;
|
||||||
IsAbsent = isAbsent;
|
IsAbsent = isAbsent;
|
||||||
IsFriday = isFriday;
|
IsFriday = isFriday;
|
||||||
IsHoliday = isHoliday;
|
IsHoliday = isHoliday;
|
||||||
LeaveType = leaveType;
|
LeaveType = leaveType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long Id { get; set; }
|
public long Id { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// تاریخ
|
/// تاریخ
|
||||||
@@ -458,12 +487,12 @@ public class CheckoutRollCallDay
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// آیا غیبت است
|
/// آیا غیبت است
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsAbsent { get; private set; }
|
public bool IsAbsent { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// آیا جمعه است
|
/// آیا جمعه است
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsFriday { get; private set; }
|
public bool IsFriday { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// آیا تعطیل رسمی است
|
/// آیا تعطیل رسمی است
|
||||||
@@ -475,6 +504,6 @@ public class CheckoutRollCallDay
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string LeaveType { get; private set; }
|
public string LeaveType { get; private set; }
|
||||||
|
|
||||||
public long CheckoutId { get; set; }
|
public long CheckoutId { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
32
Company.Domain/CheckoutAgg/CheckoutWarningMessage.cs
Normal file
32
Company.Domain/CheckoutAgg/CheckoutWarningMessage.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using _0_Framework.Application.Enums;
|
||||||
|
using _0_Framework.Domain;
|
||||||
|
|
||||||
|
namespace Company.Domain.CheckoutAgg;
|
||||||
|
|
||||||
|
public class CheckoutWarningMessage : EntityBaseWithoutCreationDate
|
||||||
|
{
|
||||||
|
public CheckoutWarningMessage(string warningMessage, long checkoutId, TypeOfCheckoutWarning typeOfCheckoutWarning)
|
||||||
|
{
|
||||||
|
WarningMessage = warningMessage;
|
||||||
|
CheckoutId = checkoutId;
|
||||||
|
TypeOfCheckoutWarning = typeOfCheckoutWarning;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پیام هشدار
|
||||||
|
/// </summary>
|
||||||
|
public string WarningMessage { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// آی دی فیش حقوقی
|
||||||
|
/// </summary>
|
||||||
|
public long CheckoutId { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// نوع هشدار فیش حقوقی
|
||||||
|
/// </summary>
|
||||||
|
public TypeOfCheckoutWarning TypeOfCheckoutWarning { get; private set; }
|
||||||
|
|
||||||
|
public Checkout Checkout { get; set; }
|
||||||
|
}
|
||||||
@@ -75,5 +75,5 @@ public interface IPersonalContractingPartyRepository :IRepository<long, Personal
|
|||||||
Task<GetLegalContractingPartyDetailsViewModel> GetLegalDetails(long id);
|
Task<GetLegalContractingPartyDetailsViewModel> GetLegalDetails(long id);
|
||||||
|
|
||||||
Task<PersonalContractingParty> GetByNationalCode(string nationalCode);
|
Task<PersonalContractingParty> GetByNationalCode(string nationalCode);
|
||||||
Task<PersonalContractingParty> GetByRegisterId(string registerId);
|
Task<PersonalContractingParty> GetByNationalId(string registerId);
|
||||||
}
|
}
|
||||||
@@ -251,6 +251,35 @@ public class PersonalContractingParty : EntityBase
|
|||||||
this.IsAuthenticated = true;
|
this.IsAuthenticated = true;
|
||||||
Phone = phone;
|
Phone = phone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UnAuthenticateRealEdit(string fName, string lName, string fatherName,string idNumber,
|
||||||
|
string idNumberSeri, string idNumberSerial, string dateOfBirth, Gender gender,string phone)
|
||||||
|
{
|
||||||
|
this.FName = fName;
|
||||||
|
this.LName = lName;
|
||||||
|
this.FatherName = fatherName;
|
||||||
|
this.IdNumberSeri = idNumberSeri;
|
||||||
|
this.IdNumberSerial = idNumberSerial;
|
||||||
|
this.DateOfBirth = !string.IsNullOrWhiteSpace(dateOfBirth) ? dateOfBirth.ToGeorgianDateTime() : null;
|
||||||
|
this.IdNumber = idNumber;
|
||||||
|
this.Gender = gender;
|
||||||
|
Phone = phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnAuthenticateLegalEdit(string fName, string lName, string fatherName, string idNumber,
|
||||||
|
string idNumberSeri,
|
||||||
|
string idNumberSerial, string dateOfBirth, Gender gender, string phone)
|
||||||
|
{
|
||||||
|
CeoFName = fName;
|
||||||
|
CeoLName = lName;
|
||||||
|
this.FatherName = fatherName;
|
||||||
|
this.IdNumberSeri = idNumberSeri;
|
||||||
|
this.IdNumberSerial = idNumberSerial;
|
||||||
|
this.DateOfBirth = !string.IsNullOrWhiteSpace(dateOfBirth) ? dateOfBirth.ToGeorgianDateTime() : null;
|
||||||
|
this.IdNumber = idNumber;
|
||||||
|
this.Gender = gender;
|
||||||
|
Phone = phone;
|
||||||
|
}
|
||||||
|
|
||||||
public void RegisterComplete(string fatherName, string idNumberSeri, string idNumberSerial, DateTime dateOfBirth, Gender gender)
|
public void RegisterComplete(string fatherName, string idNumberSeri, string idNumberSerial, DateTime dateOfBirth, Gender gender)
|
||||||
{
|
{
|
||||||
@@ -261,4 +290,13 @@ public class PersonalContractingParty : EntityBase
|
|||||||
this.Gender = gender;
|
this.Gender = gender;
|
||||||
this.IsAuthenticated = true;
|
this.IsAuthenticated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void EditLegalPartyFromInstitution(string legalPosition, string companyName,
|
||||||
|
string registerId,string nationalId)
|
||||||
|
{
|
||||||
|
LegalPosition = legalPosition;
|
||||||
|
LName = companyName;
|
||||||
|
RegisterId = registerId;
|
||||||
|
NationalId = nationalId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using _0_Framework.Application;
|
using _0_Framework.Application;
|
||||||
|
using _0_Framework.Application.Enums;
|
||||||
using _0_Framework.Domain;
|
using _0_Framework.Domain;
|
||||||
using _0_Framework.Domain.CustomizeCheckoutShared.Enums;
|
using _0_Framework.Domain.CustomizeCheckoutShared.Enums;
|
||||||
using _0_Framework.Domain.CustomizeCheckoutShared.ValueObjects;
|
using _0_Framework.Domain.CustomizeCheckoutShared.ValueObjects;
|
||||||
@@ -33,7 +34,8 @@ public class CustomizeCheckout : EntityBase
|
|||||||
ICollection<CustomizeCheckoutSalaryAid> customizeCheckoutSalaryAids,
|
ICollection<CustomizeCheckoutSalaryAid> customizeCheckoutSalaryAids,
|
||||||
ICollection<CustomizeCheckoutReward> customizeCheckoutRewards, TimeSpan lateToWorkValue, double settingSalary,
|
ICollection<CustomizeCheckoutReward> customizeCheckoutRewards, TimeSpan lateToWorkValue, double settingSalary,
|
||||||
double dailyWage, WorkshopShiftStatus shiftStatus, IrregularShift irregularShift,
|
double dailyWage, WorkshopShiftStatus shiftStatus, IrregularShift irregularShift,
|
||||||
ICollection<CustomizeRotatingShift> customizeRotatingShifts, ICollection<CustomizeCheckoutRegularShift> employeeSettingsShifts)
|
ICollection<CustomizeRotatingShift> customizeRotatingShifts, ICollection<CustomizeCheckoutRegularShift> employeeSettingsShifts,
|
||||||
|
ICollection<CheckoutDynamicDeductionItem> checkoutDynamicDeductions)
|
||||||
{
|
{
|
||||||
YearInt = Convert.ToInt32(contractStart.ToFarsi().Substring(0, 4));
|
YearInt = Convert.ToInt32(contractStart.ToFarsi().Substring(0, 4));
|
||||||
MonthInt = Convert.ToInt32(contractStart.ToFarsi().Substring(5, 2));
|
MonthInt = Convert.ToInt32(contractStart.ToFarsi().Substring(5, 2));
|
||||||
@@ -83,6 +85,7 @@ public class CustomizeCheckout : EntityBase
|
|||||||
IrregularShift = irregularShift;
|
IrregularShift = irregularShift;
|
||||||
CustomizeRotatingShifts = customizeRotatingShifts;
|
CustomizeRotatingShifts = customizeRotatingShifts;
|
||||||
RegularShifts = employeeSettingsShifts;
|
RegularShifts = employeeSettingsShifts;
|
||||||
|
CheckoutDynamicDeductions = checkoutDynamicDeductions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -286,6 +289,7 @@ public class CustomizeCheckout : EntityBase
|
|||||||
public ICollection<CustomizeCheckoutLoanInstallments> CustomizeCheckoutLoanInstallments { get; set; }
|
public ICollection<CustomizeCheckoutLoanInstallments> CustomizeCheckoutLoanInstallments { get; set; }
|
||||||
public ICollection<CustomizeCheckoutSalaryAid> CustomizeCheckoutSalaryAids { get; set; }
|
public ICollection<CustomizeCheckoutSalaryAid> CustomizeCheckoutSalaryAids { get; set; }
|
||||||
public ICollection<CustomizeCheckoutReward> CustomizeCheckoutRewards { get; set; }
|
public ICollection<CustomizeCheckoutReward> CustomizeCheckoutRewards { get; set; }
|
||||||
|
public ICollection<CheckoutDynamicDeductionItem> CheckoutDynamicDeductions { get; private set; }
|
||||||
|
|
||||||
public IrregularShift IrregularShift { get; set; }
|
public IrregularShift IrregularShift { get; set; }
|
||||||
public ICollection<CustomizeRotatingShift> CustomizeRotatingShifts { get; set; }
|
public ICollection<CustomizeRotatingShift> CustomizeRotatingShifts { get; set; }
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using Company.Domain.CustomizeCheckoutTempAgg.ValueObjects;
|
|||||||
using _0_Framework.Domain.CustomizeCheckoutShared.Enums;
|
using _0_Framework.Domain.CustomizeCheckoutShared.Enums;
|
||||||
using _0_Framework.Domain.CustomizeCheckoutShared.ValueObjects;
|
using _0_Framework.Domain.CustomizeCheckoutShared.ValueObjects;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using _0_Framework.Application.Enums;
|
||||||
|
|
||||||
|
|
||||||
namespace Company.Domain.CustomizeCheckoutTempAgg;
|
namespace Company.Domain.CustomizeCheckoutTempAgg;
|
||||||
@@ -21,7 +22,8 @@ public class CustomizeCheckoutTemp : EntityBase
|
|||||||
{
|
{
|
||||||
LateToWorkValue = lateToWorkValue;
|
LateToWorkValue = lateToWorkValue;
|
||||||
}
|
}
|
||||||
public CustomizeCheckoutTemp(DateTime contractStart, DateTime contractEnd, long employeeId, string employeeFName,
|
public CustomizeCheckoutTemp(
|
||||||
|
DateTime contractStart, DateTime contractEnd, long employeeId, string employeeFName,
|
||||||
string employeeLName, DateTime employeeDateOfBirth,
|
string employeeLName, DateTime employeeDateOfBirth,
|
||||||
string employeeNationalCode, string workshopFullName, long workshopId, long? contractId,
|
string employeeNationalCode, string workshopFullName, long workshopId, long? contractId,
|
||||||
double monthlySalary, double fridayPay, double overTimePay, double baseYearsPay, double bonusesPay,
|
double monthlySalary, double fridayPay, double overTimePay, double baseYearsPay, double bonusesPay,
|
||||||
@@ -37,7 +39,8 @@ public class CustomizeCheckoutTemp : EntityBase
|
|||||||
ICollection<CustomizeCheckoutTempSalaryAid> customizeCheckoutSalaryAids,
|
ICollection<CustomizeCheckoutTempSalaryAid> customizeCheckoutSalaryAids,
|
||||||
ICollection<CustomizeCheckoutTempReward> customizeCheckoutRewards,
|
ICollection<CustomizeCheckoutTempReward> customizeCheckoutRewards,
|
||||||
TimeSpan lateToWorkValue, double settingSalary, double dailyWage, WorkshopShiftStatus shiftStatus, IrregularShift irregularShift,
|
TimeSpan lateToWorkValue, double settingSalary, double dailyWage, WorkshopShiftStatus shiftStatus, IrregularShift irregularShift,
|
||||||
ICollection<CustomizeRotatingShift> customizeRotatingShifts, ICollection<CustomizeCheckoutRegularShift> employeeSettingsShifts)
|
ICollection<CustomizeRotatingShift> customizeRotatingShifts, ICollection<CustomizeCheckoutRegularShift> employeeSettingsShifts,
|
||||||
|
ICollection<CheckoutDynamicDeductionItem> checkoutDynamicDeductions)
|
||||||
{
|
{
|
||||||
YearInt = Convert.ToInt32(contractStart.ToFarsi().Substring(0, 4));
|
YearInt = Convert.ToInt32(contractStart.ToFarsi().Substring(0, 4));
|
||||||
MonthInt = Convert.ToInt32(contractStart.ToFarsi().Substring(5, 2));
|
MonthInt = Convert.ToInt32(contractStart.ToFarsi().Substring(5, 2));
|
||||||
@@ -87,6 +90,7 @@ public class CustomizeCheckoutTemp : EntityBase
|
|||||||
IrregularShift = irregularShift;
|
IrregularShift = irregularShift;
|
||||||
CustomizeRotatingShifts = customizeRotatingShifts;
|
CustomizeRotatingShifts = customizeRotatingShifts;
|
||||||
RegularShifts = employeeSettingsShifts;
|
RegularShifts = employeeSettingsShifts;
|
||||||
|
CheckoutDynamicDeductions = checkoutDynamicDeductions;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Getters
|
#region Getters
|
||||||
@@ -123,6 +127,7 @@ public class CustomizeCheckoutTemp : EntityBase
|
|||||||
public IrregularShift IrregularShift { get; set; }
|
public IrregularShift IrregularShift { get; set; }
|
||||||
public ICollection<CustomizeRotatingShift> CustomizeRotatingShifts { get; set; }
|
public ICollection<CustomizeRotatingShift> CustomizeRotatingShifts { get; set; }
|
||||||
public ICollection<CustomizeCheckoutRegularShift> RegularShifts { get; set; }
|
public ICollection<CustomizeCheckoutRegularShift> RegularShifts { get; set; }
|
||||||
|
public ICollection<CheckoutDynamicDeductionItem> CheckoutDynamicDeductions { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -389,4 +394,4 @@ public class CustomizeCheckoutTemp : EntityBase
|
|||||||
{
|
{
|
||||||
HasAmountConflict = hasConflict;
|
HasAmountConflict = hasConflict;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace Company.Domain.EmployeeDocumentsAgg
|
|||||||
{
|
{
|
||||||
WorkshopId = workshopId;
|
WorkshopId = workshopId;
|
||||||
EmployeeId = employeeId;
|
EmployeeId = employeeId;
|
||||||
Gender = gender;
|
Gender = gender??string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private EmployeeDocuments()
|
private EmployeeDocuments()
|
||||||
|
|||||||
189
Company.Domain/EmployeeFaceEmbeddingAgg/EmployeeFaceEmbedding.cs
Normal file
189
Company.Domain/EmployeeFaceEmbeddingAgg/EmployeeFaceEmbedding.cs
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Company.Domain.EmployeeFaceEmbeddingAgg;
|
||||||
|
|
||||||
|
public class EmployeeFaceEmbedding
|
||||||
|
{
|
||||||
|
public EmployeeFaceEmbedding()
|
||||||
|
{
|
||||||
|
EmbeddingHistory = new List<EmbeddingHistoryItem>();
|
||||||
|
MetadataHistory = new List<MetadataHistoryItem>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmployeeFaceEmbedding(string employeeFullName, long employeeId, long workshopId,
|
||||||
|
List<double> embeddings, EmployeeFaceEmbeddingMetadata metadata)
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid().ToString();
|
||||||
|
EmployeeFullName = employeeFullName;
|
||||||
|
EmployeeId = employeeId;
|
||||||
|
WorkshopId = workshopId;
|
||||||
|
Embeddings = embeddings;
|
||||||
|
Metadata = metadata;
|
||||||
|
EmbeddingHistory = new List<EmbeddingHistoryItem>();
|
||||||
|
MetadataHistory = new List<MetadataHistoryItem>();
|
||||||
|
CreatedAt = DateTime.UtcNow;
|
||||||
|
UpdatedAt = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BsonId]
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("employeeFullName")]
|
||||||
|
public string EmployeeFullName { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("employeeId")]
|
||||||
|
public long EmployeeId { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("workshopId")]
|
||||||
|
public long WorkshopId { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("embeddings")]
|
||||||
|
public List<double> Embeddings { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("metadata")]
|
||||||
|
public EmployeeFaceEmbeddingMetadata Metadata { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("embeddingHistory")]
|
||||||
|
public List<EmbeddingHistoryItem> EmbeddingHistory { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("metadataHistory")]
|
||||||
|
public List<MetadataHistoryItem> MetadataHistory { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("createdAt")]
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("updatedAt")]
|
||||||
|
public DateTime UpdatedAt { get; set; }
|
||||||
|
|
||||||
|
public void UpdateEmbedding(List<double> newEmbedding, double confidence, double refinementPercentage)
|
||||||
|
{
|
||||||
|
if (Embeddings != null)
|
||||||
|
{
|
||||||
|
EmbeddingHistory.Add(new EmbeddingHistoryItem
|
||||||
|
{
|
||||||
|
Embedding = new List<double>(Embeddings),
|
||||||
|
Timestamp = DateTime.UtcNow,
|
||||||
|
Confidence = confidence,
|
||||||
|
RefinementPercentage = refinementPercentage
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Embeddings = newEmbedding;
|
||||||
|
UpdatedAt = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateMetadata(EmployeeFaceEmbeddingMetadata newMetadata, double confidence, double refinementPercentage)
|
||||||
|
{
|
||||||
|
if (Metadata != null)
|
||||||
|
{
|
||||||
|
MetadataHistory.Add(new MetadataHistoryItem
|
||||||
|
{
|
||||||
|
Metadata = Metadata,
|
||||||
|
Timestamp = DateTime.UtcNow,
|
||||||
|
Confidence = confidence,
|
||||||
|
RefinementPercentage = refinementPercentage
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Metadata = newMetadata;
|
||||||
|
UpdatedAt = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateEmployeeInfo(string employeeFullName, long workshopId)
|
||||||
|
{
|
||||||
|
EmployeeFullName = employeeFullName;
|
||||||
|
WorkshopId = workshopId;
|
||||||
|
UpdatedAt = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EmployeeFaceEmbeddingMetadata
|
||||||
|
{
|
||||||
|
[BsonElement("avg_eye_distance_normalized")]
|
||||||
|
public double AvgEyeDistanceNormalized { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("avg_eye_to_face_ratio")]
|
||||||
|
public double AvgEyeToFaceRatio { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("avg_face_aspect_ratio")]
|
||||||
|
public double AvgFaceAspectRatio { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("avg_detection_confidence")]
|
||||||
|
public double AvgDetectionConfidence { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("avg_keypoints_normalized")]
|
||||||
|
public EmployeeFaceEmbeddingKeypoints AvgKeypointsNormalized { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("per_image_metadata")]
|
||||||
|
public List<ImageMetadata> PerImageMetadata { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EmployeeFaceEmbeddingKeypoints
|
||||||
|
{
|
||||||
|
[BsonElement("left_eye")]
|
||||||
|
public double[] LeftEye { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("right_eye")]
|
||||||
|
public double[] RightEye { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("nose")]
|
||||||
|
public double[] Nose { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("mouth_left")]
|
||||||
|
public double[] MouthLeft { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("mouth_right")]
|
||||||
|
public double[] MouthRight { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImageMetadata
|
||||||
|
{
|
||||||
|
[BsonElement("face_aspect_ratio")]
|
||||||
|
public double FaceAspectRatio { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("eye_distance_normalized")]
|
||||||
|
public double EyeDistanceNormalized { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("eye_to_face_ratio")]
|
||||||
|
public double EyeToFaceRatio { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("detection_confidence")]
|
||||||
|
public double DetectionConfidence { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("keypoints_normalized")]
|
||||||
|
public EmployeeFaceEmbeddingKeypoints KeypointsNormalized { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EmbeddingHistoryItem
|
||||||
|
{
|
||||||
|
[BsonElement("embedding")]
|
||||||
|
public List<double> Embedding { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("timestamp")]
|
||||||
|
public DateTime Timestamp { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("confidence")]
|
||||||
|
public double Confidence { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("refinementPercentage")]
|
||||||
|
public double RefinementPercentage { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MetadataHistoryItem
|
||||||
|
{
|
||||||
|
[BsonElement("metadata")]
|
||||||
|
public EmployeeFaceEmbeddingMetadata Metadata { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("timestamp")]
|
||||||
|
public DateTime Timestamp { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("confidence")]
|
||||||
|
public double Confidence { get; set; }
|
||||||
|
|
||||||
|
[BsonElement("refinementPercentage")]
|
||||||
|
public double RefinementPercentage { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Company.Domain.EmployeeFaceEmbeddingAgg;
|
||||||
|
|
||||||
|
public interface IEmployeeFaceEmbeddingRepository
|
||||||
|
{
|
||||||
|
Task CreateAsync(EmployeeFaceEmbedding employeeFaceEmbedding);
|
||||||
|
Task UpdateAsync(EmployeeFaceEmbedding employeeFaceEmbedding);
|
||||||
|
Task<EmployeeFaceEmbedding> GetByIdAsync(string id);
|
||||||
|
Task<EmployeeFaceEmbedding> GetByEmployeeIdAsync(long employeeId);
|
||||||
|
Task<List<EmployeeFaceEmbedding>> GetByWorkshopIdAsync(long workshopId);
|
||||||
|
Task<List<EmployeeFaceEmbedding>> GetByWorkshopIdsAsync(List<long> workshopIds);
|
||||||
|
Task DeleteAsync(string id);
|
||||||
|
}
|
||||||
108
Company.Domain/FinancialInvoiceAgg/FinancialInvoice.cs
Normal file
108
Company.Domain/FinancialInvoiceAgg/FinancialInvoice.cs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using _0_Framework.Domain;
|
||||||
|
using Company.Domain.PaymentTransactionAgg;
|
||||||
|
using CompanyManagment.App.Contracts.FinancialInvoice;
|
||||||
|
|
||||||
|
namespace Company.Domain.FinancialInvoiceAgg;
|
||||||
|
|
||||||
|
public class FinancialInvoice : EntityBase
|
||||||
|
{
|
||||||
|
|
||||||
|
public string InvoiceNumber { get; private set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public FinancialInvoiceStatus Status { get; private set; }
|
||||||
|
public DateTime? PaidAt { get; private set; }
|
||||||
|
public double Amount { get; private set; }
|
||||||
|
public Guid PublicId { get; private set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
|
||||||
|
public List<PaymentTransaction> PaymentTransactions { get; private set; }
|
||||||
|
public long ContractingPartyId { get; private set; }
|
||||||
|
|
||||||
|
public List<FinancialInvoiceItem> Items { get; private set; }
|
||||||
|
|
||||||
|
public FinancialInvoice(double amount, long contractingPartyId, string description)
|
||||||
|
{
|
||||||
|
InvoiceNumber = GenerateInvoiceNumber();
|
||||||
|
Status = FinancialInvoiceStatus.Unpaid;
|
||||||
|
Amount = amount;
|
||||||
|
PublicId = Guid.NewGuid();
|
||||||
|
ContractingPartyId = contractingPartyId;
|
||||||
|
Description = description;
|
||||||
|
IsActive = true;
|
||||||
|
Items = [];
|
||||||
|
PaymentTransactions = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddItem(FinancialInvoiceItem item)
|
||||||
|
{
|
||||||
|
Items ??= [];
|
||||||
|
|
||||||
|
Items.Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetItems(List<FinancialInvoiceItem> items)
|
||||||
|
{
|
||||||
|
Items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetPaid(DateTime paidAt)
|
||||||
|
{
|
||||||
|
Status = FinancialInvoiceStatus.Paid;
|
||||||
|
PaidAt = paidAt;
|
||||||
|
}
|
||||||
|
public void SetUnpaid()
|
||||||
|
{
|
||||||
|
Status = FinancialInvoiceStatus.Unpaid;
|
||||||
|
PaidAt = null;
|
||||||
|
}
|
||||||
|
public void SetCancelled()
|
||||||
|
{
|
||||||
|
Status = FinancialInvoiceStatus.Cancelled;
|
||||||
|
PaidAt = null;
|
||||||
|
}
|
||||||
|
public void SetRefunded()
|
||||||
|
{
|
||||||
|
Status = FinancialInvoiceStatus.Refunded;
|
||||||
|
PaidAt = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DeActivate()
|
||||||
|
{
|
||||||
|
IsActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetInvoiceNumber(string invoiceNumber)
|
||||||
|
{
|
||||||
|
InvoiceNumber = invoiceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateInvoiceNumber()
|
||||||
|
{
|
||||||
|
var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss");
|
||||||
|
var random = new Random().Next(1000, 9999);
|
||||||
|
return $"GZ_{timestamp}{random}";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FinancialInvoiceItem : EntityBase
|
||||||
|
{
|
||||||
|
public string Description { get; private set; }
|
||||||
|
public double Amount { get; private set; }
|
||||||
|
public FinancialInvoiceItemType Type { get; set; }
|
||||||
|
public long EntityId { get; set; }
|
||||||
|
public FinancialInvoice FinancialInvoice { get; set; }
|
||||||
|
public long FinancialInvoiceId { get; set; }
|
||||||
|
public FinancialInvoiceItem(string description, double amount,
|
||||||
|
long financialInvoiceId, FinancialInvoiceItemType type, long entityId)
|
||||||
|
{
|
||||||
|
Description = description;
|
||||||
|
Amount = amount;
|
||||||
|
FinancialInvoiceId = financialInvoiceId;
|
||||||
|
Type = type;
|
||||||
|
EntityId = entityId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using _0_Framework.Domain;
|
||||||
|
using CompanyManagment.App.Contracts.FinancialInvoice;
|
||||||
|
|
||||||
|
namespace Company.Domain.FinancialInvoiceAgg;
|
||||||
|
|
||||||
|
public interface IFinancialInvoiceRepository : IRepository<long, FinancialInvoice>
|
||||||
|
{
|
||||||
|
EditFinancialInvoice GetDetails(long id);
|
||||||
|
List<FinancialInvoiceViewModel> Search(FinancialInvoiceSearchModel searchModel);
|
||||||
|
Task<FinancialInvoice> GetUnPaidByEntityId(long entityId, FinancialInvoiceItemType financialInvoiceItemType);
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using _0_Framework.Domain;
|
using _0_Framework.Domain;
|
||||||
|
using Company.Domain.FinancialInvoiceAgg;
|
||||||
using Company.Domain.FinancialTransactionAgg;
|
using Company.Domain.FinancialTransactionAgg;
|
||||||
|
|
||||||
namespace Company.Domain.FinancialStatmentAgg;
|
namespace Company.Domain.FinancialStatmentAgg;
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ public interface IFinancialStatmentRepository : IRepository<long, FinancialStatm
|
|||||||
Task<OperationResult<ClientFinancialStatementViewModel>> GetDetailsByPublicId(string publicId);
|
Task<OperationResult<ClientFinancialStatementViewModel>> GetDetailsByPublicId(string publicId);
|
||||||
Task<GetFinancialStatementBalanceAmount> GetBalanceAmount(long id);
|
Task<GetFinancialStatementBalanceAmount> GetBalanceAmount(long id);
|
||||||
Task<double> GetClientDebtAmount(long accountId);
|
Task<double> GetClientDebtAmount(long accountId);
|
||||||
Task<FinancialStatmentDetailsByContractingPartyViewModel> GetDetailsByContractingParty(long contractingPartyId,FinancialStatementSearchModel searchModel);
|
Task<double> GetClientDebtAmountByContractingPartyId(long contractingPartyId);
|
||||||
|
|
||||||
|
Task<FinancialStatmentDetailsByContractingPartyViewModel> GetDetailsByContractingParty(long contractingPartyId,FinancialStatementSearchModel searchModel);
|
||||||
Task<FinancialStatment> GetByContractingPartyId(long contractingPartyId);
|
Task<FinancialStatment> GetByContractingPartyId(long contractingPartyId);
|
||||||
}
|
}
|
||||||
@@ -26,6 +26,35 @@ public class FinancialTransaction : EntityBase
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ایجاد از طرف بک گراند سرویس
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="financialStatementId"></param>
|
||||||
|
/// <param name="tdateGr"></param>
|
||||||
|
/// <param name="tdateFa"></param>
|
||||||
|
/// <param name="description"></param>
|
||||||
|
/// <param name="typeOfTransaction"></param>
|
||||||
|
/// <param name="descriptionOption"></param>
|
||||||
|
/// <param name="deptor"></param>
|
||||||
|
/// <param name="creditor"></param>
|
||||||
|
/// <param name="balance"></param>
|
||||||
|
/// <param name="sentSms"></param>
|
||||||
|
public FinancialTransaction(long financialStatementId, DateTime tdateGr, string tdateFa, string description,
|
||||||
|
string typeOfTransaction, string descriptionOption, double deptor, double creditor, double balance,
|
||||||
|
bool sentSms)
|
||||||
|
{
|
||||||
|
FinancialStatementId = financialStatementId;
|
||||||
|
TdateGr = tdateGr;
|
||||||
|
TdateFa = tdateFa;
|
||||||
|
Description = description;
|
||||||
|
TypeOfTransaction = typeOfTransaction;
|
||||||
|
DescriptionOption = descriptionOption;
|
||||||
|
Deptor = deptor;
|
||||||
|
Creditor = creditor;
|
||||||
|
Balance = balance;
|
||||||
|
SentSms = sentSms;
|
||||||
|
}
|
||||||
|
|
||||||
public long FinancialStatementId { get; private set; }
|
public long FinancialStatementId { get; private set; }
|
||||||
public DateTime TdateGr { get; private set; }
|
public DateTime TdateGr { get; private set; }
|
||||||
public string TdateFa { get; private set; }
|
public string TdateFa { get; private set; }
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using _0_Framework.Application;
|
using _0_Framework.Application;
|
||||||
|
using _0_Framework.Application.Enums;
|
||||||
using _0_Framework.Domain;
|
using _0_Framework.Domain;
|
||||||
using CompanyManagment.App.Contracts.InstitutionContract;
|
using CompanyManagment.App.Contracts.InstitutionContract;
|
||||||
using CompanyManagment.App.Contracts.Workshop;
|
using CompanyManagment.App.Contracts.Workshop;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
namespace Company.Domain.InstitutionContractAgg;
|
namespace Company.Domain.InstitutionContractAgg;
|
||||||
|
|
||||||
@@ -43,7 +45,7 @@ public interface IInstitutionContractRepository : IRepository<long, InstitutionC
|
|||||||
/// <param name="endOfMonthGr"></param>
|
/// <param name="endOfMonthGr"></param>
|
||||||
/// <param name="endOfMonth"></param>
|
/// <param name="endOfMonth"></param>
|
||||||
/// <param name="description"></param>
|
/// <param name="description"></param>
|
||||||
void RollcallServiceCreateTransaction();
|
Task RollCallServiceCreateTransaction();
|
||||||
|
|
||||||
Task<PagedResult<GetInstitutionContractListItemsViewModel>> GetList(InstitutionContractListSearchModel searchModel);
|
Task<PagedResult<GetInstitutionContractListItemsViewModel>> GetList(InstitutionContractListSearchModel searchModel);
|
||||||
Task<GetInstitutionContractListStatsViewModel> GetListStats(InstitutionContractListSearchModel searchModel);
|
Task<GetInstitutionContractListStatsViewModel> GetListStats(InstitutionContractListSearchModel searchModel);
|
||||||
@@ -54,10 +56,102 @@ public interface IInstitutionContractRepository : IRepository<long, InstitutionC
|
|||||||
void UpdateStatusIfNeeded(long institutionContractId);
|
void UpdateStatusIfNeeded(long institutionContractId);
|
||||||
Task<GetInstitutionVerificationDetailsViewModel> GetVerificationDetails(Guid id);
|
Task<GetInstitutionVerificationDetailsViewModel> GetVerificationDetails(Guid id);
|
||||||
Task<InstitutionContract> GetByPublicIdAsync(Guid id);
|
Task<InstitutionContract> GetByPublicIdAsync(Guid id);
|
||||||
|
InstitutionContractDiscountResponse CalculateDiscount(InstitutionContractSetDiscountRequest request);
|
||||||
|
InstitutionContractDiscountResponse ResetDiscountCreate(InstitutionContractResetDiscountForCreateRequest request);
|
||||||
|
|
||||||
|
|
||||||
|
#region Extension
|
||||||
|
|
||||||
Task<InstitutionContractExtensionInquiryResult> GetExtensionInquiry(long previousContractId);
|
Task<InstitutionContractExtensionInquiryResult> GetExtensionInquiry(long previousContractId);
|
||||||
Task<InstitutionContractExtensionWorkshopsResponse> GetExtensionWorkshops(InstitutionContractExtensionWorkshopsRequest request);
|
Task<InstitutionContractExtensionWorkshopsResponse> GetExtensionWorkshops(InstitutionContractExtensionWorkshopsRequest request);
|
||||||
Task<InstitutionContractExtensionPlanResponse> GetExtensionInstitutionPlan(InstitutionContractExtensionPlanRequest request);
|
Task<InstitutionContractExtensionPlanResponse> GetExtensionInstitutionPlan(InstitutionContractExtensionPlanRequest request);
|
||||||
Task<InstitutionContractExtensionPaymentResponse> GetExtensionPaymentMethod(InstitutionContractExtensionPaymentRequest request);
|
Task<InstitutionContractExtensionPaymentResponse> GetExtensionPaymentMethod(InstitutionContractExtensionPaymentRequest request);
|
||||||
|
Task<InstitutionContractDiscountResponse> SetDiscountForExtension(
|
||||||
|
InstitutionContractSetDiscountForExtensionRequest request);
|
||||||
|
Task<InstitutionContractDiscountResponse> ResetDiscountForExtension(InstitutionContractResetDiscountForExtensionRequest request);
|
||||||
|
|
||||||
Task<OperationResult> ExtensionComplete(InstitutionContractExtensionCompleteRequest request);
|
Task<OperationResult> ExtensionComplete(InstitutionContractExtensionCompleteRequest request);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Upgrade(Amendment)
|
||||||
|
|
||||||
|
Task<InstitutionContractAmendmentWorkshopsResponse> GetAmendmentWorkshops(long institutionContractId);
|
||||||
|
Task<InsitutionContractAmendmentPaymentResponse> GetAmendmentPaymentDetails(InsitutionContractAmendmentPaymentRequest request);
|
||||||
|
|
||||||
|
Task<InsertAmendmentTempWorkshopResponse> InsertAmendmentTempWorkshops(InstitutionContractAmendmentTempWorkshopViewModel request);
|
||||||
|
Task RemoveAmendmentWorkshops(Guid workshopTempId);
|
||||||
|
#endregion
|
||||||
|
|
||||||
Task<List<InstitutionContractSelectListViewModel>> GetInstitutionContractSelectList(string search, string selected);
|
Task<List<InstitutionContractSelectListViewModel>> GetInstitutionContractSelectList(string search, string selected);
|
||||||
|
Task<List<InstitutionContractPrintViewModel>> PrintAllAsync(List<long> ids);
|
||||||
|
|
||||||
|
|
||||||
|
#region ReminderSMS
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت لیست - ارسال پیامک
|
||||||
|
/// فراخوانی از سمت بک گراند سرویس
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<bool> SendReminderSmsForBackgroundTask();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ارسال پیامک صورت حساب ماهانه
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="now"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task SendMonthlySms(DateTime now);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ارسال پیامک مسدودی از طرف بک گراند سرویس
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task SendBlockSmsForBackgroundTask();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت لیست واجد شرایط بلاک
|
||||||
|
/// جهت ارسال پیامک مسدودی
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="checkDate"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<List<BlockSmsListData>> GetBlockListData(DateTime checkDate);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ارسال پیامک مسدودی
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="smsListData"></param>
|
||||||
|
/// <param name="typeOfSms"></param>
|
||||||
|
/// <param name="sendMessStart"></param>
|
||||||
|
/// <param name="sendMessEnd"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task SendBlockSmsToContractingParties(List<BlockSmsListData> smsListData, string typeOfSms,
|
||||||
|
string sendMessStart, string sendMessEnd);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///دریافت لیست بدهکارن
|
||||||
|
/// جهت ارسال پیامک
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<List<SmsListData>> GetSmsListData(DateTime checkDate, TypeOfSmsSetting typeOfSmsSetting);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ارسال پیامک های یاد آور بدهی
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task SendReminderSmsToContractingParties(List<SmsListData> smsListData, string typeOfSms, string sendMessStart, string sendMessEnd);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region CreateMontlyTransaction
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ایجاد سند مالی برای قرارداد ها
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task CreateTransactionForInstitutionContracts(DateTime endOfMonthGr, string endOfMonthFa, string description);
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
Task<long> GetIdByInstallmentId(long installmentId);
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
using _0_Framework.Application.Enums;
|
||||||
using _0_Framework.Domain;
|
using _0_Framework.Domain;
|
||||||
using Company.Domain.InstitutionContractContactInfoAgg;
|
using Company.Domain.InstitutionContractContactInfoAgg;
|
||||||
using CompanyManagment.App.Contracts.InstitutionContract;
|
using CompanyManagment.App.Contracts.InstitutionContract;
|
||||||
@@ -17,7 +19,8 @@ public class InstitutionContract : EntityBase
|
|||||||
string contractEndFa, double contractAmount, double dailyCompenseation, double obligation,
|
string contractEndFa, double contractAmount, double dailyCompenseation, double obligation,
|
||||||
double totalAmount, int extensionNo, string workshopManualCount, string employeeManualCount, string description,
|
double totalAmount, int extensionNo, string workshopManualCount, string employeeManualCount, string description,
|
||||||
string officialCompany, string typeOfcontract, string hasValueAddedTax, double valueAddedTax,
|
string officialCompany, string typeOfcontract, string hasValueAddedTax, double valueAddedTax,
|
||||||
List<InstitutionContractWorkshopInitial> workshopDetails, long lawId)
|
List<InstitutionContractWorkshopInitial> workshopDetails, long lawId,
|
||||||
|
int discountPercentage, double discountAmount)
|
||||||
{
|
{
|
||||||
ContractNo = contractNo;
|
ContractNo = contractNo;
|
||||||
RepresentativeId = representativeId;
|
RepresentativeId = representativeId;
|
||||||
@@ -55,8 +58,12 @@ public class InstitutionContract : EntityBase
|
|||||||
WorkshopGroup = new InstitutionContractWorkshopGroup(id, workshopDetails);
|
WorkshopGroup = new InstitutionContractWorkshopGroup(id, workshopDetails);
|
||||||
PublicId = Guid.NewGuid();
|
PublicId = Guid.NewGuid();
|
||||||
LawId = lawId;
|
LawId = lawId;
|
||||||
|
DiscountPercentage = discountPercentage;
|
||||||
|
DiscountAmount = discountAmount;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public long LawId { get; private set; }
|
public long LawId { get; private set; }
|
||||||
|
|
||||||
public string ContractNo { get; private set; }
|
public string ContractNo { get; private set; }
|
||||||
@@ -119,26 +126,29 @@ public class InstitutionContract : EntityBase
|
|||||||
public string HasValueAddedTax { get; private set; }
|
public string HasValueAddedTax { get; private set; }
|
||||||
|
|
||||||
public double ValueAddedTax { get; private set; }
|
public double ValueAddedTax { get; private set; }
|
||||||
|
|
||||||
public Guid PublicId { get; private set; }
|
public Guid PublicId { get; private set; }
|
||||||
|
|
||||||
public string VerifyCode { get; private set; }
|
public string VerifyCode { get; private set; }
|
||||||
public DateTime VerifyCodeCreation { get; private set; }
|
public DateTime VerifyCodeCreation { get; private set; }
|
||||||
|
public string VerifierFullName { get; private set; }
|
||||||
|
public string VerifierPhoneNumber { get; private set; }
|
||||||
|
|
||||||
[NotMapped]
|
public double DiscountAmount { get; private set; }
|
||||||
public bool VerifyCodeExpired => VerifyCodeCreation.Add(ExpireTime) <= DateTime.Now;
|
|
||||||
|
public int DiscountPercentage { get; private set; }
|
||||||
|
|
||||||
|
[NotMapped] public bool VerifyCodeExpired => VerifyCodeCreation.Add(ExpireTime) <= DateTime.Now;
|
||||||
|
|
||||||
|
[NotMapped] public bool CanResendVerifyCode => VerifyCodeCreation.Add(ReSendTime) <= DateTime.Now;
|
||||||
|
|
||||||
[NotMapped]
|
|
||||||
public bool CanResendVerifyCode => VerifyCodeCreation.Add(ReSendTime) <= DateTime.Now;
|
|
||||||
|
|
||||||
[NotMapped] public TimeSpan ExpireTime => TimeSpan.FromMinutes(5);
|
[NotMapped] public TimeSpan ExpireTime => TimeSpan.FromMinutes(5);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[NotMapped] public TimeSpan ReSendTime => TimeSpan.FromMinutes(2);
|
[NotMapped] public TimeSpan ReSendTime => TimeSpan.FromMinutes(2);
|
||||||
|
|
||||||
public bool IsInstallment { get; set; }
|
public bool IsInstallment { get; set; }
|
||||||
|
|
||||||
public InstitutionContractVerificationStatus VerificationStatus { get; private set; }
|
public InstitutionContractVerificationStatus VerificationStatus { get; private set; }
|
||||||
|
|
||||||
public InstitutionContractWorkshopGroup WorkshopGroup { get; private set; }
|
public InstitutionContractWorkshopGroup WorkshopGroup { get; private set; }
|
||||||
@@ -227,10 +237,12 @@ public class InstitutionContract : EntityBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void SetVerifyCode(string code)
|
public void SetVerifyCode(string code,string verifierFullName, string verifierPhoneNumber)
|
||||||
{
|
{
|
||||||
VerifyCode = code;
|
VerifyCode = code;
|
||||||
VerifyCodeCreation = DateTime.Now;
|
VerifyCodeCreation = DateTime.Now;
|
||||||
|
VerifierFullName = verifierFullName;
|
||||||
|
VerifierPhoneNumber = verifierPhoneNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetWorkshopGroup(InstitutionContractWorkshopGroup workshopGroup)
|
public void SetWorkshopGroup(InstitutionContractWorkshopGroup workshopGroup)
|
||||||
@@ -254,6 +266,19 @@ public class InstitutionContract : EntityBase
|
|||||||
|
|
||||||
public class InstitutionContractAmendment : EntityBase
|
public class InstitutionContractAmendment : EntityBase
|
||||||
{
|
{
|
||||||
|
private InstitutionContractAmendment(){}
|
||||||
|
public InstitutionContractAmendment(long institutionContractId,
|
||||||
|
List<InstitutionContractInstallment> installments, double amount, bool hasInstallment,
|
||||||
|
InstitutionContractAmendmentChange amendmentChange, long lawId)
|
||||||
|
{
|
||||||
|
InstitutionContractId = institutionContractId;
|
||||||
|
Installments = installments is { Count: > 0} ? installments : [];
|
||||||
|
Amount = amount;
|
||||||
|
HasInstallment = hasInstallment;
|
||||||
|
AmendmentChanges = [amendmentChange];
|
||||||
|
LawId = lawId;
|
||||||
|
}
|
||||||
|
|
||||||
public long InstitutionContractId { get; set; }
|
public long InstitutionContractId { get; set; }
|
||||||
public InstitutionContract InstitutionContract { get; set; }
|
public InstitutionContract InstitutionContract { get; set; }
|
||||||
public List<InstitutionContractInstallment> Installments { get; set; }
|
public List<InstitutionContractInstallment> Installments { get; set; }
|
||||||
@@ -262,10 +287,47 @@ public class InstitutionContractAmendment : EntityBase
|
|||||||
public string VerifyCode { get; set; }
|
public string VerifyCode { get; set; }
|
||||||
public DateTime VerificationCreation { get; set; }
|
public DateTime VerificationCreation { get; set; }
|
||||||
public List<InstitutionContractAmendmentChange> AmendmentChanges { get; set; }
|
public List<InstitutionContractAmendmentChange> AmendmentChanges { get; set; }
|
||||||
|
|
||||||
|
public long LawId { get; set; }
|
||||||
|
|
||||||
|
public void SetVerifyCode(string code,string verifierFullName, string verifierPhoneNumber)
|
||||||
|
{
|
||||||
|
VerifyCode = code;
|
||||||
|
VerifyCodeCreation = DateTime.Now;
|
||||||
|
VerifierFullName = verifierFullName;
|
||||||
|
VerifierPhoneNumber = verifierPhoneNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string VerifierPhoneNumber { get; private set; }
|
||||||
|
|
||||||
|
public string VerifierFullName { get; private set; }
|
||||||
|
|
||||||
|
public DateTime VerifyCodeCreation { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InstitutionContractAmendmentChange : EntityBase
|
public class InstitutionContractAmendmentChange : EntityBase
|
||||||
{
|
{
|
||||||
|
private InstitutionContractAmendmentChange() { }
|
||||||
|
private InstitutionContractAmendmentChange(long institutionContractAmendmentId,
|
||||||
|
InstitutionContractAmendment institutionContractAmendment, InstitutionContractAmendmentChangeType changeType,
|
||||||
|
DateTime changeDateGr, bool? hasRollCallPlan, bool? hasCustomizeCheckoutPlan, bool? hasContractPlan,
|
||||||
|
bool? hasContractPlanInPerson, bool? hasInsurancePlan, bool? hasInsurancePlanInPerson, int? personnelCount,
|
||||||
|
long? workshopDetailsId)
|
||||||
|
{
|
||||||
|
InstitutionContractAmendmentId = institutionContractAmendmentId;
|
||||||
|
InstitutionContractAmendment = institutionContractAmendment;
|
||||||
|
ChangeType = changeType;
|
||||||
|
ChangeDateGr = changeDateGr;
|
||||||
|
HasRollCallPlan = hasRollCallPlan;
|
||||||
|
HasCustomizeCheckoutPlan = hasCustomizeCheckoutPlan;
|
||||||
|
HasContractPlan = hasContractPlan;
|
||||||
|
HasContractPlanInPerson = hasContractPlanInPerson;
|
||||||
|
HasInsurancePlan = hasInsurancePlan;
|
||||||
|
HasInsurancePlanInPerson = hasInsurancePlanInPerson;
|
||||||
|
PersonnelCount = personnelCount;
|
||||||
|
WorkshopDetailsId = workshopDetailsId;
|
||||||
|
}
|
||||||
|
|
||||||
public long InstitutionContractAmendmentId { get; private set; }
|
public long InstitutionContractAmendmentId { get; private set; }
|
||||||
public InstitutionContractAmendment InstitutionContractAmendment { get; private set; }
|
public InstitutionContractAmendment InstitutionContractAmendment { get; private set; }
|
||||||
public InstitutionContractAmendmentChangeType ChangeType { get; private set; }
|
public InstitutionContractAmendmentChangeType ChangeType { get; private set; }
|
||||||
@@ -310,8 +372,6 @@ public class InstitutionContractAmendmentChange : EntityBase
|
|||||||
/// تعداد کارگاه
|
/// تعداد کارگاه
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long? WorkshopDetailsId { get; private set; }
|
public long? WorkshopDetailsId { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum InstitutionContractAmendmentChangeType
|
public enum InstitutionContractAmendmentChangeType
|
||||||
@@ -321,20 +381,3 @@ public enum InstitutionContractAmendmentChangeType
|
|||||||
WorkshopCreated
|
WorkshopCreated
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum InstitutionContractVerificationStatus
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// در انتظار تایید
|
|
||||||
/// </summary>
|
|
||||||
PendingForVerify = 0,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// در انتظار کارپوشه
|
|
||||||
/// </summary>
|
|
||||||
PendingWorkflow = 1,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// تایید شده
|
|
||||||
/// </summary>
|
|
||||||
Verified = 2
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Company.Domain.InstitutionContractAmendmentTempAgg;
|
||||||
|
|
||||||
|
public class InstitutionContractAmendmentTemp
|
||||||
|
{
|
||||||
|
public InstitutionContractAmendmentTemp(List<InstitutionContractAmendmentTempPrevWorkshop> prevWorkshops,
|
||||||
|
long institutionContractId)
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid();
|
||||||
|
PrevWorkshops = prevWorkshops;
|
||||||
|
NewWorkshops = prevWorkshops.Select(x=> new InstitutionContractAmendmentTempNewWorkshop(
|
||||||
|
x.WorkshopName, x.CountPerson, x.ContractAndCheckout, x.ContractAndCheckoutInPerson, x.Insurance,
|
||||||
|
x.InsuranceInPerson, x.RollCall, x.RollCallInPerson, x.CustomizeCheckout, x.Price, x.WorkshopId,
|
||||||
|
x.CurrentWorkshopId, 0)).ToList();
|
||||||
|
InstitutionContractId = institutionContractId;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BsonId]
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public Guid Id { get; private set; }
|
||||||
|
public List<InstitutionContractAmendmentTempPrevWorkshop> PrevWorkshops { get; private set; }
|
||||||
|
public List<InstitutionContractAmendmentTempNewWorkshop> NewWorkshops { get; private set; }
|
||||||
|
public long InstitutionContractId { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InstitutionContractAmendmentTempNewWorkshop : InstitutionContractAmendmentTempPrevWorkshop
|
||||||
|
{
|
||||||
|
public InstitutionContractAmendmentTempNewWorkshop(string workshopName, int countPerson, bool contractAndCheckout,
|
||||||
|
bool contractAndCheckoutInPerson, bool insurance, bool insuranceInPerson, bool rollCall, bool rollCallInPerson,
|
||||||
|
bool customizeCheckout, double price, long workshopId, long currentWorkshopId,double priceDifference) : base(
|
||||||
|
workshopName, countPerson, contractAndCheckout, contractAndCheckoutInPerson, insurance, insuranceInPerson,
|
||||||
|
rollCall, rollCallInPerson, customizeCheckout, price, workshopId, currentWorkshopId)
|
||||||
|
{
|
||||||
|
PriceDifference = priceDifference;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// مبلغ اختلاف کارگاه جدید با کارگاه قبلی(مبلغ اصلی ارتقاء)
|
||||||
|
/// </summary>
|
||||||
|
public double PriceDifference { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
public void Edit(string workshopName, int countPerson, bool contractAndCheckout,
|
||||||
|
bool contractAndCheckoutInPerson,
|
||||||
|
bool insurance, bool insuranceInPerson, bool rollCall, bool customizeCheckout,
|
||||||
|
double price,double priceDifference)
|
||||||
|
{
|
||||||
|
base.Edit(workshopName, countPerson, contractAndCheckout, contractAndCheckoutInPerson, insurance,
|
||||||
|
insuranceInPerson, rollCall, customizeCheckout, price);
|
||||||
|
PriceDifference = priceDifference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InstitutionContractAmendmentTempPrevWorkshop
|
||||||
|
{
|
||||||
|
public InstitutionContractAmendmentTempPrevWorkshop(string workshopName, int countPerson, bool contractAndCheckout,
|
||||||
|
bool contractAndCheckoutInPerson,
|
||||||
|
bool insurance, bool insuranceInPerson,
|
||||||
|
bool rollCall, bool rollCallInPerson, bool customizeCheckout, double price, long workshopId,
|
||||||
|
long currentWorkshopId)
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid();
|
||||||
|
WorkshopName = workshopName;
|
||||||
|
CountPerson = countPerson;
|
||||||
|
ContractAndCheckout = contractAndCheckout;
|
||||||
|
Insurance = insurance;
|
||||||
|
RollCall = rollCall;
|
||||||
|
CustomizeCheckout = customizeCheckout;
|
||||||
|
ContractAndCheckoutInPerson = contractAndCheckoutInPerson;
|
||||||
|
InsuranceInPerson = insuranceInPerson;
|
||||||
|
RollCallInPerson = rollCallInPerson;
|
||||||
|
Price = price;
|
||||||
|
WorkshopId = workshopId;
|
||||||
|
CurrentWorkshopId = currentWorkshopId;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
|
||||||
|
public long CurrentWorkshopId { get; private set; }
|
||||||
|
public long WorkshopId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// نام کارگاه
|
||||||
|
/// </summary>
|
||||||
|
public string WorkshopName { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// تعداد پرسنل
|
||||||
|
/// </summary>
|
||||||
|
public int CountPerson { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
#region ServiceSelection
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// قرارداد و تصفیه
|
||||||
|
/// </summary>
|
||||||
|
public bool ContractAndCheckout { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// بیمه
|
||||||
|
/// </summary>
|
||||||
|
public bool Insurance { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// حضورغباب
|
||||||
|
/// </summary>
|
||||||
|
public bool RollCall { get; private set; }
|
||||||
|
|
||||||
|
public bool RollCallInPerson { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// فیش غیر رسمی
|
||||||
|
/// </summary>
|
||||||
|
public bool CustomizeCheckout { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// خدمات حضوری قرداد و تصفیه
|
||||||
|
/// </summary>
|
||||||
|
public bool ContractAndCheckoutInPerson { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// خدمات حضوری بیمه
|
||||||
|
/// </summary>
|
||||||
|
public bool InsuranceInPerson { get; private set; }
|
||||||
|
|
||||||
|
public double Price { get; private set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public void Edit(string workshopName, int countPerson, bool contractAndCheckout, bool contractAndCheckoutInPerson,
|
||||||
|
bool insurance, bool insuranceInPerson, bool rollCall, bool customizeCheckout,
|
||||||
|
double price)
|
||||||
|
{
|
||||||
|
WorkshopName = workshopName;
|
||||||
|
CountPerson = countPerson;
|
||||||
|
ContractAndCheckout = contractAndCheckout;
|
||||||
|
Insurance = insurance;
|
||||||
|
RollCall = rollCall;
|
||||||
|
CustomizeCheckout = customizeCheckout;
|
||||||
|
ContractAndCheckoutInPerson = contractAndCheckoutInPerson;
|
||||||
|
InsuranceInPerson = insuranceInPerson;
|
||||||
|
Price = price;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using _0_Framework.Application;
|
|
||||||
|
|
||||||
namespace Company.Domain.InstitutionContractInsertTempAgg;
|
namespace Company.Domain.InstitutionContractExtensionTempAgg;
|
||||||
|
|
||||||
public interface IInstitutionContractExtenstionTempRepository
|
public interface IInstitutionContractExtenstionTempRepository
|
||||||
{
|
{
|
||||||
@@ -5,7 +5,7 @@ using CompanyManagment.App.Contracts.InstitutionContractContactinfo;
|
|||||||
using MongoDB.Bson;
|
using MongoDB.Bson;
|
||||||
using MongoDB.Bson.Serialization.Attributes;
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
namespace Company.Domain.InstitutionContractInsertTempAgg;
|
namespace Company.Domain.InstitutionContractExtensionTempAgg;
|
||||||
|
|
||||||
public class InstitutionContractExtensionTemp
|
public class InstitutionContractExtensionTemp
|
||||||
{
|
{
|
||||||
@@ -30,8 +30,8 @@ public class InstitutionContractExtensionTemp
|
|||||||
public InstitutionContractExtensionPlanDetail ThreeMonths { get; set; }
|
public InstitutionContractExtensionPlanDetail ThreeMonths { get; set; }
|
||||||
public InstitutionContractExtensionPlanDetail SixMonths { get; set; }
|
public InstitutionContractExtensionPlanDetail SixMonths { get; set; }
|
||||||
public InstitutionContractExtensionPlanDetail TwelveMonths { get; set; }
|
public InstitutionContractExtensionPlanDetail TwelveMonths { get; set; }
|
||||||
public InstitutionContractExtensionPaymentMonthly MonthlyPayment { get; set; }
|
public InstitutionContractPaymentMonthlyViewModel MonthlyPayment { get; set; }
|
||||||
public InstitutionContractExtensionPaymentOneTime OneTimePayment { get; set; }
|
public InstitutionContractPaymentOneTimeViewModel OneTimePayment { get; set; }
|
||||||
|
|
||||||
public bool HasContractInPerson { get; set; }
|
public bool HasContractInPerson { get; set; }
|
||||||
|
|
||||||
@@ -58,13 +58,14 @@ public class InstitutionContractExtensionTemp
|
|||||||
HasContractInPerson = hasContractInPerson;
|
HasContractInPerson = hasContractInPerson;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAmountAndDuration(InstitutionContractDuration duration,InstitutionContractExtensionPaymentMonthly monthly,
|
public void SetAmountAndDuration(InstitutionContractDuration duration,InstitutionContractPaymentMonthlyViewModel monthly,
|
||||||
InstitutionContractExtensionPaymentOneTime oneTime)
|
InstitutionContractPaymentOneTimeViewModel oneTime)
|
||||||
{
|
{
|
||||||
Duration = duration;
|
Duration = duration;
|
||||||
MonthlyPayment = monthly;
|
MonthlyPayment = monthly;
|
||||||
OneTimePayment = oneTime;
|
OneTimePayment = oneTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,6 +51,14 @@ public interface IInsuranceListRepository:IRepository<long, InsuranceList>
|
|||||||
List<EmployeeInsurancListDataViewModel> GetEmployeeInsuranceDataAmonthAgo(DateTime currentMonthStartDate, long workshopId);
|
List<EmployeeInsurancListDataViewModel> GetEmployeeInsuranceDataAmonthAgo(DateTime currentMonthStartDate, long workshopId);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت اطلاعات بیمه کارکنان برای استفاده در فیش حقوقی
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="startDate"></param>
|
||||||
|
/// <param name="workshopId"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
List<EmployeeInsurancListDataViewModel> EmployeeInsuranceDataBy(DateTime startDate, long workshopId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// بدست آوردن اطلاعات محاسباتی ماه پرسنل برای ویرایش
|
/// بدست آوردن اطلاعات محاسباتی ماه پرسنل برای ویرایش
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using _0_Framework.Domain;
|
using _0_Framework.Domain;
|
||||||
|
using Company.Domain.FinancialInvoiceAgg;
|
||||||
using CompanyManagment.App.Contracts.PaymentTransaction;
|
using CompanyManagment.App.Contracts.PaymentTransaction;
|
||||||
|
|
||||||
namespace Company.Domain.PaymentTransactionAgg;
|
namespace Company.Domain.PaymentTransactionAgg;
|
||||||
@@ -9,22 +10,25 @@ namespace Company.Domain.PaymentTransactionAgg;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class PaymentTransaction:EntityBase
|
public class PaymentTransaction:EntityBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// سازنده کلاس PaymentTransaction با دریافت اطلاعات تراکنش.
|
/// سازنده کلاس PaymentTransaction با دریافت اطلاعات تراکنش.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="contractingPartyId">شناسه طرف قرارداد</param>
|
/// <param name="contractingPartyId">شناسه طرف قرارداد</param>
|
||||||
/// <param name="amount">مبلغ تراکنش</param>
|
/// <param name="amount">مبلغ تراکنش</param>
|
||||||
/// <param name="contractingPartyName"></param>
|
/// <param name="contractingPartyName"></param>
|
||||||
/// <param name="callBackUrl"></param>
|
/// <param name="callBackUrl"></param>
|
||||||
public PaymentTransaction(long contractingPartyId,
|
/// <param name="gateway"></param>
|
||||||
|
public PaymentTransaction(long contractingPartyId,
|
||||||
double amount,
|
double amount,
|
||||||
string contractingPartyName,string callBackUrl)
|
string contractingPartyName,string callBackUrl,
|
||||||
|
PaymentTransactionGateWay gateway)
|
||||||
{
|
{
|
||||||
ContractingPartyId = contractingPartyId;
|
ContractingPartyId = contractingPartyId;
|
||||||
Status = PaymentTransactionStatus.Pending;
|
Status = PaymentTransactionStatus.Pending;
|
||||||
Amount = amount;
|
Amount = amount;
|
||||||
ContractingPartyName = contractingPartyName;
|
ContractingPartyName = contractingPartyName;
|
||||||
CallBackUrl = callBackUrl;
|
CallBackUrl = callBackUrl;
|
||||||
|
Gateway = gateway;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -68,13 +72,23 @@ public class PaymentTransaction:EntityBase
|
|||||||
public string TransactionId { get; private set; }
|
public string TransactionId { get; private set; }
|
||||||
|
|
||||||
public string CallBackUrl { get; private set; }
|
public string CallBackUrl { get; private set; }
|
||||||
|
public PaymentTransactionGateWay Gateway { get; private set; }
|
||||||
|
public string Rrn { get; private set; }
|
||||||
|
public string DigitalReceipt { get; private set; }
|
||||||
|
|
||||||
public void SetPaid(string cardNumber,string bankName)
|
public FinancialInvoice FinancialInvoice { get; set; }
|
||||||
|
public long? FinancialInvoiceId { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public void SetPaid(string cardNumber,string bankName,string rrn,string digitalReceipt)
|
||||||
{
|
{
|
||||||
Status = PaymentTransactionStatus.Success;
|
Status = PaymentTransactionStatus.Success;
|
||||||
TransactionDate = DateTime.Now;
|
TransactionDate = DateTime.Now;
|
||||||
CardNumber = cardNumber;
|
CardNumber = cardNumber;
|
||||||
BankName = bankName;
|
BankName = bankName;
|
||||||
|
Rrn = rrn;
|
||||||
|
DigitalReceipt = digitalReceipt;
|
||||||
|
|
||||||
}
|
}
|
||||||
public void SetFailed()
|
public void SetFailed()
|
||||||
{
|
{
|
||||||
@@ -85,4 +99,5 @@ public class PaymentTransaction:EntityBase
|
|||||||
{
|
{
|
||||||
TransactionId = transactionId;
|
TransactionId = transactionId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,21 +11,23 @@ namespace Company.Domain.ReportAgg
|
|||||||
{
|
{
|
||||||
Task<AllReport> GetAllActiveWorkshopsNew(string year, string month);
|
Task<AllReport> GetAllActiveWorkshopsNew(string year, string month);
|
||||||
AllReport GetAllActiveWorkshops(string year, string month);
|
AllReport GetAllActiveWorkshops(string year, string month);
|
||||||
WorkshopResult GetWorkshopContractDone(string year, string month, long accountId, List<long> workshopList);
|
Task<WorkshopResult> GetWorkshopContractDone(string year, string month, long accountId, List<long> workshopList);
|
||||||
WorkshopResult GetWorkshopContractSignDone(string year, string month, long accountId, List<long> workshopList);
|
Task<WorkshopResult> GetWorkshopContractSignDone(string year, string month, long accountId,
|
||||||
WorkshopResult GetWorkshopCheckoutDone(string year, string month, long accountId, List<long> workshopList);
|
|
||||||
WorkshopResult GetWorkshopCheckoutSignDone(string year, string month, long accountId, List<long> workshopList);
|
|
||||||
List<EmployeeNotDone> GetEmployeeContract(string year, string month, long workshopId);
|
|
||||||
List<EmployeeNotDone> GetEmployeeContractSign(string year, string month, long workshopId);
|
|
||||||
List<EmployeeNotDone> GetEmployeeCheckout(string year, string month, long workshopId);
|
|
||||||
List<EmployeeNotDone> GetEmployeeCheckoutSign(string year, string month, long workshopId);
|
|
||||||
PrintAllContractCheckout GetPrintAllContractDone(string year, string month, long accountId,
|
|
||||||
List<long> workshopList);
|
List<long> workshopList);
|
||||||
PrintAllContractCheckout GetPrintAllContractSignDone(string year, string month, long accountId,
|
Task<WorkshopResult> GetWorkshopCheckoutDone(string year, string month, long accountId, List<long> workshopList);
|
||||||
|
Task<WorkshopResult> GetWorkshopCheckoutSignDone(string year, string month, long accountId,
|
||||||
List<long> workshopList);
|
List<long> workshopList);
|
||||||
PrintAllContractCheckout GetPrintAllCheckoutDone(string year, string month, long accountId,
|
Task<List<EmployeeNotDone>> GetEmployeeContract(string year, string month, long workshopId);
|
||||||
|
Task<List<EmployeeNotDone>> GetEmployeeContractSign(string year, string month, long workshopId);
|
||||||
|
Task<List<EmployeeNotDone>> GetEmployeeCheckout(string year, string month, long workshopId);
|
||||||
|
Task<List<EmployeeNotDone>> GetEmployeeCheckoutSign(string year, string month, long workshopId);
|
||||||
|
Task<PrintAllContractCheckout> GetPrintAllContractDone(string year, string month, long accountId,
|
||||||
List<long> workshopList);
|
List<long> workshopList);
|
||||||
PrintAllContractCheckout GetPrintAllCheckoutSignDone(string year, string month, long accountId,
|
Task<PrintAllContractCheckout> GetPrintAllContractSignDone(string year, string month, long accountId,
|
||||||
|
List<long> workshopList);
|
||||||
|
Task<PrintAllContractCheckout> GetPrintAllCheckoutDone(string year, string month, long accountId,
|
||||||
|
List<long> workshopList);
|
||||||
|
Task<PrintAllContractCheckout> GetPrintAllCheckoutSignDone(string year, string month, long accountId,
|
||||||
List<long> workshopList);
|
List<long> workshopList);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -26,5 +26,6 @@ namespace Company.Domain.RollCallEmployeeStatusAgg
|
|||||||
List<RollCallEmployeeStatusViewModel> GetActiveByWorkshopIdInDate(long workshopId, DateTime startDateGr, DateTime endDateGr);
|
List<RollCallEmployeeStatusViewModel> GetActiveByWorkshopIdInDate(long workshopId, DateTime startDateGr, DateTime endDateGr);
|
||||||
List<RollCallEmployeeStatusViewModel> GetByWorkshopIdInDates(long workshopId, DateTime start, DateTime end);
|
List<RollCallEmployeeStatusViewModel> GetByWorkshopIdInDates(long workshopId, DateTime start, DateTime end);
|
||||||
bool IsActiveInPeriod(long employeeId, long workshopId, DateTime startDate, DateTime endDate);
|
bool IsActiveInPeriod(long employeeId, long workshopId, DateTime startDate, DateTime endDate);
|
||||||
}
|
void RemoveRange(IEnumerable<RollCallEmployeeStatus> rollCallEmployeeStatusList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
30
Company.Domain/SmsResultAgg/ISmsSettingsRepository.cs
Normal file
30
Company.Domain/SmsResultAgg/ISmsSettingsRepository.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using _0_Framework.Application.Enums;
|
||||||
|
using _0_Framework.Domain;
|
||||||
|
using CompanyManagment.App.Contracts.SmsResult;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Company.Domain.SmsResultAgg;
|
||||||
|
|
||||||
|
public interface ISmsSettingsRepository : IRepository<long, SmsSetting>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ویرایش پیامک خودکار
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<EditSmsSetting> GetSmsSettingToEdit(long id);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت لیست پیامک های خودکار بر اساس نوع آن
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="typeOfSmsSetting"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<SmsSettingViewModel> GetSmsSettingsByType(TypeOfSmsSetting typeOfSmsSetting);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// حذف از دیتابیس
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task RemoveItem(long id);
|
||||||
|
}
|
||||||
@@ -5,7 +5,8 @@ namespace Company.Domain.SmsResultAgg;
|
|||||||
|
|
||||||
public class SmsResult: EntityBase
|
public class SmsResult: EntityBase
|
||||||
{
|
{
|
||||||
public SmsResult(int messageId, string status,string typeOfSms, string contractingPartyName,string mobile, long contractingPatyId, long institutionContractId)
|
public SmsResult(int messageId, string status,string typeOfSms,
|
||||||
|
string contractingPartyName,string mobile, long contractingPatyId, long institutionContractId)
|
||||||
{
|
{
|
||||||
MessageId = messageId;
|
MessageId = messageId;
|
||||||
Status = status;
|
Status = status;
|
||||||
|
|||||||
72
Company.Domain/SmsResultAgg/SmsSetting.cs
Normal file
72
Company.Domain/SmsResultAgg/SmsSetting.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
using _0_Framework.Application.Enums;
|
||||||
|
using _0_Framework.Domain;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Company.Domain.SmsResultAgg;
|
||||||
|
|
||||||
|
public class SmsSetting : EntityBaseWithoutCreationDate
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// ایجاد تنظیمات پیامک
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="typeOfSmsSetting"></param>
|
||||||
|
/// <param name="dayOfMonth"></param>
|
||||||
|
/// <param name="timeOfDay"></param>
|
||||||
|
public SmsSetting(TypeOfSmsSetting typeOfSmsSetting, int dayOfMonth, TimeSpan timeOfDay)
|
||||||
|
{
|
||||||
|
TypeOfSmsSetting = typeOfSmsSetting;
|
||||||
|
DayOfMonth = dayOfMonth;
|
||||||
|
TimeOfDay = timeOfDay;
|
||||||
|
IsActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// نوع پیامک
|
||||||
|
/// </summary>
|
||||||
|
public TypeOfSmsSetting TypeOfSmsSetting { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// عدد روز از ماه
|
||||||
|
/// </summary>
|
||||||
|
public int DayOfMonth { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ساعت
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan TimeOfDay { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// فعال/غیرفعال
|
||||||
|
/// </summary>
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ویرایش تنظیمات پیامک
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dayOfMonth"></param>
|
||||||
|
/// <param name="timeOfDay"></param>
|
||||||
|
public void Edit(int dayOfMonth, TimeSpan timeOfDay)
|
||||||
|
{
|
||||||
|
DayOfMonth = dayOfMonth;
|
||||||
|
TimeOfDay = timeOfDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// فعال نمودن
|
||||||
|
/// </summary>
|
||||||
|
public void Active()
|
||||||
|
{
|
||||||
|
IsActive = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// غیر فعال نمودن
|
||||||
|
/// </summary>
|
||||||
|
public void DeActive()
|
||||||
|
{
|
||||||
|
IsActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -12,9 +12,7 @@ public class CaseHistoryRollCallExcelForEmployeeViewModel
|
|||||||
public string EmployeeFullName { get; set; }
|
public string EmployeeFullName { get; set; }
|
||||||
public string TotalWorkingHoursFa { get; set; }
|
public string TotalWorkingHoursFa { get; set; }
|
||||||
public string TotalWorkingTimeSpan { get; set; }
|
public string TotalWorkingTimeSpan { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public List<RollCallItemForEmployeeExcelViewModel> RollCalls { get; set; }
|
public List<RollCallItemForEmployeeExcelViewModel> RollCalls { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,7 +38,8 @@ public class RollCallItemForEmployeeExcelViewModel
|
|||||||
public bool HasLeave { get; set; }
|
public bool HasLeave { get; set; }
|
||||||
|
|
||||||
public string TotalWorkingHours { get; set; }
|
public string TotalWorkingHours { get; set; }
|
||||||
|
public string EnterTimeDifferences { get; set; }
|
||||||
|
public string ExitTimeDifferences { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RollCallTimeExcelViewModel
|
public class RollCallTimeExcelViewModel
|
||||||
|
|||||||
@@ -113,11 +113,12 @@ public class RollCallExcelGenerator : ExcelGenerator
|
|||||||
worksheet.Cells[i + row + 1, 1].Value = i + 1;
|
worksheet.Cells[i + row + 1, 1].Value = i + 1;
|
||||||
worksheet.Cells[i + row + 1, 2].Value = rollCall.DayOfWeekFa;
|
worksheet.Cells[i + row + 1, 2].Value = rollCall.DayOfWeekFa;
|
||||||
worksheet.Cells[i + row + 1, 3].Value = rollCall.DateFa;
|
worksheet.Cells[i + row + 1, 3].Value = rollCall.DateFa;
|
||||||
worksheet.Cells[i + row + 1, 4].Value = "-";
|
worksheet.Cells[i + row + 1, 4].Value = rollCall.EnterTimeDifferences;
|
||||||
worksheet.Cells[i + row + 1, 5].Value = rollCall.StartsItems;
|
worksheet.Cells[i + row + 1, 5].Value = rollCall.StartsItems;
|
||||||
worksheet.Cells[i + row + 1, 6].Value = rollCall.EndsItems;
|
worksheet.Cells[i + row + 1, 6].Value = rollCall.EndsItems;
|
||||||
worksheet.Cells[i + row + 1, 7].Value = "-";
|
worksheet.Cells[i + row + 1, 7].Value = rollCall.ExitTimeDifferences;
|
||||||
worksheet.Cells[i + row + 1, 8].Value = rollCall.TotalWorkingHours == string.Empty ? "ندارد" : rollCall.TotalWorkingHours;
|
worksheet.Cells[i + row + 1, 8].Value = rollCall.TotalWorkingHours == string.Empty
|
||||||
|
? "ندارد" : rollCall.TotalWorkingHours;
|
||||||
|
|
||||||
// Style data cells
|
// Style data cells
|
||||||
for (int j = 1; j <= 8; j++)
|
for (int j = 1; j <= 8; j++)
|
||||||
@@ -307,6 +308,49 @@ public class RollCallExcelGenerator : ExcelGenerator
|
|||||||
return package.GetAsByteArray();
|
return package.GetAsByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string CalculateExitMinuteDifference(TimeSpan early, TimeSpan late)
|
||||||
|
{
|
||||||
|
if (early == TimeSpan.Zero && late == TimeSpan.Zero)
|
||||||
|
{
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
else if (late != TimeSpan.Zero)
|
||||||
|
{
|
||||||
|
var minutes = late.TotalMinutes > 999 ? "999" : late.TotalMinutes.ToString();
|
||||||
|
return $"{minutes}+";
|
||||||
|
}
|
||||||
|
else if (early != TimeSpan.Zero)
|
||||||
|
{
|
||||||
|
var minutes = early.TotalMinutes > 999 ? "999" : early.TotalMinutes.ToString();
|
||||||
|
return $"{minutes}-";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return $"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string CalculateEntryMinuteDifference(TimeSpan early, TimeSpan late)
|
||||||
|
{
|
||||||
|
if (early == TimeSpan.Zero && late == TimeSpan.Zero)
|
||||||
|
{
|
||||||
|
return "-";
|
||||||
|
}
|
||||||
|
else if (late != TimeSpan.Zero)
|
||||||
|
{
|
||||||
|
var minutes = late.TotalMinutes > 999 ? "999" : late.TotalMinutes.ToString();
|
||||||
|
return $"{minutes}-";
|
||||||
|
}
|
||||||
|
else if (early != TimeSpan.Zero)
|
||||||
|
{
|
||||||
|
var minutes = early.TotalMinutes > 999 ? "999" : early.TotalMinutes.ToString();
|
||||||
|
return $"{minutes}+";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return $"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using System.Drawing;
|
||||||
|
using CompanyManagment.App.Contracts.Workshop;
|
||||||
|
using OfficeOpenXml;
|
||||||
|
using OfficeOpenXml.Style;
|
||||||
|
|
||||||
|
namespace CompanyManagement.Infrastructure.Excel.WorkshopsRollCall;
|
||||||
|
|
||||||
|
public class WorkshopRollCallExcelExporter
|
||||||
|
{
|
||||||
|
public static byte[] Export(List<WorkshopRollCallExcelViewModel> workshops)
|
||||||
|
{
|
||||||
|
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
|
||||||
|
using (var package = new ExcelPackage())
|
||||||
|
{
|
||||||
|
var ws = package.Workbook.Worksheets.Add("Workshops");
|
||||||
|
// Header
|
||||||
|
ws.Cells[1, 1].Value = "نام کارگاه";
|
||||||
|
ws.Cells[1, 2].Value = "فعال/غیرفعال";
|
||||||
|
ws.Cells[1, 3].Value = "تعداد پرسنل";
|
||||||
|
ws.Cells[1, 4].Value = "نام کارفرما";
|
||||||
|
ws.Row(1).Style.Font.Bold = true;
|
||||||
|
ws.Row(1).Style.Fill.PatternType = ExcelFillStyle.Solid;
|
||||||
|
ws.Row(1).Style.Fill.BackgroundColor.SetColor(Color.LightGray);
|
||||||
|
|
||||||
|
int row = 2;
|
||||||
|
foreach (var w in workshops)
|
||||||
|
{
|
||||||
|
ws.Cells[row, 1].Value = w.WorkshopName;
|
||||||
|
ws.Cells[row, 2].Value = w.IsActive ? "فعال" : "غیرفعال";
|
||||||
|
ws.Cells[row, 3].Value = w.PersonnelCount;
|
||||||
|
ws.Cells[row, 4].Value = w.EmployerName;
|
||||||
|
if (!w.IsActive)
|
||||||
|
{
|
||||||
|
using (var range = ws.Cells[row, 1, row, 4])
|
||||||
|
{
|
||||||
|
range.Style.Fill.PatternType = ExcelFillStyle.Solid;
|
||||||
|
range.Style.Fill.BackgroundColor.SetColor(Color.LightGray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
row++;
|
||||||
|
}
|
||||||
|
ws.Cells[ws.Dimension.Address].AutoFitColumns();
|
||||||
|
return package.GetAsByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
namespace CompanyManagement.Infrastructure.Excel.WorkshopsRollCall
|
||||||
|
{
|
||||||
|
public class WorkshopRollCallExcelViewModel
|
||||||
|
{
|
||||||
|
public string WorkshopName { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
public int PersonnelCount { get; set; }
|
||||||
|
public string EmployerName { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Company.Domain.CameraBugReportAgg;
|
||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
|
||||||
|
namespace CompanyManagement.Infrastructure.Mongo.CameraBugReportRepo;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// پیادهسازی انبار گزارش خرابی دوربین برای MongoDB
|
||||||
|
/// </summary>
|
||||||
|
public class CameraBugReportRepository : ICameraBugReportRepository
|
||||||
|
{
|
||||||
|
private readonly IMongoCollection<CameraBugReport> _cameraBugReports;
|
||||||
|
|
||||||
|
public CameraBugReportRepository(IMongoDatabase database)
|
||||||
|
{
|
||||||
|
_cameraBugReports = database.GetCollection<CameraBugReport>("CameraBugReports");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task CreateAsync(CameraBugReport bugReport)
|
||||||
|
{
|
||||||
|
await _cameraBugReports.InsertOneAsync(bugReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateAsync(CameraBugReport bugReport)
|
||||||
|
{
|
||||||
|
await _cameraBugReports.ReplaceOneAsync(
|
||||||
|
x => x.Id == bugReport.Id,
|
||||||
|
bugReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<CameraBugReport> GetByIdAsync(Guid id)
|
||||||
|
{
|
||||||
|
return await _cameraBugReports
|
||||||
|
.Find(x => x.Id == id)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<CameraBugReport>> GetAllAsync()
|
||||||
|
{
|
||||||
|
return await _cameraBugReports
|
||||||
|
.Find(_ => true)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<CameraBugReport>> GetAllAsync(int skip, int take)
|
||||||
|
{
|
||||||
|
return await _cameraBugReports
|
||||||
|
.Find(_ => true)
|
||||||
|
.Skip(skip)
|
||||||
|
.Limit(take)
|
||||||
|
.SortByDescending(x => x.CreationDate)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteAsync(Guid id)
|
||||||
|
{
|
||||||
|
await _cameraBugReports.DeleteOneAsync(x => x.Id == id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> IsExistAsync(Guid id)
|
||||||
|
{
|
||||||
|
var result = await _cameraBugReports
|
||||||
|
.Find(x => x.Id == id)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
return result != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<CameraBugReport>> FilterAsync(
|
||||||
|
CameraBugReportType? type = null,
|
||||||
|
CameraBugPriority? priority = null,
|
||||||
|
CameraBugReportStatus? status = null,
|
||||||
|
string searchTerm = null,
|
||||||
|
int skip = 0,
|
||||||
|
int take = 10)
|
||||||
|
{
|
||||||
|
var filterDefinition = BuildFilterDefinition(type, priority, status, searchTerm);
|
||||||
|
|
||||||
|
return await _cameraBugReports
|
||||||
|
.Find(filterDefinition)
|
||||||
|
.Skip(skip)
|
||||||
|
.Limit(take)
|
||||||
|
.SortByDescending(x => x.CreationDate)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int> CountAsync(
|
||||||
|
CameraBugReportType? type = null,
|
||||||
|
CameraBugPriority? priority = null,
|
||||||
|
CameraBugReportStatus? status = null,
|
||||||
|
string searchTerm = null)
|
||||||
|
{
|
||||||
|
var filterDefinition = BuildFilterDefinition(type, priority, status, searchTerm);
|
||||||
|
var count = await _cameraBugReports.CountDocumentsAsync(filterDefinition);
|
||||||
|
return (int)count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FilterDefinition<CameraBugReport> BuildFilterDefinition(
|
||||||
|
CameraBugReportType? type = null,
|
||||||
|
CameraBugPriority? priority = null,
|
||||||
|
CameraBugReportStatus? status = null,
|
||||||
|
string searchTerm = null)
|
||||||
|
{
|
||||||
|
var filters = new List<FilterDefinition<CameraBugReport>>();
|
||||||
|
|
||||||
|
if (type.HasValue)
|
||||||
|
filters.Add(Builders<CameraBugReport>.Filter.Eq(x => x.Type, type.Value));
|
||||||
|
|
||||||
|
if (priority.HasValue)
|
||||||
|
filters.Add(Builders<CameraBugReport>.Filter.Eq(x => x.Priority, priority.Value));
|
||||||
|
|
||||||
|
if (status.HasValue)
|
||||||
|
filters.Add(Builders<CameraBugReport>.Filter.Eq(x => x.Status, status.Value));
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(searchTerm))
|
||||||
|
{
|
||||||
|
var searchFilter = Builders<CameraBugReport>.Filter.Or(
|
||||||
|
Builders<CameraBugReport>.Filter.Regex(x => x.Title, new BsonRegularExpression(searchTerm, "i")),
|
||||||
|
Builders<CameraBugReport>.Filter.Regex(x => x.Description, new BsonRegularExpression(searchTerm, "i")),
|
||||||
|
Builders<CameraBugReport>.Filter.Regex(x => x.UserEmail, new BsonRegularExpression(searchTerm, "i"))
|
||||||
|
);
|
||||||
|
filters.Add(searchFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filters.Count == 0)
|
||||||
|
return Builders<CameraBugReport>.Filter.Empty;
|
||||||
|
|
||||||
|
return Builders<CameraBugReport>.Filter.And(filters);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync methods from IRepository interface (not used in MongoDB flow but required for interface implementation)
|
||||||
|
public CameraBugReport Get(long id)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("استفاده از GetByIdAsync برای MongoDB");
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<CameraBugReport> Get()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("استفاده از GetAllAsync برای MongoDB");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Create(CameraBugReport entity)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("استفاده از CreateAsync برای MongoDB");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ExistsIgnoreQueryFilter(System.Linq.Expressions.Expression<Func<CameraBugReport, bool>> expression)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("استفاده از IsExistAsync برای MongoDB");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Exists(System.Linq.Expressions.Expression<Func<CameraBugReport, bool>> expression)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("استفاده از FilterAsync برای MongoDB");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SaveChanges()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("MongoDB نیازی به SaveChanges ندارد");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SaveChangesAsync()
|
||||||
|
{
|
||||||
|
// MongoDB خودکار ذخیره میکند، بنابراین این متد خالی است
|
||||||
|
await Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction> BeginTransactionAsync()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("MongoDB اعاملات را بصورت متفاوت مدیریت میکند");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using Company.Domain.EmployeeFaceEmbeddingAgg;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
|
||||||
|
namespace CompanyManagement.Infrastructure.Mongo.EmployeeFaceEmbeddingRepo;
|
||||||
|
|
||||||
|
public class EmployeeFaceEmbeddingRepository : IEmployeeFaceEmbeddingRepository
|
||||||
|
{
|
||||||
|
private readonly IMongoCollection<EmployeeFaceEmbedding> _employeeFaceEmbeddings;
|
||||||
|
|
||||||
|
public EmployeeFaceEmbeddingRepository(IMongoDatabase database)
|
||||||
|
{
|
||||||
|
_employeeFaceEmbeddings = database.GetCollection<EmployeeFaceEmbedding>("EmployeeFaces");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task CreateAsync(EmployeeFaceEmbedding employeeFaceEmbedding)
|
||||||
|
{
|
||||||
|
await _employeeFaceEmbeddings.InsertOneAsync(employeeFaceEmbedding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpdateAsync(EmployeeFaceEmbedding employeeFaceEmbedding)
|
||||||
|
{
|
||||||
|
await _employeeFaceEmbeddings.ReplaceOneAsync(
|
||||||
|
x => x.Id == employeeFaceEmbedding.Id,
|
||||||
|
employeeFaceEmbedding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EmployeeFaceEmbedding> GetByIdAsync(string id)
|
||||||
|
{
|
||||||
|
return await _employeeFaceEmbeddings
|
||||||
|
.Find(x => x.Id == id)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<EmployeeFaceEmbedding> GetByEmployeeIdAsync(long employeeId)
|
||||||
|
{
|
||||||
|
return await _employeeFaceEmbeddings
|
||||||
|
.Find(x => x.EmployeeId == employeeId)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<EmployeeFaceEmbedding>> GetByWorkshopIdAsync(long workshopId)
|
||||||
|
{
|
||||||
|
return await _employeeFaceEmbeddings
|
||||||
|
.Find(x => x.WorkshopId == workshopId)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<EmployeeFaceEmbedding>> GetByWorkshopIdsAsync(List<long> workshopIds)
|
||||||
|
{
|
||||||
|
return await _employeeFaceEmbeddings
|
||||||
|
.Find(x => workshopIds.First()==x.WorkshopId)
|
||||||
|
.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteAsync(string id)
|
||||||
|
{
|
||||||
|
await _employeeFaceEmbeddings.DeleteOneAsync(x => x.Id == id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using Company.Domain.InstitutionContractInsertTempAgg;
|
using Company.Domain.InstitutionContractExtensionTempAgg;
|
||||||
using MongoDB.Driver;
|
using MongoDB.Driver;
|
||||||
|
|
||||||
namespace CompanyManagement.Infrastructure.Mongo.InstitutionContractInsertTempRepo;
|
namespace CompanyManagement.Infrastructure.Mongo.InstitutionContractInsertTempRepo;
|
||||||
|
|||||||
@@ -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;
|
namespace CompanyManagment.App.Contracts.AndroidApkVersion;
|
||||||
|
|
||||||
|
public record AndroidApkVersionInfo(int LatestVersionCode, string LatestVersionName, bool ShouldUpdate, bool IsForceUpdate, string DownloadUrl, string ReleaseNotes);
|
||||||
|
|
||||||
public interface IAndroidApkVersionApplication
|
public interface IAndroidApkVersionApplication
|
||||||
{
|
{
|
||||||
Task<OperationResult> CreateAndActive(IFormFile file);
|
Task<OperationResult> CreateAndActive(IFormFile file, ApkType apkType, string versionName, string versionCode, bool isForce = false);
|
||||||
Task<OperationResult> CreateAndDeActive(IFormFile file);
|
Task<OperationResult> CreateAndDeActive(IFormFile file, ApkType apkType, string versionName, string versionCode, bool isForce = false);
|
||||||
Task<string> GetLatestActiveVersionPath();
|
Task<string> GetLatestActiveVersionPath(ApkType apkType);
|
||||||
|
Task<AndroidApkVersionInfo> GetLatestActiveInfo(ApkType apkType, int currentVersionCode);
|
||||||
OperationResult Remove(long id);
|
OperationResult Remove(long id);
|
||||||
|
|
||||||
bool HasAndroidApkToDownload();
|
bool HasAndroidApkToDownload(ApkType apkType);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
namespace Company.Application.Contracts.AuthorizedBankDetails
|
||||||
|
{
|
||||||
|
public class AuthorizedBankDetailsSearchModel
|
||||||
|
{
|
||||||
|
public string CardNumber { get; set; }
|
||||||
|
public string AccountNumber { get; set; }
|
||||||
|
public string IBan { get; set; }
|
||||||
|
public string BankName { get; set; }
|
||||||
|
public string NationalIdentifier { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
namespace Company.Application.Contracts.AuthorizedBankDetails;
|
||||||
|
|
||||||
|
public class AuthorizedBankDetailsViewModel
|
||||||
|
{
|
||||||
|
public string NationalIdentifier { get; set; }
|
||||||
|
|
||||||
|
public long Id { get; set; }
|
||||||
|
public string CustomerType { get; set; }
|
||||||
|
public string CardNumber { get; set; }
|
||||||
|
public string AccountNumber { get; set; }
|
||||||
|
public string IBan { get; set; }
|
||||||
|
public string BankName { get; set; }
|
||||||
|
public List<AuthorizedBankDetailsOwnerViewModel> Owners { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Company.Application.Contracts.AuthorizedBankDetails
|
||||||
|
{
|
||||||
|
public class CreateAuthorizedBankDetails
|
||||||
|
{
|
||||||
|
public string CardNumber { get; set; }
|
||||||
|
|
||||||
|
public string AccountNumber { get; set; }
|
||||||
|
|
||||||
|
public string IBan { get; set; }
|
||||||
|
|
||||||
|
public string BankName { get; set; }
|
||||||
|
|
||||||
|
public List<CreateAuthorizedBankDetailsOwner> OwnersList { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CreateAuthorizedBankDetailsOwner
|
||||||
|
{
|
||||||
|
public string FName { get; set; }
|
||||||
|
|
||||||
|
public string LName { get; set; }
|
||||||
|
|
||||||
|
public string NationalIdentifier { get; set; }
|
||||||
|
|
||||||
|
public string CustomerType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Company.Application.Contracts.AuthorizedBankDetails
|
||||||
|
{
|
||||||
|
public class EditAuthorizedBankDetails
|
||||||
|
{
|
||||||
|
public long Id { get; set; }
|
||||||
|
|
||||||
|
public string CardNumber { get; set; }
|
||||||
|
|
||||||
|
public string AccountNumber { get; set; }
|
||||||
|
|
||||||
|
public string IBan { get; set; }
|
||||||
|
|
||||||
|
public string BankName { get; set; }
|
||||||
|
|
||||||
|
public List<AuthorizedBankDetailsOwnerViewModel> OwnersList { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AuthorizedBankDetailsOwnerViewModel
|
||||||
|
{
|
||||||
|
public string FName { get; set; }
|
||||||
|
public string LName { get; set; }
|
||||||
|
public string NationalIdentifier { get; set; }
|
||||||
|
public string CustomerType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using _0_Framework.Application;
|
||||||
|
using Company.Application.Contracts.AuthorizedBankDetails;
|
||||||
|
|
||||||
|
namespace Company.Application.Contracts.AuthorizedBankDetails
|
||||||
|
{
|
||||||
|
public interface IAuthorizedBankDetailsApplication
|
||||||
|
{
|
||||||
|
OperationResult Create(CreateAuthorizedBankDetails command);
|
||||||
|
EditAuthorizedBankDetails GetDetails(long id);
|
||||||
|
List<AuthorizedBankDetailsViewModel> Search(AuthorizedBankDetailsSearchModel searchModel);
|
||||||
|
AuthorizedBankDetailsViewModel GetByIban(string iban);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace CompanyManagment.App.Contracts.CameraBugReport
|
||||||
|
{
|
||||||
|
public class CameraBugReportDetailViewModel
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string UserEmail { get; set; }
|
||||||
|
public long? AccountId { get; set; }
|
||||||
|
public string DeviceModel { get; set; }
|
||||||
|
public string OsVersion { get; set; }
|
||||||
|
public string Platform { get; set; }
|
||||||
|
public string Manufacturer { get; set; }
|
||||||
|
public string DeviceId { get; set; }
|
||||||
|
public string ScreenResolution { get; set; }
|
||||||
|
public int MemoryInMB { get; set; }
|
||||||
|
public int StorageInMB { get; set; }
|
||||||
|
public int BatteryLevel { get; set; }
|
||||||
|
public bool IsCharging { get; set; }
|
||||||
|
public string NetworkType { get; set; }
|
||||||
|
public string AppVersion { get; set; }
|
||||||
|
public string BuildNumber { get; set; }
|
||||||
|
public string PackageName { get; set; }
|
||||||
|
public DateTime InstallTime { get; set; }
|
||||||
|
public DateTime LastUpdateTime { get; set; }
|
||||||
|
public string Flavor { get; set; }
|
||||||
|
public CameraBugReportType Type { get; set; }
|
||||||
|
public CameraBugPriority Priority { get; set; }
|
||||||
|
public CameraBugReportStatus Status { get; set; }
|
||||||
|
public string StackTrace { get; set; }
|
||||||
|
public DateTime CreationDate { get; set; }
|
||||||
|
public DateTime? UpdateDate { get; set; }
|
||||||
|
public List<string> Logs { get; set; }
|
||||||
|
public List<CameraBugReportScreenshotViewModel> Screenshots { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CameraBugReportScreenshotViewModel
|
||||||
|
{
|
||||||
|
public string FileName { get; set; }
|
||||||
|
public DateTime UploadDate { get; set; }
|
||||||
|
public string Base64Data { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace CompanyManagment.App.Contracts.CameraBugReport
|
||||||
|
{
|
||||||
|
public class CameraBugReportViewModel
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string UserEmail { get; set; }
|
||||||
|
public long? AccountId { get; set; }
|
||||||
|
public string DeviceModel { get; set; }
|
||||||
|
public string AppVersion { get; set; }
|
||||||
|
public CameraBugReportType Type { get; set; }
|
||||||
|
public CameraBugPriority Priority { get; set; }
|
||||||
|
public CameraBugReportStatus Status { get; set; }
|
||||||
|
public DateTime CreationDate { get; set; }
|
||||||
|
public DateTime? UpdateDate { get; set; }
|
||||||
|
public int LogsCount { get; set; }
|
||||||
|
public int ScreenshotsCount { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace CompanyManagment.App.Contracts.CameraBugReport
|
||||||
|
{
|
||||||
|
public class CreateCameraBugReportCommand
|
||||||
|
{
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public string UserEmail { get; set; }
|
||||||
|
public long? AccountId { get; set; }
|
||||||
|
public string DeviceModel { get; set; }
|
||||||
|
public string OsVersion { get; set; }
|
||||||
|
public string Platform { get; set; }
|
||||||
|
public string Manufacturer { get; set; }
|
||||||
|
public string DeviceId { get; set; }
|
||||||
|
public string ScreenResolution { get; set; }
|
||||||
|
public int MemoryInMB { get; set; }
|
||||||
|
public int StorageInMB { get; set; }
|
||||||
|
public int BatteryLevel { get; set; }
|
||||||
|
public bool IsCharging { get; set; }
|
||||||
|
public string NetworkType { get; set; }
|
||||||
|
public string AppVersion { get; set; }
|
||||||
|
public string BuildNumber { get; set; }
|
||||||
|
public string PackageName { get; set; }
|
||||||
|
public DateTime InstallTime { get; set; }
|
||||||
|
public DateTime LastUpdateTime { get; set; }
|
||||||
|
public string Flavor { get; set; }
|
||||||
|
public CameraBugReportType Type { get; set; }
|
||||||
|
public CameraBugPriority Priority { get; set; }
|
||||||
|
public string StackTrace { get; set; }
|
||||||
|
public List<string> Logs { get; set; }
|
||||||
|
public List<string> Screenshots { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace CompanyManagment.App.Contracts.CameraBugReport
|
||||||
|
{
|
||||||
|
public class EditCameraBugReportCommand
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public CameraBugPriority Priority { get; set; }
|
||||||
|
public CameraBugReportStatus Status { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using _0_Framework.Application;
|
||||||
|
|
||||||
|
namespace CompanyManagment.App.Contracts.CameraBugReport
|
||||||
|
{
|
||||||
|
public interface ICameraBugReportApplication
|
||||||
|
{
|
||||||
|
Task<OperationResult> CreateAsync(CreateCameraBugReportCommand command);
|
||||||
|
Task<OperationResult> EditAsync(EditCameraBugReportCommand command);
|
||||||
|
Task<OperationResult> DeleteAsync(Guid id);
|
||||||
|
Task<List<CameraBugReportViewModel>> GetAllAsync(CameraBugReportSearchModel searchModel);
|
||||||
|
Task<CameraBugReportDetailViewModel> GetDetailsAsync(Guid id);
|
||||||
|
Task<bool> IsExistAsync(Guid id);
|
||||||
|
|
||||||
|
// Keep sync methods for backward compatibility but they delegate to async
|
||||||
|
OperationResult Create(CreateCameraBugReportCommand command);
|
||||||
|
OperationResult Edit(EditCameraBugReportCommand command);
|
||||||
|
OperationResult Delete(Guid id);
|
||||||
|
List<CameraBugReportViewModel> GetAll(CameraBugReportSearchModel searchModel);
|
||||||
|
CameraBugReportDetailViewModel GetDetails(Guid id);
|
||||||
|
bool IsExist(Guid id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CameraBugReportSearchModel
|
||||||
|
{
|
||||||
|
public CameraBugReportType? Type { get; set; }
|
||||||
|
public CameraBugPriority? Priority { get; set; }
|
||||||
|
public CameraBugReportStatus? Status { get; set; }
|
||||||
|
public string SearchTerm { get; set; }
|
||||||
|
public int PageNumber { get; set; } = 1;
|
||||||
|
public int PageSize { get; set; } = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// </summary>
|
||||||
|
/// وضعیت گزارش خرابی دوربین
|
||||||
|
/// <summary>
|
||||||
|
public enum CameraBugReportStatus
|
||||||
|
{
|
||||||
|
Reopened = 5, // مجدداً باز شده
|
||||||
|
Closed = 4, // بسته شده
|
||||||
|
Fixed = 3, // رفع شده
|
||||||
|
InProgress = 2, // در حال بررسی
|
||||||
|
Open = 1, // باز
|
||||||
|
}
|
||||||
|
|
||||||
|
/// </summary>
|
||||||
|
/// اولویت گزارش خرابی دوربین
|
||||||
|
/// <summary>
|
||||||
|
public enum CameraBugPriority
|
||||||
|
{
|
||||||
|
Low = 4, // پایین
|
||||||
|
Medium = 3, // متوسط
|
||||||
|
High = 2, // بالا
|
||||||
|
Critical = 1, // بحرانی
|
||||||
|
}
|
||||||
|
|
||||||
|
/// </summary>
|
||||||
|
/// انواع گزارش خرابی دوربین
|
||||||
|
/// <summary>
|
||||||
|
public enum CameraBugReportType
|
||||||
|
{
|
||||||
|
Other = 8, // سایر
|
||||||
|
CrashOnCapture = 7, // کرش هنگام عکسبرداری
|
||||||
|
LightingIssue = 6, // مشکل روشنایی
|
||||||
|
FocusIssue = 5, // مشکل فوکوس
|
||||||
|
PerformanceIssue = 4, // مشکل عملکردی
|
||||||
|
FaceRecognitionFailed = 3, // شناسایی چهره ناموفق
|
||||||
|
BlurryImage = 2, // تصویر مبهم
|
||||||
|
CameraNotWorking = 1, // دوربین کار نمیکند
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using _0_Framework.Application.Enums;
|
||||||
using CompanyManagment.App.Contracts.Employer;
|
using CompanyManagment.App.Contracts.Employer;
|
||||||
using CompanyManagment.App.Contracts.Loan;
|
using CompanyManagment.App.Contracts.Loan;
|
||||||
using CompanyManagment.App.Contracts.RollCall;
|
using CompanyManagment.App.Contracts.RollCall;
|
||||||
@@ -133,6 +134,15 @@ public class CheckoutViewModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string TotalPaidLeave { get; set; }
|
public string TotalPaidLeave { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// آیا فیش نیاز به بروزرسانی دارد
|
||||||
|
/// </summary>
|
||||||
|
public bool IsUpdateNeeded { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// لیست پیام های هشدار فیش حقوقی
|
||||||
|
/// </summary>
|
||||||
|
public List<CheckoutWarningMessageModel> CheckoutWarningMessageList { get; set; }
|
||||||
|
|
||||||
public bool HasSignCheckout { get; set; }
|
public bool HasSignCheckout { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
using _0_Framework.Application.Enums;
|
||||||
|
|
||||||
|
namespace CompanyManagment.App.Contracts.Checkout;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// مدل هشدار فیش حقوقی
|
||||||
|
/// </summary>
|
||||||
|
public class CheckoutWarningMessageModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// پیام هشدار
|
||||||
|
/// </summary>
|
||||||
|
public string WarningMessage { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// آی دی فیش حقوقی
|
||||||
|
/// </summary>
|
||||||
|
public long CheckoutId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// نوع هشدار فیش حقوقی
|
||||||
|
/// </summary>
|
||||||
|
public TypeOfCheckoutWarning TypeOfCheckoutWarning { get; set; }
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Security.AccessControl;
|
using System.Security.AccessControl;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Transactions;
|
using System.Transactions;
|
||||||
using _0_Framework.Application;
|
using _0_Framework.Application;
|
||||||
|
using _0_Framework.Application.UID;
|
||||||
using CompanyManagment.App.Contracts.OriginalTitle;
|
using CompanyManagment.App.Contracts.OriginalTitle;
|
||||||
|
|
||||||
namespace CompanyManagment.App.Contracts.ContractingPartyBankAccounts;
|
namespace CompanyManagment.App.Contracts.ContractingPartyBankAccounts;
|
||||||
@@ -74,5 +76,27 @@ public interface IContractingPartyBankAccountsApplication
|
|||||||
/// <param name="selected">نام سلکت شده</param>
|
/// <param name="selected">نام سلکت شده</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task<List<string>> ContractingPartyNamesSelectList(string search, string selected);
|
Task<List<string>> ContractingPartyNamesSelectList(string search, string selected);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// احراز هویت اطلاعات بانکی طرف حساب
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="command"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
Task<ContractingPartyBankInquiryResponse> InquiryContractingPartyBankDetails(InquiryContractingPartyBankDetailsRequest command);
|
||||||
|
|
||||||
|
}
|
||||||
|
public class InquiryContractingPartyBankDetailsRequest
|
||||||
|
{
|
||||||
|
public string CardNumber { get; set; }
|
||||||
|
public string AccountNumber { get; set; }
|
||||||
|
public string IBan { get; set; }
|
||||||
|
public UidBanks? UidBank { get; set; }
|
||||||
|
}
|
||||||
|
public class ContractingPartyBankInquiryResponse
|
||||||
|
{
|
||||||
|
public string FullName { get; set; }
|
||||||
|
public string Iban { get; set; }
|
||||||
|
public string AccountNumber { get; set; }
|
||||||
|
public string CardNumber { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user