Compare commits

...

80 Commits

Author SHA1 Message Date
21624a835b fix: update time restrictions for entry and exit registration to 5 minutes 2025-12-22 12:16:47 +03:30
12fab5a9a5 add {id:guid} convention for controllers 2025-12-20 20:57:34 +03:30
20dd8f64f4 add: include OneMonthWithoutTax and OneMonthTax properties in InstitutionContractPrintViewModel 2025-12-20 20:28:08 +03:30
b827493306 refactor: remove unused discount-related classes from IInstitutionContractApplicationpnpm 2025-12-20 20:12:31 +03:30
04c65eae93 Merge branch 'Feature/institution-contract/print'
# Conflicts:
#	CompanyManagment.App.Contracts/InstitutionContract/IInstitutionContractApplication.cs
2025-12-20 20:10:30 +03:30
b4526a4338 Merge branch 'Feature/institution-contract/verify-mannually' 2025-12-20 20:09:13 +03:30
2d879ce80a fix: update workshop identification logic in InstitutionContractApplication 2025-12-20 20:06:28 +03:30
56e79d2099 fix: correct ContractAmountWithTax calculation for old contracts 2025-12-20 19:38:32 +03:30
93891f3837 add one month more details for InstitutionContract.cs print 2025-12-20 19:18:27 +03:30
SamSys
5bdfbc572b add next deploy and contractingParty add to workshop on AndroidApk page 2025-12-20 18:42:53 +03:30
4385a65cbc feat: add manual verification endpoint for institution contracts 2025-12-20 18:27:59 +03:30
722f8dae7c feat: implement manual verification for institution contracts and add signing type handling 2025-12-20 18:27:17 +03:30
SamSys
07113353c4 add uploadFrontEnd btn to AndroidApk page 2025-12-20 16:01:07 +03:30
8c6336b9bd fix: correct IsOldContract logic to properly identify old contracts 2025-12-20 14:35:02 +03:30
20e3d454cf feat: add ContractAmountWithTax calculation and update related references 2025-12-20 13:35:52 +03:30
2bf31db6b2 fix: enhance parameter binding logic for route parameters 2025-12-20 12:05:34 +03:30
7a4a6de84f feat: add OneMonthPrice to institution contract details 2025-12-20 10:56:36 +03:30
4f16d7680c feat: add insurance client list retrieval with pagination and filtering 2025-12-18 10:59:06 +03:30
SamSys
7a10d5ce59 changes 2025-12-18 10:40:11 +03:30
SamSys
3d88feeee7 Clent Add Employee Change to authorizedCanceled 2025-12-17 19:13:47 +03:30
SamSys
f408624463 Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-17 13:25:38 +03:30
SamSys
8296292e49 checkout week finder switch fixed bug 2025-12-17 13:25:24 +03:30
be8deef167 fix: update license context setting for Excel packages 2025-12-17 11:33:40 +03:30
84fb29c8c8 feat: enhance project creation validation and add operation result filter 2025-12-16 20:18:54 +03:30
0969e8a5fd Merge remote-tracking branch 'origin/master' 2025-12-16 19:14:28 +03:30
92e2282381 refactor: change GetAllCodes to return a dictionary for improved structure 2025-12-16 19:13:30 +03:30
SamSys
3b71b7d707 add pmPermission to claim 2025-12-16 18:24:18 +03:30
6123a53f01 fix: update permission check for project board visibility 2025-12-16 17:15:22 +03:30
ec74db17eb Merge branch 'master' into Feature/program-manager/set-permission-board 2025-12-16 17:10:41 +03:30
dc118cf18b Merge branch 'master' of https://github.com/syntax24/OriginalGozareshgir 2025-12-16 17:09:54 +03:30
a11e54c333 Add project board detail endpoint & validation improvements
- Added GET /board/{id:guid} endpoint to ProjectController for detailed project board info.
- Enforced max length of 15 characters for project names in CreateProjectCommandValidator.
- Improved SetTimeProjectCommandHandler: skip zero/negative initial times, removed duplicate error message, and cleaned up formatting.
- Enhanced RollCallApplication to use employee-specific workshop shift settings when available.
2025-12-16 17:09:28 +03:30
SamSys
2383e7a54f Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-16 17:03:02 +03:30
SamSys
2ef1ea3d1a add new permission for workshop 2025-12-16 17:02:40 +03:30
SamSys
ebdc9b1e55 ProgramManager PermissionCodes set 2025-12-16 16:26:15 +03:30
9e5a494881 feat: enhance project board query with skill and user details 2025-12-16 14:18:00 +03:30
2972807c9f feat: add permission handling methods and project board detail query 2025-12-16 12:56:49 +03:30
f7351454f3 feat: implement method to update face embedding names for employees with changed names 2025-12-16 11:05:22 +03:30
b64d0e5ffd feat: add method to update employee full name in FaceEmbeddingService and integrate with RollCallEmployeeApplication 2025-12-16 10:39:51 +03:30
35b7a3a3dd remove documentation file generation from project settings 2025-12-16 09:32:42 +03:30
fe93ef60c9 Merge branch 'master' of https://github.com/syntax24/OriginalGozareshgir 2025-12-15 21:14:06 +03:30
ef865d9c68 Add Skill navigation to Phase/ProjectSection, refactor logic
- Add Skill navigation properties to PhaseSection and ProjectSection, with EF Core mappings and migration for foreign keys and indexes.
- Refactor SetSkillFlags in GetProjectsListQueryHandler for clarity and efficiency; use eager loading for Skill.
- Add HasRemainingTime() to TaskSection and enforce time check in ChangeStatusSectionCommandHandler.
- Optimize EmployeeDocumentsRepository queries; add EmployeeId to WorkshopWithEmployeeDocumentsViewModel.
- Improve CustomExceptionHandler to handle FluentValidation exceptions and return proper status codes.
- Add FluentValidation package reference and perform minor code cleanups.
2025-12-15 20:56:32 +03:30
SamSys
61e35100f9 Merge branch 'master' of https://github.com/samsyntax24/OriginalGozareshgir 2025-12-15 18:49:35 +03:30
SamSys
01d33ff340 add InstitutionContract Confirm Reminder Sms completed 2025-12-15 18:49:13 +03:30
cd64e1d24d Merge remote-tracking branch 'origin/master' 2025-12-15 14:06:18 +03:30
d9da2e97ab feat: add method to retrieve task sections assigned to a user and enhance permission code structure 2025-12-15 14:06:07 +03:30
SamSys
1c1c8816a5 pm GetHolidaysInDates completed - remove OldholidayItems 2025-12-15 14:01:42 +03:30
a1e85261a6 Merge remote-tracking branch 'origin/master' 2025-12-15 13:49:53 +03:30
000af89fd7 feat: add permission checking and task assignment handling in ProjectBoardHub 2025-12-15 13:49:41 +03:30
SamSys
a4f3feba1c update account edit method 2025-12-15 13:26:09 +03:30
SamSys
a3d286c040 remove PmDbContext and depndencies 2025-12-15 13:05:05 +03:30
SamSys
902ef34757 Remove Pm Old Context 2025-12-15 12:42:19 +03:30
SamSys
e67aca37f9 Insurance HasCheckout change 2025-12-15 12:15:00 +03:30
2a31b27f9b feat: simplify StartWork and StopWork methods by removing userId parameter 2025-12-15 10:43:17 +03:30
e05eb1236b Merge branch 'refs/heads/Feature/program-manager/signalR-notification'
# Conflicts:
#	ServiceHost/Program.cs
2025-12-15 10:41:31 +03:30
a7d3b1e96f feat: update SignalR group handling for project status notifications 2025-12-15 10:14:32 +03:30
73bef104fb feat: implement custom parameter binding convention for ASP.NET Core 2025-12-15 09:45:39 +03:30
SamSys
b31559a29a add institutionContractConfirmTab SmsSettigs 2025-12-14 18:59:22 +03:30
SamSys
e62270a9b7 update sms settings js 2025-12-14 18:14:18 +03:30
SamSys
998759e2dc change smsSettings 2025-12-14 17:58:27 +03:30
SamSys
49d401856f change GetAverageWeeklyDuration method 2025-12-14 17:46:19 +03:30
SamSys
2faf6c1400 Get Average Weekly Duration query Handler 2025-12-14 16:27:36 +03:30
SamSys
a01a927f6f chnage pm shift duration method on domain 2025-12-14 15:11:39 +03:30
bca1e66f0f feat: update ProjectBoardHub endpoint to include API prefix 2025-12-14 14:21:45 +03:30
SamSys
097d5a6e86 sepration report js 2025-12-14 14:03:39 +03:30
83a7bbf5f3 feat: register SignalR notification publisher for board updates 2025-12-14 13:50:24 +03:30
SamSys
24501df615 sepration js and css for workshop and account 2025-12-14 12:50:19 +03:30
da46d45601 feat: implement SignalR notifications for project status changes 2025-12-14 12:13:23 +03:30
14fda440c1 Merge branch 'Feature/program-manager/move' 2025-12-14 11:19:31 +03:30
85ce92af2c feat: add permission attribute to program manager menu items 2025-12-14 09:41:16 +03:30
SamSys
5777a869cf migration changes 2025-12-13 22:42:08 +03:30
ed6301831c add program-manager in menu 2025-12-13 20:38:47 +03:30
2d0eb52211 merge from programManager Move 2025-12-13 20:24:20 +03:30
05d8b738cc Merge branch 'Feature/notification/create-api' 2025-12-13 20:18:29 +03:30
370feca81e Refactor bug report pages to use string identifiers and improve styling 2025-12-13 18:26:01 +03:30
339cea998a Merge branch 'Feature/roll-call/camera-bug-report'
# Conflicts:
#	PersonalContractingParty.Config/PersonalBootstrapper.cs
2025-12-13 17:30:31 +03:30
b3f42af77c Refactor bug report system to use Guid for identifiers instead of long 2025-12-13 11:19:17 +03:30
eb49bf771d changes mongo camera report 2025-12-12 19:42:08 +03:30
ea896c4c11 Add migration for camera bug report system with related logs and screenshots 2025-12-07 17:56:56 +03:30
167b2bce09 Implement camera bug report system with CRUD operations and logging 2025-12-07 17:54:55 +03:30
517f2d06ca Add CountController to manage task, ticket, and workflow counts 2025-12-06 17:44:00 +03:30
209 changed files with 33386 additions and 6020 deletions

View File

@@ -6,6 +6,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FluentValidation" Version="12.1.1" />
<PackageReference Include="IPE.SmsIR" Version="1.2.7" />
<PackageReference Include="EPPlus" Version="8.4.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="2.3.0" />

View File

@@ -56,6 +56,11 @@ public class AuthHelper : IAuthHelper
return Tools.DeserializeFromBsonList<int>(permissions); //Mahan
}
public bool HasPermission(int permission)
{
return GetPermissions().Any(x => x == permission);
}
public long CurrentAccountId()
{
return IsAuthenticated()
@@ -199,7 +204,7 @@ public class AuthHelper : IAuthHelper
new("WorkshopSlug",slug),
new("WorkshopId", account.WorkshopId.ToString()),
new("WorkshopName",account.WorkshopName??""),
new("pm.userId", account.PmUserId?.ToString() ?? "0"),
new("pm.userId", account.PmUserId.ToString()),
};

View File

@@ -33,4 +33,9 @@ public enum TypeOfSmsSetting
/// </summary>
LegalAction,
/// <summary>
/// پیامک تایید قراداد
/// </summary>
InstitutionContractConfirm,
}

View File

@@ -11,6 +11,7 @@ public interface IFaceEmbeddingService
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);
Task<OperationResult> UpdateEmbeddingFullNameAsync(long employeeId, long workshopId, string newFullName);
}
public class FaceEmbeddingResponse

View File

@@ -12,6 +12,7 @@ public interface IAuthHelper
string CurrentAccountRole();
AuthViewModel CurrentAccountInfo();
List<int> GetPermissions();
bool HasPermission(int permission);
long CurrentAccountId();
string CurrentAccountMobile();

View File

@@ -27,7 +27,7 @@ public interface ISmsService
Task<double> GetCreditAmount();
public Task<bool> SendInstitutionCreationVerificationLink(string number, string fullName, Guid institutionId, long contractingPartyId, long institutionContractId);
public Task<bool> SendInstitutionCreationVerificationLink(string number, string fullName, Guid institutionId, long contractingPartyId, long institutionContractId, string typeOfSms = null);
public Task<bool> SendInstitutionVerificationCode(string number, string code, string contractingPartyFullName,
long contractingPartyId, long institutionContractId);

View File

@@ -17,7 +17,7 @@ public class ExcelGenerator
{
public ExcelGenerator()
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
}
public static byte[] GenerateExcel<T>(List<T> obj, string date = "") where T : class
{

View File

@@ -1,7 +1,10 @@
using System;
#nullable enable
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FluentValidation;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -27,6 +30,14 @@ public class CustomExceptionHandler : IExceptionHandler
(string Detail, string Title, int StatusCode, Dictionary<string, object>? Extra) details = exception switch
{
ValidationException validationException =>
(
validationException.Errors.FirstOrDefault()?.ErrorMessage ?? "One or more validation errors occurred.",
"Validation Error",
context.Response.StatusCode = StatusCodes.Status400BadRequest,
null
),
InternalServerException =>
(
exception.Message,
@@ -34,6 +45,7 @@ public class CustomExceptionHandler : IExceptionHandler
context.Response.StatusCode = StatusCodes.Status500InternalServerError,
null
),
BadRequestException bre =>
(
exception.Message,
@@ -41,6 +53,7 @@ public class CustomExceptionHandler : IExceptionHandler
context.Response.StatusCode = StatusCodes.Status400BadRequest,
bre.Extra
),
NotFoundException =>
(
exception.Message,
@@ -48,6 +61,7 @@ public class CustomExceptionHandler : IExceptionHandler
context.Response.StatusCode = StatusCodes.Status404NotFound,
null
),
UnAuthorizeException =>
(
exception.Message,
@@ -55,6 +69,7 @@ public class CustomExceptionHandler : IExceptionHandler
context.Response.StatusCode = StatusCodes.Status401Unauthorized,
null
),
_ =>
(
exception.Message,
@@ -73,8 +88,6 @@ public class CustomExceptionHandler : IExceptionHandler
Extensions = details.Extra ?? new Dictionary<string, object>()
};
problemDetails.Extensions.Add("traceId", context.TraceIdentifier);
await context.Response.WriteAsJsonAsync(problemDetails, cancellationToken: cancellationToken);

View File

@@ -81,7 +81,8 @@ public class FaceEmbeddingService : IFaceEmbeddingService
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
_logger.LogInformation("Embeddings generated successfully for Employee {EmployeeId}, Workshop {WorkshopId}",
_logger.LogInformation(
"Embeddings generated successfully for Employee {EmployeeId}, Workshop {WorkshopId}",
employeeId, workshopId);
// ارسال اطلاع‌رسانی به سایر سیستم‌ها
@@ -159,7 +160,8 @@ public class FaceEmbeddingService : IFaceEmbeddingService
if (response.IsSuccessStatusCode)
{
_logger.LogInformation("Embeddings generated successfully from streams for Employee {EmployeeId}", employeeId);
_logger.LogInformation("Embeddings generated successfully from streams for Employee {EmployeeId}",
employeeId);
// ارسال اطلاع‌رسانی به سایر سیستم‌ها
if (_notificationService != null)
@@ -184,7 +186,8 @@ public class FaceEmbeddingService : IFaceEmbeddingService
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while generating embeddings from streams for Employee {EmployeeId}", employeeId);
_logger.LogError(ex, "Error while generating embeddings from streams for Employee {EmployeeId}",
employeeId);
return new OperationResult
{
IsSuccedded = false,
@@ -343,4 +346,59 @@ public class FaceEmbeddingService : IFaceEmbeddingService
};
}
}
public async Task<OperationResult> UpdateEmbeddingFullNameAsync(long employeeId, long workshopId,
string newFullName)
{
try
{
var httpClient = _httpClientFactory.CreateClient();
httpClient.BaseAddress = new Uri(_apiBaseUrl);
httpClient.Timeout = TimeSpan.FromSeconds(30);
var requestBody = new
{
employee_id = employeeId,
workshop_id = workshopId,
employee_full_name = newFullName
};
var response = await httpClient.PutAsJsonAsync("embeddings/update-name", requestBody);
if (response.IsSuccessStatusCode)
{
_logger.LogInformation("Employee Name Changed For {EmployeeId} In workshop ={WorkshopId}", employeeId,
workshopId);
// ارسال اطلاع‌رسانی به سایر سیستم‌ها
if (_notificationService != null)
{
//await _notificationService.NotifyEmbeddingRefinedAsync(workshopId, employeeId);
}
return new OperationResult { IsSuccedded = true, Message = "عملیات با موفقیت انجام شد" };
}
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 Changing EmployeeFullName for Employee {EmployeeId}", employeeId);
return new OperationResult
{
IsSuccedded = false,
Message = "خطا در بهبود Embedding"
};
}
}
}

View File

@@ -1,6 +1,4 @@
using System.Collections.Generic;
namespace AccountManagement.Application.Contracts.Account;
namespace AccountManagement.Application.Contracts.Account;
public class EditAccount : CreateAccount
{

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AccountManagement.Application.Contracts.Account;
namespace AccountManagement.Application.Contracts.Account;
public class EditClientAccount : RegisterAccount
{

View File

@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using AccountManagement.Application.Contracts.ProgramManager;
using Shared.Contracts.PmUser.Queries;
namespace AccountManagement.Application.Contracts.Account;
@@ -75,12 +74,8 @@ public interface IAccountApplication
void CameraLogin(CameraLoginRequest request);
/// <summary>
/// دریافت کاربر پروگرام منیجر با اکانت آی دی
/// </summary>
/// <param name="accountId"></param>
/// <returns></returns>
Task<GetPmUserDto> GetPmUserByAccountId(long accountId);
Task<GetPmUserDto> GetPmUserAsync(long accountId);
}
public class CameraLoginRequest

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _0_Framework.Application;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Http;
namespace AccountManagement.Application.Contracts.Account;

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AccountManagement.Application.Contracts.Account;
namespace AccountManagement.Application.Contracts.Account;
public class WorkshopSelectList
{

View File

@@ -1,28 +0,0 @@
using System.Collections.Generic;
namespace AccountManagement.Application.Contracts.ProgramManager;
public record GetPmRolesDto
{
/// <summary>
/// آی دی نقش
/// </summary>
public long Id { get; set; }
/// <summary>
/// نام نقش
/// </summary>
public string RoleName { get; set; }
/// <summary>
/// آی دی نقش در گزارشگیر
/// </summary>
public long? GozareshgirRoleId { get; set; }
/// <summary>
/// لیست کدهای دسترسی
/// </summary>
public List<int> Permissions { get; set; }
}

View File

@@ -2,13 +2,9 @@
using _0_Framework.Application.Sms;
using _0_Framework.Exceptions;
using AccountManagement.Application.Contracts.Account;
using AccountManagement.Application.Contracts.ProgramManagerApiResult;
using AccountManagement.Domain.AccountAgg;
using AccountManagement.Domain.AccountLeftWorkAgg;
using AccountManagement.Domain.CameraAccountAgg;
using AccountManagement.Domain.InternalApiCaller;
using AccountManagement.Domain.PmDomains.PmRoleUserAgg;
using AccountManagement.Domain.PmDomains.PmUserAgg;
using AccountManagement.Domain.PositionAgg;
using AccountManagement.Domain.RoleAgg;
using AccountManagement.Domain.SubAccountAgg;
@@ -17,25 +13,13 @@ using AccountManagement.Domain.SubAccountRoleAgg;
using Company.Domain._common;
using Company.Domain.WorkshopAgg;
using Company.Domain.WorkshopSubAccountAgg;
using CompanyManagment.App.Contracts.Workshop;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.JsonPatch.Operations;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Runtime.InteropServices;
using System.Security.Claims;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AccountManagement.Application.Contracts.ProgramManager;
using Shared.Contracts.PmUser.Commands;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
using Shared.Contracts.PmUser.Queries;
//using AccountManagement.Domain.RoleAgg;
@@ -58,13 +42,13 @@ public class AccountApplication : IAccountApplication
private readonly ISubAccountRoleRepository _subAccountRoleRepository;
private readonly IWorkshopSubAccountRepository _workshopSubAccountRepository;
private readonly ISubAccountPermissionSubtitle1Repository _accountPermissionSubtitle1Repository;
private readonly IPmUserRepository _pmUserRepository;
private readonly IUnitOfWork _unitOfWork;
private readonly IPmUserQueryService _pmUserQueryService;
private readonly IPmUserCommandService _pmUserCommandService;
public AccountApplication(IAccountRepository accountRepository, IPasswordHasher passwordHasher,
IFileUploader fileUploader, IAuthHelper authHelper, IRoleRepository roleRepository, IWorker worker, ISmsService smsService, ICameraAccountRepository cameraAccountRepository, IPositionRepository positionRepository, IAccountLeftworkRepository accountLeftworkRepository, IWorkshopRepository workshopRepository, ISubAccountRepository subAccountRepository, ISubAccountRoleRepository subAccountRoleRepository, IWorkshopSubAccountRepository workshopSubAccountRepository, ISubAccountPermissionSubtitle1Repository accountPermissionSubtitle1Repository, IUnitOfWork unitOfWork, IPmUserRepository pmUserRepository, IPmUserQueryService pmUserQueryService, IPmUserCommandService pmUserCommandService)
IFileUploader fileUploader, IAuthHelper authHelper, IRoleRepository roleRepository, IWorker worker, ISmsService smsService, ICameraAccountRepository cameraAccountRepository, IPositionRepository positionRepository, IAccountLeftworkRepository accountLeftworkRepository, IWorkshopRepository workshopRepository, ISubAccountRepository subAccountRepository, ISubAccountRoleRepository subAccountRoleRepository, IWorkshopSubAccountRepository workshopSubAccountRepository, ISubAccountPermissionSubtitle1Repository accountPermissionSubtitle1Repository, IUnitOfWork unitOfWork, IPmUserQueryService pmUserQueryService, IPmUserCommandService pmUserCommandService)
{
_authHelper = authHelper;
_roleRepository = roleRepository;
@@ -78,7 +62,7 @@ public class AccountApplication : IAccountApplication
_workshopSubAccountRepository = workshopSubAccountRepository;
_accountPermissionSubtitle1Repository = accountPermissionSubtitle1Repository;
_unitOfWork = unitOfWork;
_pmUserRepository = pmUserRepository;
_pmUserQueryService = pmUserQueryService;
_pmUserCommandService = pmUserCommandService;
_fileUploader = fileUploader;
@@ -171,6 +155,8 @@ public class AccountApplication : IAccountApplication
if (command.IsProgramManagerUser)
{
if (command.UserRoles == null)
return operation.Failed("حداقل یک نقش برای کاربر مدیریت پروژه لازم است");
var pmUserRoles = command.UserRoles.Where(x => x > 0).ToList();
var createPm = await _pmUserCommandService.Create(new CreatePmUserDto(command.Fullname, command.Username, account.Password, command.Mobile,
null, account.id, pmUserRoles));
@@ -268,6 +254,8 @@ public class AccountApplication : IAccountApplication
//);
var userResult =await _pmUserQueryService.GetPmUserDataByAccountId(account.id);
if (command.UserRoles == null)
return operation.Failed("حداقل یک نقش برای کاربر مدیریت پروژه لازم است");
var pmUserRoles = command.UserRoles.Where(x => x > 0).ToList();
//اگر کاربر در پروگرام منیجر قبلا ایجاد شده
@@ -412,6 +400,23 @@ public class AccountApplication : IAccountApplication
.Permissions
.Select(x => x.Code)
.ToList();
//PmPermission
var PmUserData = _pmUserQueryService.GetPmUserDataByAccountId(account.id).GetAwaiter().GetResult();
if (PmUserData.AccountId > 0 && PmUserData.IsActive)
{
var pmUserPermissions =
PmUserData.RoleListDto != null
? PmUserData.RoleListDto
.SelectMany(x => x.Permissions)
.Where(p => p != 99)
.Distinct()
.ToList()
: new List<int>();
permissions.AddRange(pmUserPermissions);
}
int? positionValue;
if (account.PositionId != null)
{
@@ -421,7 +426,7 @@ public class AccountApplication : IAccountApplication
{
positionValue = null;
}
var pmUserId = _pmUserQueryService.GetCurrentPmUserIdFromAccountId(account.id).GetAwaiter().GetResult();
var pmUserId = PmUserData.AccountId > 0 ? PmUserData.AccountId : null;
var authViewModel = new AuthViewModel(account.id, account.RoleId, account.Fullname
, account.Username, account.Mobile, account.ProfilePhoto,
permissions, account.RoleName, account.AdminAreaPermission,
@@ -1015,8 +1020,8 @@ public class AccountApplication : IAccountApplication
_authHelper.CameraSignIn(authViewModel);
}
public async Task<GetPmUserDto> GetPmUserByAccountId(long accountId)
public async Task<GetPmUserDto> GetPmUserAsync(long accountId)
{
return await _pmUserRepository.GetPmUserByAccountId(accountId);
return await _pmUserQueryService.GetPmUserDataByAccountId(accountId);
}
}

View File

@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _0_Framework.Application;
using AccountManagement.Application.Contracts.Account;
using AccountManagement.Application.Contracts.CameraAccount;

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using _0_Framework.Application;

View File

@@ -4,13 +4,7 @@ using AccountManagement.Domain.RoleAgg;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AccountManagement.Application.Contracts.ProgramManagerApiResult;
using AccountManagement.Domain.InternalApiCaller;
using Company.Domain._common;
using AccountManagement.Application.Contracts.Ticket;
using AccountManagement.Domain.PmDomains.PmPermissionAgg;
using AccountManagement.Domain.PmDomains.PmRoleAgg;
using AccountManagement.Domain.PmDomains.PmUserAgg;
using Microsoft.AspNetCore.Mvc.Rendering;
using Shared.Contracts.PmRole.Commands;
using GetPmRolesDto = Shared.Contracts.PmRole.Queries.GetPmRolesDto;
@@ -22,18 +16,15 @@ namespace AccountManagement.Application;
public class RoleApplication : IRoleApplication
{
private readonly IRoleRepository _roleRepository;
private readonly IPmRoleRepository _pmRoleRepository;
private readonly IPmUserRepository _pmUserRepository;
private readonly IPmRoleQueryService _pmRoleQueryService;
private readonly IPmRoleCommandService _pmRoleCommandService;
private readonly IUnitOfWork _unitOfWork;
public RoleApplication(IRoleRepository roleRepository, IUnitOfWork unitOfWork, IPmRoleRepository pmRoleRepository, IPmUserRepository pmUserRepository, IPmRoleQueryService pmRoleQueryService, IPmRoleCommandService pmRoleCommandService)
public RoleApplication(IRoleRepository roleRepository, IUnitOfWork unitOfWork, IPmRoleQueryService pmRoleQueryService, IPmRoleCommandService pmRoleCommandService)
{
_roleRepository = roleRepository;
_unitOfWork = unitOfWork;
_pmRoleRepository = pmRoleRepository;
_pmUserRepository = pmUserRepository;
_pmRoleQueryService = pmRoleQueryService;
_pmRoleCommandService = pmRoleCommandService;
}

View File

@@ -5,14 +5,11 @@ using AccountManagement.Domain.AccountAgg;
using AccountManagement.Domain.CameraAccountAgg;
using AccountManagement.Domain.SubAccountAgg;
using AccountManagement.Domain.SubAccountRoleAgg;
using Company.Domain.WorkshopAccountAgg;
using Company.Domain.WorkshopSubAccountAgg;
using CompanyManagment.App.Contracts.Workshop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
namespace AccountManagement.Application

View File

@@ -1,9 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using _0_Framework.Application;
using AccountManagement.Application.Contracts.TaskSubject;
using AccountManagement.Domain.TaskSubjectAgg;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
namespace AccountManagement.Application;

View File

@@ -1,18 +0,0 @@
using AccountManagement.Domain.PmDomains.PmRoleAgg;
using AccountManagement.Domain.PmDomains.PmUserAgg;
using AccountMangement.Infrastructure.EFCore.PmDbConetxt;
using AccountMangement.Infrastructure.EFCore.Repository.PmRepositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace AccountManagement.Configuration;
public class PmDbBootstrapper
{
public static void Configure(IServiceCollection services, string connectionString)
{
services.AddTransient<IPmRoleRepository, PmRoleRepository>();
services.AddTransient<IPmUserRepository, PmUserRepository>();
services.AddDbContext<PmDbContext>(x => x.UseSqlServer(connectionString));
}
}

View File

@@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AccountManagement.Domain.PmDomains.PmRoleAgg;
namespace AccountManagement.Domain.PmDomains.PmPermissionAgg;
public class PmPermission
{
public long Id { get; private set; }
public int Code { get; private set; }
public PmRole Role { get; private set; }
public PmPermission(int code)
{
Code = code;
}
}

View File

@@ -1,15 +0,0 @@
using _0_Framework.Domain;
using System.Collections.Generic;
using System.Threading.Tasks;
using AccountManagement.Application.Contracts.ProgramManager;
namespace AccountManagement.Domain.PmDomains.PmRoleAgg;
public interface IPmRoleRepository :IRepository<long, PmRole>
{
Task<List<GetPmRolesDto>> GetPmRoleList(long? gozareshgirRoleId);
Task<PmRole?> GetPmRoleToEdit(long gozareshgirRoleId);
}

View File

@@ -1,46 +0,0 @@
using System.Collections.Generic;
using _0_Framework.Domain;
using AccountManagement.Domain.PmDomains.PmPermissionAgg;
namespace AccountManagement.Domain.PmDomains.PmRoleAgg;
public class PmRole : EntityBase
{
/// <summary>
/// نام نقش
/// </summary>
public string RoleName { get; private set; }
/// <summary>
/// لیست پرمیشن کد ها
/// </summary>
public List<PmPermission> PmPermission { get; private set; }
/// <summary>
/// ای دی نقش در گزارشگیر
/// </summary>
public long? GozareshgirRoleId { get; private set; }
protected PmRole()
{
}
public PmRole(string roleName,long? gozareshgirRolId, List<PmPermission> permissions)
{
RoleName = roleName;
PmPermission = permissions;
GozareshgirRoleId = gozareshgirRolId;
}
public void Edit(string roleName, List<PmPermission> permissions)
{
RoleName = roleName;
PmPermission = permissions;
}
}

View File

@@ -1,19 +0,0 @@
using AccountManagement.Domain.PmDomains.PmUserAgg;
namespace AccountManagement.Domain.PmDomains.PmRoleUserAgg;
public class PmRoleUser
{
public PmRoleUser(long roleId)
{
RoleId = roleId;
}
public long Id { get; private set; }
public long RoleId { get; private set; }
public PmUser User { get; set; }
}

View File

@@ -1,22 +0,0 @@
using _0_Framework.Domain;
using AccountManagement.Application.Contracts.ProgramManager;
using System.Threading.Tasks;
using Shared.Contracts.PmUser.Queries;
namespace AccountManagement.Domain.PmDomains.PmUserAgg;
public interface IPmUserRepository : IRepository<long, PmUser>
{
/// <summary>
/// دریافت کاربر پروگرام منیجر جهتد ویرایش
/// </summary>
/// <param name="accountId"></param>
/// <returns></returns>
Task<PmUser?> GetByPmUsertoEditbyAccountId(long accountId);
/// <summary>
/// دریافت کرابر پروگرام منیجر با اکانت آی دی در گزارشگیر
/// </summary>
/// <param name="accountId"></param>
/// <returns></returns>
Task<GetPmUserDto> GetPmUserByAccountId(long accountId);
}

View File

@@ -1,127 +0,0 @@
using System;
using System.Collections.Generic;
using _0_Framework.Domain;
using AccountManagement.Domain.PmDomains.PmRoleUserAgg;
namespace AccountManagement.Domain.PmDomains.PmUserAgg;
/// <summary>
/// کاربر
/// </summary>
public class PmUser : EntityBase
{
/// <summary>
/// ایجاد
/// </summary>
/// <param name="fullName"></param>
/// <param name="userName"></param>
/// <param name="password"></param>
/// <param name="mobile"></param>
/// <param name="email"></param>
/// <param name="accountId"></param>
/// <param name="roles"></param>
public PmUser(string fullName, string userName, string password, string mobile, string email, long? accountId, List<PmRoleUser> roles)
{
FullName = fullName;
UserName = userName;
Password = password;
Mobile = mobile;
Email = email;
IsActive = true;
AccountId = accountId;
RoleUser = roles;
}
protected PmUser()
{
}
/// <summary>
/// نام و نام خانوادگی
/// </summary>
public string FullName { get; private set; }
/// <summary>
/// نام کاربری
/// </summary>
public string UserName { get; private set; }
/// <summary>
/// گذرواژه
/// </summary>
public string Password { get; private set; }
/// <summary>
/// مسیر عکس پروفایل
/// </summary>
public string ProfilePhotoPath { get; private set; }
/// <summary>
/// شماره موبایل
/// </summary>
public string Mobile { get; set; }
/// <summary>
/// ایمیل
/// </summary>
public string Email { get; private set; }
/// <summary>
/// فعال/غیر فعال بودن یوزر
/// </summary>
public bool IsActive { get; private set; }
/// <summary>
/// کد یکبارمصرف ورود
/// </summary>
public string VerifyCode { get; private set; }
/// <summary>
/// آی دی کاربر در گزارشگیر
/// </summary>
public long? AccountId { get; private set; }
/// <summary>
/// لیست پرمیشن کد ها
/// </summary>
public List<PmRoleUser> RoleUser { get; private set; }
/// <summary>
/// آپدیت کاربر
/// </summary>
/// <param name="fullName"></param>
/// <param name="userName"></param>
/// <param name="mobile"></param>
/// <param name="roles"></param>
/// <param name="isActive"></param>
public void Edit(string fullName, string userName, string mobile, List<PmRoleUser> roles, bool isActive)
{
FullName = fullName;
UserName = userName;
Mobile = mobile;
RoleUser = roles;
IsActive = isActive;
}
/// <summary>
/// غیرفعال سازی
/// </summary>
public void DeActive()
{
IsActive = false;
}
/// <summary>
/// فعال سازی
/// </summary>
public void ReActive()
{
IsActive = true;
}
}

View File

@@ -1,4 +1,4 @@
using AccountManagement.Domain.AccountAgg;
using AccountManagement.Domain.AccountAgg;
using AccountMangement.Infrastructure.EFCore.Mappings;
using Microsoft.EntityFrameworkCore;
using System;
@@ -26,7 +26,6 @@ using AccountManagement.Domain.SubAccountPermissionSubtitle2Agg;
using AccountManagement.Domain.SubAccountPermissionSubtitle3Agg;
using AccountManagement.Domain.SubAccountPermissionSubtitle4Agg;
using AccountManagement.Domain.SubAccountRoleAgg;
using AccountMangement.Infrastructure.EFCore.Seed;
using AccountManagement.Domain.TaskScheduleAgg;
namespace AccountMangement.Infrastructure.EFCore
@@ -60,9 +59,10 @@ namespace AccountMangement.Infrastructure.EFCore
public DbSet<TaskSchedule> TaskSchedules { get; set; }
#endregion
#region Pooya
public DbSet<SubAccount> SubAccounts { get; set; }
public DbSet<SubAccountRole> SubAccountRoles { get; set; }

View File

@@ -24,4 +24,8 @@
<Folder Include="Services\" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Mappings\BugReportMapping.cs" />
</ItemGroup>
</Project>

View File

@@ -1,24 +0,0 @@
using AccountManagement.Domain.PmDomains.PmRoleAgg;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace AccountMangement.Infrastructure.EFCore.Mappings.PmMappings;
public class PmRoleMapping : IEntityTypeConfiguration<PmRole>
{
public void Configure(EntityTypeBuilder<PmRole> builder)
{
builder.ToTable("PmRoles", t => t.ExcludeFromMigrations());
builder.HasKey(x => x.id);
builder.Property(x => x.RoleName).HasMaxLength(100).IsRequired();
builder.OwnsMany(x => x.PmPermission, navigationBuilder =>
{
navigationBuilder.HasKey(x => x.Id);
navigationBuilder.ToTable("PmRolePermissions", t => t.ExcludeFromMigrations());
navigationBuilder.WithOwner(x => x.Role);
});
}
}

View File

@@ -1,30 +0,0 @@
using AccountManagement.Domain.PmDomains.PmUserAgg;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace AccountMangement.Infrastructure.EFCore.Mappings.PmMappings;
public class PmUserMapping :IEntityTypeConfiguration<PmUser>
{
public void Configure(EntityTypeBuilder<PmUser> builder)
{
builder.ToTable("Users");
builder.HasKey(x => x.id);
builder.Property(x => x.FullName).HasMaxLength(100).IsRequired();
builder.Property(x => x.UserName).HasMaxLength(100).IsRequired();
builder.Property(x => x.Password).HasMaxLength(1000).IsRequired();
builder.Property(x => x.ProfilePhotoPath).HasMaxLength(500).IsRequired(false);
builder.Property(x => x.Mobile).HasMaxLength(20).IsRequired();
builder.Property(x => x.Email).HasMaxLength(150).IsRequired(false); ;
builder.Property(x => x.VerifyCode).HasMaxLength(10).IsRequired(false);
builder.OwnsMany(x => x.RoleUser, navigationBuilder =>
{
navigationBuilder.HasKey(x => x.Id);
navigationBuilder.ToTable("RoleUsers");
navigationBuilder.WithOwner(x => x.User);
});
}
}

View File

@@ -1,32 +0,0 @@
using AccountManagement.Domain.PmDomains.PmRoleAgg;
using AccountManagement.Domain.PmDomains.PmUserAgg;
using AccountMangement.Infrastructure.EFCore.Mappings;
using AccountMangement.Infrastructure.EFCore.Mappings.PmMappings;
using Microsoft.EntityFrameworkCore;
namespace AccountMangement.Infrastructure.EFCore.PmDbConetxt;
public class PmDbContext : DbContext
{
public PmDbContext(DbContextOptions<PmDbContext> options) : base(options)
{
}
public DbSet<PmUser> Users { get; set; } = null!;
public DbSet<PmRole> PmRoles { get; set; } = null!;
public PmDbContext()
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var assembly = typeof(PmUserMapping).Assembly;
modelBuilder.ApplyConfigurationsFromAssembly(assembly);
//SubAccountPermissionSeeder.Seed(modelBuilder);
base.OnModelCreating(modelBuilder);
}
}

View File

@@ -1,49 +0,0 @@
using _0_Framework.InfraStructure;
using AccountManagement.Application.Contracts.ProgramManager;
using AccountManagement.Domain.PmDomains.PmRoleAgg;
using AccountMangement.Infrastructure.EFCore.PmDbConetxt;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
namespace AccountMangement.Infrastructure.EFCore.Repository.PmRepositories;
public class PmRoleRepository : RepositoryBase<long, PmRole>, IPmRoleRepository
{
private readonly PmDbContext _pmDbContext;
public PmRoleRepository(PmDbContext context) : base(context)
{
_pmDbContext = context;
}
public async Task<List<GetPmRolesDto>> GetPmRoleList(long? gozareshgirRoleId)
{
var query = _pmDbContext.PmRoles.AsQueryable();
if (gozareshgirRoleId != null && gozareshgirRoleId > 0)
query = query.Where(x => x.GozareshgirRoleId == gozareshgirRoleId);
var res = await query
.Select(p => new GetPmRolesDto()
{
Id = p.id,
RoleName = p.RoleName,
GozareshgirRoleId = p.GozareshgirRoleId,
Permissions = p.PmPermission.Select(x => x.Code).ToList()
})
.ToListAsync();
return res;
}
public async Task<PmRole?> GetPmRoleToEdit(long gozareshgirRoleId)
{
return await _pmDbContext.PmRoles.FirstOrDefaultAsync(x => x.GozareshgirRoleId == gozareshgirRoleId);
}
}

View File

@@ -1,48 +0,0 @@
using _0_Framework.InfraStructure;
using AccountManagement.Application.Contracts.ProgramManager;
using AccountManagement.Domain.PmDomains.PmUserAgg;
using AccountMangement.Infrastructure.EFCore.PmDbConetxt;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Shared.Contracts.PmUser.Queries;
namespace AccountMangement.Infrastructure.EFCore.Repository.PmRepositories;
public class PmUserRepository :RepositoryBase<long, PmUser>, IPmUserRepository
{
private readonly PmDbContext _pmDbContext;
public PmUserRepository(PmDbContext context, PmDbContext pmDbContext) : base(context)
{
_pmDbContext = pmDbContext;
}
public async Task<PmUser?> GetByPmUsertoEditbyAccountId(long accountId)
{
return await _pmDbContext.Users.FirstOrDefaultAsync(x => x.AccountId == accountId);
}
public async Task<GetPmUserDto> GetPmUserByAccountId(long accountId)
{
var query = await _pmDbContext.Users.FirstOrDefaultAsync(x => x.AccountId == accountId);
if (query == null)
return new GetPmUserDto();
List<long> roles = query.RoleUser.Select(x => x.RoleId).ToList();
return new GetPmUserDto()
{
FullName = query.FullName,
UserName = query.UserName,
ProfilePhotoPath = query.ProfilePhotoPath,
Mobile = query.Mobile,
IsActive = query.IsActive,
AccountId = query.AccountId,
Roles = roles,
RoleListDto = await _pmDbContext.PmRoles.Where(x => roles.Contains(x.id)).Select(x => new RoleListDto()
{
RoleName = x.RoleName,
RoleId = x.id,
Permissions = x.PmPermission.Select(x => x.Code).ToList()
}).ToListAsync(),
};
}
}

175
BUG_REPORT_SYSTEM.md Normal file
View 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 قابل دسترس هستند
- حذف و ویرایش نیاز به تأیید دارد

View File

@@ -12,6 +12,7 @@
<ProjectReference Include="..\..\0_Framework\0_Framework.csproj" />
<ProjectReference Include="..\..\AccountManagement.Configuration\AccountManagement.Configuration.csproj" />
<ProjectReference Include="..\..\PersonalContractingParty.Config\PersonalContractingParty.Config.csproj" />
<ProjectReference Include="..\..\ProgramManager\src\Infrastructure\GozareshgirProgramManager.Infrastructure\GozareshgirProgramManager.Infrastructure.csproj" />
<ProjectReference Include="..\..\Query.Bootstrapper\Query.Bootstrapper.csproj" />
<ProjectReference Include="..\..\WorkFlow\Infrastructure\WorkFlow.Infrastructure.Config\WorkFlow.Infrastructure.Config.csproj" />
</ItemGroup>

View File

@@ -47,6 +47,11 @@ public class JobSchedulerRegistrator
() => SendBlockSms(),
"*/1 * * * *" // هر 1 دقیقه یکبار چک کن
);
RecurringJob.AddOrUpdate(
"InstitutionContract.SendInstitutionContractConfirmSms",
() => SendInstitutionContractConfirmSms(),
"*/1 * * * *" // هر 1 دقیقه یکبار چک کن
);
}
@@ -146,4 +151,15 @@ public class JobSchedulerRegistrator
await _institutionContractRepository.SendBlockSmsForBackgroundTask();
}
/// <summary>
/// ارسال پیامک یادآور تایید قراداد مالی
/// </summary>
/// <returns></returns>
[DisableConcurrentExecution(timeoutInSeconds: 100)]
public async System.Threading.Tasks.Task SendInstitutionContractConfirmSms()
{
await _institutionContractRepository.SendInstitutionContractConfirmSmsTask();
}
}

View File

@@ -7,11 +7,16 @@ using BackgroundInstitutionContract.Task;
using BackgroundInstitutionContract.Task.Jobs;
using CompanyManagment.App.Contracts.Hubs;
using CompanyManagment.EFCore.Services;
using GozareshgirProgramManager.Application._Bootstrapper;
using GozareshgirProgramManager.Application.Modules.Users.Commands.CreateUser;
using GozareshgirProgramManager.Infrastructure;
using GozareshgirProgramManager.Infrastructure.Persistence.Seed;
using Hangfire;
using Microsoft.AspNetCore.Identity;
using MongoDB.Driver;
using PersonalContractingParty.Config;
using Query.Bootstrapper;
using Shared.Contracts.PmUser.Queries;
using WorkFlow.Infrastructure.Config;
var builder = WebApplication.CreateBuilder(args);
@@ -38,10 +43,15 @@ builder.Services.AddSingleton<IMongoDatabase>(mongoDatabase);
#endregion
builder.Services.AddProgramManagerApplication();
builder.Services.AddProgramManagerInfrastructure(builder.Configuration);
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();

314
CHANGELOG.md Normal file
View 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 اجرا شده است

View File

@@ -0,0 +1,195 @@
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")]
[BsonRepresentation(MongoDB.Bson.BsonType.String)]
public CameraBugReportStatus Status { get; private set; }
[BsonElement("priority")]
[BsonRepresentation(MongoDB.Bson.BsonType.String)]
public CameraBugPriority Priority { get; private set; }
[BsonElement("type")]
[BsonRepresentation(MongoDB.Bson.BsonType.String)]
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 });
}
}

View 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; }
}
}

View File

@@ -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; }
}
}

View File

@@ -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);
}

View File

@@ -140,6 +140,11 @@ public interface IInstitutionContractRepository : IRepository<long, InstitutionC
/// <returns></returns>
Task SendReminderSmsToContractingParties(List<SmsListData> smsListData, string typeOfSms, string sendMessStart, string sendMessEnd);
/// <summary>
/// ارسال پیامک یادآور تایید قراداد مالی
/// </summary>
/// <returns></returns>
Task SendInstitutionContractConfirmSmsTask();
#endregion
#region CreateMontlyTransaction

View File

@@ -98,6 +98,11 @@ public class InstitutionContract : EntityBase
// مبلغ قرارداد
public double ContractAmount { get; private set; }
public double ContractAmountWithTax => !IsOldContract ? ContractAmount + ContractAmountTax
: ContractAmount;
public double ContractAmountTax => ContractAmount*0.10;
//خسارت روزانه
public double DailyCompenseation { get; private set; }
@@ -159,6 +164,10 @@ public class InstitutionContract : EntityBase
public List<InstitutionContractAmendment> Amendments { get; private set; }
public InstitutionContractSigningType? SigningType { get; private set; }
public bool IsOldContract => LawId== 0;
public InstitutionContract()
{
ContactInfoList = [];
@@ -262,6 +271,10 @@ public class InstitutionContract : EntityBase
{
WorkshopGroup = null;
}
public void SetSigningType(InstitutionContractSigningType signingType)
{
SigningType = signingType;
}
}
public class InstitutionContractAmendment : EntityBase

View File

@@ -10,13 +10,15 @@ public class InstitutionContractWorkshopCurrent:InstitutionContractWorkshopBase
public InstitutionContractWorkshopCurrent(string workshopName, bool hasRollCallPlan,
bool hasRollCallPlanInPerson, bool hasCustomizeCheckoutPlan, bool hasContractPlan,
bool hasContractPlanInPerson, bool hasInsurancePlan, bool hasInsurancePlanInPerson,
int personnelCount, double price,long institutionContractWorkshopGroupId,InstitutionContractWorkshopGroup workshopGroup,long workshopId) : base(workshopName, hasRollCallPlan,
int personnelCount, double price,long institutionContractWorkshopGroupId,
InstitutionContractWorkshopGroup workshopGroup,long workshopId,long initialWorkshopId) : base(workshopName, hasRollCallPlan,
hasRollCallPlanInPerson, hasCustomizeCheckoutPlan, hasContractPlan,
hasContractPlanInPerson, hasInsurancePlan, hasInsurancePlanInPerson, personnelCount, price)
{
InstitutionContractWorkshopGroupId = institutionContractWorkshopGroupId;
WorkshopGroup = workshopGroup;
WorkshopId = workshopId;
InitialWorkshopId = initialWorkshopId;
}
public long InstitutionContractWorkshopGroupId { get; private set; }
public InstitutionContractWorkshopGroup WorkshopGroup { get; private set; }

View File

@@ -37,4 +37,10 @@ public class InstitutionContractWorkshopGroup : EntityBase
CurrentWorkshops = updatedDetails.ToList();
LastModifiedDate = DateTime.Now;
}
public void AddCurrentWorkshop(InstitutionContractWorkshopCurrent currentWorkshop)
{
CurrentWorkshops.Add(currentWorkshop);
LastModifiedDate = DateTime.Now;
}
}

View File

@@ -31,7 +31,7 @@ public class InstitutionContractWorkshopInitial:InstitutionContractWorkshopBase
WorkshopCreated = true;
WorkshopCurrent = new InstitutionContractWorkshopCurrent(WorkshopName,Services.RollCall,Services.RollCallInPerson,
Services.CustomizeCheckout,Services.Contract,Services.ContractInPerson,Services.Insurance,
Services.InsuranceInPerson,PersonnelCount,Price,InstitutionContractWorkshopGroupId,WorkshopGroup,workshopId);
Services.InsuranceInPerson,PersonnelCount,Price,InstitutionContractWorkshopGroupId,WorkshopGroup,workshopId,id);
WorkshopCurrent.SetEmployers(Employers.Select(x=>x.EmployerId).ToList());
}

View File

@@ -73,6 +73,7 @@ public interface IInsuranceListRepository:IRepository<long, InsuranceList>
Task<InsuranceListConfirmOperation> GetInsuranceOperationDetails(long id);
Task<InsuranceListTabsCountViewModel> GetTabCounts(InsuranceListSearchModel searchModel);
Task<PagedResult<InsuranceClientListViewModel>> GetInsuranceClientList(InsuranceClientSearchModel searchModel);
#endregion

View File

@@ -316,7 +316,10 @@ public class Workshop : EntityBase
IsStaticCheckout = isStaticCheckout;
}
public void AddContractingPartyId(long contractingPartyId)
{
ContractingPartyId = contractingPartyId;
}
public void Active(string archiveCode)
{
this.IsActive = true;

View File

@@ -26,7 +26,7 @@ public class CustomizeWorkshopGroupSettingExcelGenerator
{
public static byte[] Generate(List<CustomizeWorkshopGroupExcelViewModel> groups)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using (var package = new ExcelPackage())
{
var worksheet = package.Workbook.Worksheets.Add("GroupsAndEmployees");

View File

@@ -24,7 +24,7 @@ public class CaseManagementExcelGenerator
};
public static byte[] GenerateCheckoutTempExcelInfo(List<FileExcelViewModel> data)
{
OfficeOpenXml.ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new ExcelPackage();
CreateSheet(data, package,"همه");
CreateSheet(data.Where(x=>x.Status ==2).ToList(), package,"فعال");

View File

@@ -46,7 +46,7 @@ public class CustomizeCheckoutExcelGenerator
};
public static byte[] GenerateCheckoutTempExcelInfo(List<CustomizeCheckoutTempExcelViewModel> data, List<string> selectedParameters)
{
OfficeOpenXml.ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add("Sheet1");

View File

@@ -7,7 +7,7 @@ public class EmployeeBankInfoExcelGenerator
{
public static byte[] Generate(List<EmployeeBankInfoExcelViewModel> list)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add("EmployeeBankInfo");
@@ -166,7 +166,7 @@ public class EmployeeBankInfoExcelGenerator
public static byte[] Generate2(List<EmployeeBankInfoExcelViewModel> list)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new ExcelPackage();
foreach (var employee in list)
{

View File

@@ -13,7 +13,7 @@ public class InstitutionContractExcelGenerator
public static byte[] GenerateExcel(List<InstitutionContractViewModel> institutionContractViewModels)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new ExcelPackage();
var allWorksheet = package.Workbook.Worksheets.Add("همه");

View File

@@ -8,7 +8,7 @@ public class RollCallExcelGenerator : ExcelGenerator
{
public static byte[] CaseHistoryExcelForEmployee(CaseHistoryRollCallExcelForEmployeeViewModel data)
{
OfficeOpenXml.ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new OfficeOpenXml.ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add("Sheet1");
var rollCalls = data.RollCalls;
@@ -181,7 +181,7 @@ public class RollCallExcelGenerator : ExcelGenerator
public static byte[] CaseHistoryExcelForOneDay(CaseHistoryRollCallForOneDayViewModel data)
{
OfficeOpenXml.ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
OfficeOpenXml.ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using var package = new OfficeOpenXml.ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add("Sheet1");
var rollCalls = data.RollCalls;

View File

@@ -43,7 +43,7 @@ public class SalaryAidImportExcel
ValidData = []
};
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
if (file == null || file.Length == 0)
{

View File

@@ -9,7 +9,7 @@ public class WorkshopRollCallExcelExporter
{
public static byte[] Export(List<WorkshopRollCallExcelViewModel> workshops)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelPackage.License.SetNonCommercialOrganization("Gozareshgir Noncommercial organization");
using (var package = new ExcelPackage())
{
var ws = package.Workbook.Worksheets.Add("Workshops");

View File

@@ -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 اعاملات را بصورت متفاوت مدیریت می‌کند");
}
}

View File

@@ -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; }
}
}

View File

@@ -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; }
}
}

View File

@@ -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; }
}
}

View File

@@ -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; }
}
}

View File

@@ -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, // دوربین کار نمی‌کند
}

View File

@@ -60,7 +60,7 @@ public interface IEmployeeApplication
/// <returns></returns>
Task<OperationResult<EmployeeByNationalCodeInWorkshopViewModel>>
ValidateCreateEmployeeClientByNationalCodeAndWorkshopId(string nationalCode,
string birthDate, long workshopId);
string birthDate,bool authorizedCanceled, long workshopId);
/// <summary>
/// پرسنل هایی که در کارگاهی از سمت ادمین شروع به کار کرده اند

View File

@@ -13,5 +13,6 @@ namespace CompanyManagment.App.Contracts.EmployeeDocuments
public string EmployerName { get; set; }
public List<EmployeeDocumentItemViewModel> SubmittedItems { get; set; }
public int EmployeesWithoutDocumentCount { get; set; }
public long EmployeeId { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
namespace CompanyManagment.App.Contracts.InstitutionContract;
public enum InstitutionContractSigningType
{
/// <summary>
/// قدیمی
/// </summary>
Legacy = 0,
/// <summary>
/// الکترونیکی با کد یکبار مصرف
/// </summary>
OtpBased = 1,
/// <summary>
/// به صورت فیزیکی
/// </summary>
Physical = 2
}

View File

@@ -7,7 +7,6 @@ using System.Threading.Tasks;
using _0_Framework.Application;
using _0_Framework.Application.Sms;
using CompanyManagment.App.Contracts.Checkout;
using CompanyManagment.App.Contracts.Law;
using CompanyManagment.App.Contracts.TemporaryClientRegistration;
using CompanyManagment.App.Contracts.Workshop;
using CompanyManagment.App.Contracts.WorkshopPlan;
@@ -260,154 +259,13 @@ public interface IInstitutionContractApplication
/// <returns></returns>
Task<InstitutionContractPrintViewModel> PrintOneAsync(long id);
Task<OperationResult> SetPendingWorkflow(long entityId);
Task<OperationResult> SetPendingWorkflow(long entityId,InstitutionContractSigningType signingType);
Task<long> GetIdByInstallmentId(long installmentId);
}
public class InstitutionContractDiscountResponse
{
public InstitutionContractDiscountOneTimeViewModel OneTime { get; set; }
public InstitutionContractDiscountMonthlyViewModel Monthly { get; set; }
}
public class InstitutionContractDiscountMonthlyViewModel:InstitutionContractDiscountOneTimeViewModel
{
public List<MonthlyInstallment> Installments { get; set; }
}
public class InstitutionContractDiscountOneTimeViewModel
{
/// <summary>
/// مجموع مبالغ
/// تایید قرارداد مالی به صورت دستی
/// </summary>
public string TotalAmount { get; set; }
/// <summary>
/// ارزش افزوده
/// </summary>
public string Tax { get; set; }
/// <summary>
/// مبلغ قابل پرداخت
/// </summary>
public string PaymentAmount { get; set; }
public string DiscountedAmount { get; set; }
public int DiscountPercetage { get; set; }
public string Obligation { get; set; }
public string OneMonthAmount { get; set; }
}
public class InstitutionContractResetDiscountForCreateRequest
{
public int DiscountPercentage { get; set; }
public double TotalAmount { get; set; }
public bool IsInstallment { get; set; }
public InstitutionContractDuration Duration { get; set; }
public double OneMonthAmount { get; set; }
}
public class InstitutionContractSetDiscountForExtensionRequest
{
public Guid TempId { get; set; }
public int DiscountPercentage { get; set; }
public double TotalAmount { get; set; }
public bool IsInstallment { get; set; }
}
public class InstitutionContractResetDiscountForExtensionRequest
{
public Guid TempId { get; set; }
public bool IsInstallment { get; set; }
}
public class InstitutionContractSetDiscountRequest
{
public int DiscountPercentage { get; set; }
public double TotalAmount { get; set; }
public InstitutionContractDuration Duration { get; set; }
public double OneMonthAmount { get; set; }
public bool IsInstallment { get; set; }
}
public class InstitutionContractPrintViewModel
{
public InstitutionContratVerificationParty FirstParty { get; set; }
public InstitutionContratVerificationParty SecondParty { get; set; }
public string ContractNo { get; set; }
public string CreationDate { get; set; }
public string ContractStart { get; set; }
public string ContractEnd { get; set; }
public List<GetInstitutionVerificationDetailsWorkshopsViewModel> Workshops { get; set; }
public string TotalPrice { get; set; }
public string TaxPrice { get; set; }
public string PaymentPrice { get; set; }
public string VerifyCode { get; set; }
public string VerifyDate { get; set; }
public string VerifyTime { get; set; }
public string VerifierFullName { get; set; }
public string VerifierPhoneNumber { get; set; }
public LawViewModel LawViewModel { get; set; }
public string Obligation { get; set; }
}
public class InsertAmendmentTempWorkshopResponse
{
public Guid WorkshopTempId { get; set; }
public string Amount { get; set; }
}
public class InstitutionContractAmendmentWorkshopsResponse
{
/// <summary>
///
/// </summary>
public List<InstitutionContractAmendmentTempWorkshopViewModel> Workshops { get; set; }
public Guid TempId { get; set; }
/// <param name="institutionContractId"></param>
/// <returns></returns>
Task<OperationResult> VerifyInstitutionContractManually(long institutionContractId);
}
public class InstitutionContractSelectListViewModel : SelectListViewModel;
public class InstitutionContractExtensionInquiryResponse
{
public long Id { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public string DateOfBirthFa { get; set; }
public string FatherName { get; set; }
public string IdNumberSerial { get; set; }
public string IdNumber { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string City { get; set; }
public string State { get; set; }
public long RepresentativeId { get; set; }
public string NationalCode { get; set; }
}
public class InstitutionContractExtensionPaymentMonthly:InstitutionContractExtensionPaymentOneTime
{
public List<MonthlyInstallment> Installments { get; set; }
}
public class InstitutionContractExtensionPaymentOneTime
{
/// <summary>
/// مجموع مبالغ
/// </summary>
public string TotalAmount { get; set; }
/// <summary>
/// ارزش افزوده
/// </summary>
public string Tax { get; set; }
/// <summary>
/// مبلغ قابل پرداخت
/// </summary>
public string PaymentAmount { get; set; }
}

View File

@@ -0,0 +1,9 @@
using System;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InsertAmendmentTempWorkshopResponse
{
public Guid WorkshopTempId { get; set; }
public string Amount { get; set; }
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractAmendmentWorkshopsResponse
{
/// <summary>
///
/// </summary>
public List<InstitutionContractAmendmentTempWorkshopViewModel> Workshops { get; set; }
public Guid TempId { get; set; }
}

View File

@@ -0,0 +1,38 @@
using System.Collections.Generic;
using CompanyManagment.App.Contracts.TemporaryClientRegistration;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractDiscountResponse
{
public InstitutionContractDiscountOneTimeViewModel OneTime { get; set; }
public InstitutionContractDiscountMonthlyViewModel Monthly { get; set; }
}
public class InstitutionContractDiscountMonthlyViewModel:InstitutionContractDiscountOneTimeViewModel
{
public List<MonthlyInstallment> Installments { get; set; }
}
public class InstitutionContractDiscountOneTimeViewModel
{
/// <summary>
/// مجموع مبالغ
/// </summary>
public string TotalAmount { get; set; }
/// <summary>
/// ارزش افزوده
/// </summary>
public string Tax { get; set; }
/// <summary>
/// مبلغ قابل پرداخت
/// </summary>
public string PaymentAmount { get; set; }
public string DiscountedAmount { get; set; }
public int DiscountPercetage { get; set; }
public string Obligation { get; set; }
public string OneMonthAmount { get; set; }
}

View File

@@ -0,0 +1,18 @@
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractExtensionInquiryResponse
{
public long Id { get; set; }
public string FName { get; set; }
public string LName { get; set; }
public string DateOfBirthFa { get; set; }
public string FatherName { get; set; }
public string IdNumberSerial { get; set; }
public string IdNumber { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string City { get; set; }
public string State { get; set; }
public long RepresentativeId { get; set; }
public string NationalCode { get; set; }
}

View File

@@ -0,0 +1,24 @@
using System.Collections.Generic;
using CompanyManagment.App.Contracts.TemporaryClientRegistration;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractExtensionPaymentMonthly:InstitutionContractExtensionPaymentOneTime
{
public List<MonthlyInstallment> Installments { get; set; }
}
public class InstitutionContractExtensionPaymentOneTime
{
/// <summary>
/// مجموع مبالغ
/// </summary>
public string TotalAmount { get; set; }
/// <summary>
/// ارزش افزوده
/// </summary>
public string Tax { get; set; }
/// <summary>
/// مبلغ قابل پرداخت
/// </summary>
public string PaymentAmount { get; set; }
}

View File

@@ -0,0 +1,28 @@
using System.Collections.Generic;
using CompanyManagment.App.Contracts.Law;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractPrintViewModel
{
public InstitutionContratVerificationParty FirstParty { get; set; }
public InstitutionContratVerificationParty SecondParty { get; set; }
public string ContractNo { get; set; }
public string CreationDate { get; set; }
public string ContractStart { get; set; }
public string ContractEnd { get; set; }
public List<GetInstitutionVerificationDetailsWorkshopsViewModel> Workshops { get; set; }
public string TotalPrice { get; set; }
public string TaxPrice { get; set; }
public string PaymentPrice { get; set; }
public string OneMonthPrice { get; set; }
public string VerifyCode { get; set; }
public string VerifyDate { get; set; }
public string VerifyTime { get; set; }
public string VerifierFullName { get; set; }
public string VerifierPhoneNumber { get; set; }
public LawViewModel LawViewModel { get; set; }
public string Obligation { get; set; }
public string OneMonthWithoutTax { get; set; }
public string OneMonthTax { get; set; }
}

View File

@@ -0,0 +1,10 @@
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractResetDiscountForCreateRequest
{
public int DiscountPercentage { get; set; }
public double TotalAmount { get; set; }
public bool IsInstallment { get; set; }
public InstitutionContractDuration Duration { get; set; }
public double OneMonthAmount { get; set; }
}

View File

@@ -0,0 +1,9 @@
using System;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractResetDiscountForExtensionRequest
{
public Guid TempId { get; set; }
public bool IsInstallment { get; set; }
}

View File

@@ -0,0 +1,5 @@
using _0_Framework.Application;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractSelectListViewModel : SelectListViewModel;

View File

@@ -0,0 +1,11 @@
using System;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractSetDiscountForExtensionRequest
{
public Guid TempId { get; set; }
public int DiscountPercentage { get; set; }
public double TotalAmount { get; set; }
public bool IsInstallment { get; set; }
}

View File

@@ -0,0 +1,10 @@
namespace CompanyManagment.App.Contracts.InstitutionContract;
public class InstitutionContractSetDiscountRequest
{
public int DiscountPercentage { get; set; }
public double TotalAmount { get; set; }
public InstitutionContractDuration Duration { get; set; }
public double OneMonthAmount { get; set; }
public bool IsInstallment { get; set; }
}

View File

@@ -0,0 +1,12 @@
using System;
namespace CompanyManagment.App.Contracts.InstitutionContract;
public record InstitutionCreationVerificationSmsDto
{
public string Number{ get; set; }
public string FullName { get; set; }
public Guid InstitutionId { get; set; }
public long ContractingPartyId { get; set; }
public long InstitutionContractId { get; set; }
};

View File

@@ -90,8 +90,27 @@ public interface IInsuranceListApplication
Task<InsuranceListConfirmOperation> GetInsuranceOperationDetails(long id);
Task<InsuranceListTabsCountViewModel> GetTabCounts(InsuranceListSearchModel searchModel);
Task<PagedResult<InsuranceClientListViewModel>> GetInsuranceClientList(InsuranceClientSearchModel searchModel);
#endregion
Task<List<InsuranceListViewModel>> GetNotCreatedWorkshop(InsuranceListSearchModel searchModel);
}
public class InsuranceClientSearchModel:PaginationRequest
{
public int Year { get; set; }
public int Month { get; set; }
public string Sorting { get; set; }
}
public class InsuranceClientListViewModel
{
public long Id { get; set; }
public string Year { get; set; }
public string Month { get; set; }
public long WorkShopId { get; set; }
public int YearInt { get; set; }
public string MonthName { get; set; }
public int MonthInt { get; set; }
}

View File

@@ -1,6 +1,7 @@
using _0_Framework.Application;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CompanyManagment.App.Contracts.RollCallEmployee;

View File

@@ -0,0 +1,292 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using _0_Framework.Application;
using CompanyManagment.App.Contracts.CameraBugReport;
using Company.Domain.CameraBugReportAgg;
namespace CompanyManagment.Application
{
public class CameraBugReportApplication : ICameraBugReportApplication
{
private readonly ICameraBugReportRepository _repository;
public CameraBugReportApplication(ICameraBugReportRepository repository)
{
_repository = repository;
}
// ============ Async Methods (MongoDB) ============
public async Task<OperationResult> CreateAsync(CreateCameraBugReportCommand command)
{
var op = new OperationResult();
try
{
var bugReport = new CameraBugReport(
command.Title,
command.Description,
command.UserEmail,
command.DeviceModel,
command.OsVersion,
command.Manufacturer,
command.BuildNumber,
command.AppVersion,
command.ScreenResolution,
command.IsCharging,
command.BatteryLevel,
command.StorageInMB,
command.MemoryInMB,
command.NetworkType,
command.Platform,
command.DeviceId,
command.PackageName,
command.InstallTime,
command.LastUpdateTime,
command.Flavor,
command.Type,
command.Priority,
command.AccountId,
command.StackTrace
);
// اضافه کردن لاگ‌ها
if (command.Logs != null && command.Logs.Any())
{
foreach (var log in command.Logs)
{
bugReport.AddLog(log);
}
}
// اضافه کردن تصاویر
if (command.Screenshots != null && command.Screenshots.Any())
{
foreach (var screenshot in command.Screenshots)
{
bugReport.AddScreenshot(screenshot, $"screenshot_{Guid.NewGuid()}.jpg");
}
}
await _repository.CreateAsync(bugReport);
return op.Succcedded();
}
catch (Exception ex)
{
return op.Failed($"خطا در ثبت گزارش خرابی: {ex.Message}");
}
}
public async Task<OperationResult> EditAsync(EditCameraBugReportCommand command)
{
var op = new OperationResult();
try
{
var bugReport = await _repository.GetByIdAsync(command.Id);
if (bugReport == null)
return op.Failed("گزارش خرابی یافت نشد.");
bugReport.ChangePriority(command.Priority);
bugReport.ChangeStatus(command.Status);
await _repository.UpdateAsync(bugReport);
return op.Succcedded();
}
catch (Exception ex)
{
return op.Failed($"خطا در ویرایش گزارش خرابی: {ex.Message}");
}
}
public async Task<OperationResult> DeleteAsync(Guid id)
{
var op = new OperationResult();
try
{
var exists = await _repository.IsExistAsync(id);
if (!exists)
return op.Failed("گزارش خرابی یافت نشد.");
await _repository.DeleteAsync(id);
return op.Succcedded();
}
catch (Exception ex)
{
return op.Failed($"خطا در حذف گزارش خرابی: {ex.Message}");
}
}
public async Task<List<CameraBugReportViewModel>> GetAllAsync(CameraBugReportSearchModel searchModel)
{
try
{
var skip = (searchModel.PageNumber - 1) * searchModel.PageSize;
var bugReports = await _repository.FilterAsync(
searchModel.Type,
searchModel.Priority,
searchModel.Status,
searchModel.SearchTerm,
skip,
searchModel.PageSize
);
return bugReports.Select(x => new CameraBugReportViewModel
{
Id = x.Id,
Title = x.Title,
Description = x.Description,
UserEmail = x.UserEmail,
AccountId = x.AccountId,
DeviceModel = x.DeviceModel,
AppVersion = x.AppVersion,
Type = x.Type,
Priority = x.Priority,
Status = x.Status,
CreationDate = x.CreationDate,
UpdateDate = x.UpdateDate,
LogsCount = x.Logs?.Count ?? 0,
ScreenshotsCount = x.Screenshots?.Count ?? 0
}).ToList();
}
catch (Exception ex)
{
throw new Exception($"خطا در دریافت لیست گزارش‌ها: {ex.Message}", ex);
}
}
public async Task<CameraBugReportDetailViewModel> GetDetailsAsync(Guid id)
{
try
{
var bugReport = await _repository.GetByIdAsync(id);
if (bugReport == null)
return null;
return new CameraBugReportDetailViewModel
{
Id = bugReport.Id,
Title = bugReport.Title,
Description = bugReport.Description,
UserEmail = bugReport.UserEmail,
AccountId = bugReport.AccountId,
DeviceModel = bugReport.DeviceModel,
OsVersion = bugReport.OsVersion,
Platform = bugReport.Platform,
Manufacturer = bugReport.Manufacturer,
DeviceId = bugReport.DeviceId,
ScreenResolution = bugReport.ScreenResolution,
MemoryInMB = bugReport.MemoryInMB,
StorageInMB = bugReport.StorageInMB,
BatteryLevel = bugReport.BatteryLevel,
IsCharging = bugReport.IsCharging,
NetworkType = bugReport.NetworkType,
AppVersion = bugReport.AppVersion,
BuildNumber = bugReport.BuildNumber,
PackageName = bugReport.PackageName,
InstallTime = bugReport.InstallTime,
LastUpdateTime = bugReport.LastUpdateTime,
Flavor = bugReport.Flavor,
Type = bugReport.Type,
Priority = bugReport.Priority,
Status = bugReport.Status,
StackTrace = bugReport.StackTrace,
CreationDate = bugReport.CreationDate,
UpdateDate = bugReport.UpdateDate,
Logs = bugReport.Logs?.Select(x => x.Message).ToList() ?? new List<string>(),
Screenshots = bugReport.Screenshots?.Select(x => new CameraBugReportScreenshotViewModel
{
FileName = x.FileName,
UploadDate = x.UploadDate,
Base64Data = x.Base64Data
}).ToList() ?? new List<CameraBugReportScreenshotViewModel>()
};
}
catch (Exception ex)
{
throw new Exception($"خطا در دریافت جزئیات گزارش: {ex.Message}", ex);
}
}
public async Task<bool> IsExistAsync(Guid id)
{
return await _repository.IsExistAsync(id);
}
// ============ Sync Methods (Backward Compatibility) ============
public OperationResult Create(CreateCameraBugReportCommand command)
{
try
{
return CreateAsync(command).ConfigureAwait(false).GetAwaiter().GetResult();
}
catch (Exception ex)
{
return new OperationResult().Failed($"خطا: {ex.Message}");
}
}
public OperationResult Edit(EditCameraBugReportCommand command)
{
try
{
return EditAsync(command).ConfigureAwait(false).GetAwaiter().GetResult();
}
catch (Exception ex)
{
return new OperationResult().Failed($"خطا: {ex.Message}");
}
}
public OperationResult Delete(Guid id)
{
try
{
return DeleteAsync(id).ConfigureAwait(false).GetAwaiter().GetResult();
}
catch (Exception ex)
{
return new OperationResult().Failed($"خطا: {ex.Message}");
}
}
public List<CameraBugReportViewModel> GetAll(CameraBugReportSearchModel searchModel)
{
try
{
return GetAllAsync(searchModel).ConfigureAwait(false).GetAwaiter().GetResult();
}
catch (Exception ex)
{
throw new Exception($"خطا: {ex.Message}", ex);
}
}
public CameraBugReportDetailViewModel GetDetails(Guid id)
{
try
{
return GetDetailsAsync(id).ConfigureAwait(false).GetAwaiter().GetResult();
}
catch (Exception ex)
{
throw new Exception($"خطا: {ex.Message}", ex);
}
}
public bool IsExist(Guid id)
{
try
{
return IsExistAsync(id).ConfigureAwait(false).GetAwaiter().GetResult();
}
catch (Exception ex)
{
throw new Exception($"خطا: {ex.Message}", ex);
}
}
}
}

View File

@@ -1263,7 +1263,7 @@ public class EmployeeAplication : RepositoryBase<long, Employee>, IEmployeeAppli
System.IO.File.WriteAllBytes(filePath, bytes);
}
public async Task<OperationResult<EmployeeByNationalCodeInWorkshopViewModel>>
ValidateCreateEmployeeClientByNationalCodeAndWorkshopId(string nationalCode, string birthDate, long workshopId)
ValidateCreateEmployeeClientByNationalCodeAndWorkshopId(string nationalCode, string birthDate,bool authorizedCanceled, long workshopId)
{
var op = new OperationResult<EmployeeByNationalCodeInWorkshopViewModel>();
@@ -1279,10 +1279,11 @@ public class EmployeeAplication : RepositoryBase<long, Employee>, IEmployeeAppli
var employee = _EmployeeRepository.GetByNationalCodeIgnoreQueryFilter(nationalCode);
if (employee == null)
if (employee == null && !authorizedCanceled)
{
var personalInfo = await _uidService.GetPersonalInfo(nationalCode, birthDate);
if (personalInfo != null)
{
if (personalInfo.ResponseContext.Status.Code == 14)
{
return op.Failed("سامانه احراز هویت در دسترس نمیباشد لطفا اطلاعات پرسنل را به صورت دستی وارد کنید", new EmployeeByNationalCodeInWorkshopViewModel() { AuthorizedCanceled = true });
@@ -1322,6 +1323,19 @@ public class EmployeeAplication : RepositoryBase<long, Employee>, IEmployeeAppli
EmployeeLName = newEmployee.LName
});
}
else
{
return op.Failed("سامانه احراز هویت در دسترس نمیباشد لطفا اطلاعات پرسنل را به صورت دستی وارد کنید", new EmployeeByNationalCodeInWorkshopViewModel() { AuthorizedCanceled = true });
}
}
else if (employee == null && authorizedCanceled)
{
return op.Succcedded(new EmployeeByNationalCodeInWorkshopViewModel());
}
if (_leftWorkTempRepository.ExistsIgnoreQueryFilter(x =>
x.EmployeeId == employee.id && x.WorkshopId == workshopId && x.LeftWorkType == LeftWorkTempType.StartWork))
@@ -1329,9 +1343,12 @@ public class EmployeeAplication : RepositoryBase<long, Employee>, IEmployeeAppli
return op.Failed("این پرسنل در کارگاه شما قبلا افزوده شده است و در انتظار تایید میباشد");
}
var personalInfoResponse = await _uidService.GetPersonalInfo(nationalCode, birthDate);
if (personalInfoResponse != null)
{
if (employee.IsAuthorized == false)
{
var personalInfoResponse = await _uidService.GetPersonalInfo(nationalCode, birthDate);
if (personalInfoResponse.ResponseContext.Status.Code == 0)
{
@@ -1373,6 +1390,8 @@ public class EmployeeAplication : RepositoryBase<long, Employee>, IEmployeeAppli
{
return op.Failed("کد ملی با تاریخ تولد وارد شده مطابقت ندارد");
}
}
var leftWorkViewModel = _leftWorkRepository.GetLastLeftWorkByEmployeeIdAndWorkshopId(workshopId, employee.id);
if (leftWorkViewModel == null)

View File

@@ -1537,7 +1537,7 @@ public class InstitutionContractApplication : IInstitutionContractApplication
return (await _institutionContractRepository.PrintAllAsync([id])).FirstOrDefault();
}
public async Task<OperationResult> SetPendingWorkflow(long entityId)
public async Task<OperationResult> SetPendingWorkflow(long entityId,InstitutionContractSigningType signingType)
{
var op = new OperationResult();
var institutionContract = await _institutionContractRepository.GetIncludeWorkshopDetailsAsync(entityId);
@@ -1551,6 +1551,30 @@ public class InstitutionContractApplication : IInstitutionContractApplication
return op.Failed("وضعیت قرارداد مالی برای این عملیات مناسب نمی باشد");
}
var initialCreatedWorkshops = institutionContract.WorkshopGroup.InitialWorkshops
.Where(x => x.WorkshopCreated && x.WorkshopId is > 0).ToList();
var currentWorkshops = institutionContract.WorkshopGroup.CurrentWorkshops.ToList();
foreach (var createdWorkshop in initialCreatedWorkshops)
{
if (currentWorkshops.Any(x => x.WorkshopId == createdWorkshop.WorkshopId))
{
continue;
}
var currentWorkshop = new InstitutionContractWorkshopCurrent(createdWorkshop.WorkshopName,
createdWorkshop.Services.RollCall, createdWorkshop.Services.RollCallInPerson,
createdWorkshop.Services.CustomizeCheckout, createdWorkshop.Services.Contract,
createdWorkshop.Services.ContractInPerson, createdWorkshop.Services.Insurance,
createdWorkshop.Services.InsuranceInPerson,createdWorkshop.PersonnelCount, createdWorkshop.Price,
createdWorkshop.InstitutionContractWorkshopGroupId,createdWorkshop.WorkshopGroup,
createdWorkshop.WorkshopId!.Value, createdWorkshop.id);
institutionContract.WorkshopGroup.AddCurrentWorkshop(currentWorkshop);
}
if (institutionContract.WorkshopGroup.InitialWorkshops.All(x => x.WorkshopCreated && x.WorkshopId is > 0))
{
institutionContract.Verified();
@@ -1560,6 +1584,8 @@ public class InstitutionContractApplication : IInstitutionContractApplication
institutionContract.SetPendingWorkflow();
}
institutionContract.SetSigningType(signingType);
await _institutionContractRepository.SaveChangesAsync();
return op.Succcedded();
}
@@ -1569,6 +1595,28 @@ public class InstitutionContractApplication : IInstitutionContractApplication
return await _institutionContractRepository.GetIdByInstallmentId(installmentId);
}
public async Task<OperationResult> VerifyInstitutionContractManually(long institutionContractId)
{
var op = new OperationResult();
var institutionContract =await _institutionContractRepository
.GetIncludeWorkshopDetailsAsync(institutionContractId);
if (institutionContract == null)
return op.Failed("قرارداد مالی یافت نشد");
if (institutionContract.VerificationStatus == InstitutionContractVerificationStatus.Verified)
return op.Failed("قرارداد مالی قبلا تایید شده است");
var transaction = await _institutionContractRepository.BeginTransactionAsync();
await SetPendingWorkflow(institutionContractId,InstitutionContractSigningType.Physical);
await transaction.CommitAsync();
await _institutionContractRepository.SaveChangesAsync();
return op.Succcedded();
}
private async Task<OperationResult<PersonalContractingParty>> CreateLegalContractingPartyEntity(
CreateInstitutionContractLegalPartyRequest request, long representativeId, string address, string city,
string state)

View File

@@ -2371,6 +2371,11 @@ public class InsuranceListApplication : IInsuranceListApplication
return _insuranceListRepositpry.GetTabCounts(searchModel);
}
public async Task<PagedResult<InsuranceClientListViewModel>> GetInsuranceClientList(InsuranceClientSearchModel searchModel)
{
return await _insuranceListRepositpry.GetInsuranceClientList(searchModel);
}
public async Task<List<InsuranceListViewModel>> GetNotCreatedWorkshop(InsuranceListSearchModel searchModel)
{
return await _insuranceListRepositpry.GetNotCreatedWorkshop(searchModel);

View File

@@ -384,6 +384,7 @@ public class RollCallApplication : IRollCallApplication
var workshopSettings = _customizeWorkshopSettingsRepository.GetBy(command.WorkshopId);
var employeeSettings =
_customizeWorkshopEmployeeSettingsRepository.GetByEmployeeIdAndWorkshopIdIncludeGroupSettings(
command.WorkshopId, command.EmployeeId)?.WorkshopShiftStatus;

View File

@@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Transactions;
using _0_Framework.Application.FaceEmbedding;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
namespace CompanyManagment.Application;
@@ -23,7 +24,9 @@ public class RollCallEmployeeApplication : IRollCallEmployeeApplication
private readonly ILeftWorkRepository _leftWorkRepository;
private readonly IRollCallEmployeeStatusRepository _rollCallEmployeeStatusRepository;
private readonly IWebHostEnvironment _webHostEnvironment;
public RollCallEmployeeApplication(IRollCallEmployeeRepository rollCallEmployeeRepository, IEmployeeRepository employeeRepository, IRollCallEmployeeStatusApplication rollCallEmployeeStatusApplication, ILeftWorkRepository leftWorkRepository, IRollCallEmployeeStatusRepository rollCallEmployeeStatusRepository, IWebHostEnvironment webHostEnvironment)
private readonly IFaceEmbeddingService _faceEmbeddingService;
public RollCallEmployeeApplication(IRollCallEmployeeRepository rollCallEmployeeRepository, IEmployeeRepository employeeRepository, IRollCallEmployeeStatusApplication rollCallEmployeeStatusApplication, ILeftWorkRepository leftWorkRepository, IRollCallEmployeeStatusRepository rollCallEmployeeStatusRepository, IWebHostEnvironment webHostEnvironment, IFaceEmbeddingService faceEmbeddingService)
{
_rollCallEmployeeRepository = rollCallEmployeeRepository;
_employeeRepository = employeeRepository;
@@ -31,6 +34,7 @@ public class RollCallEmployeeApplication : IRollCallEmployeeApplication
_leftWorkRepository = leftWorkRepository;
_rollCallEmployeeStatusRepository = rollCallEmployeeStatusRepository;
_webHostEnvironment = webHostEnvironment;
_faceEmbeddingService = faceEmbeddingService;
}
public OperationResult Create(CreateRollCallEmployee command)
@@ -213,9 +217,18 @@ public class RollCallEmployeeApplication : IRollCallEmployeeApplication
if (entity.IsActiveString != "true")
return result.Failed("امکان تغییر نام برای کارمند غیر فعال وجود ندارد");
var transaction = _rollCallEmployeeRepository.BeginTransactionAsync().GetAwaiter().GetResult();
entity.ChangeName(fName, lName);
_rollCallEmployeeRepository.SaveChanges();
var embeddingRes =_faceEmbeddingService
.UpdateEmbeddingFullNameAsync(entity.EmployeeId, entity.WorkshopId, fullName)
.GetAwaiter().GetResult();
if (!embeddingRes.IsSuccedded)
return result.Failed("خطا در به روز رسانی نام در سیستم تشخیص چهره: " + embeddingRes.Message);
transaction.Commit();
return result.Succcedded();
}
#endregion

View File

@@ -118,6 +118,7 @@ using Company.Domain.WorkshopSubAccountAgg;
using Company.Domain.YearlySalaryAgg;
using Company.Domain.YearlySalaryItemsAgg;
using Company.Domain.YearlysSalaryTitleAgg;
using Company.Domain.CameraBugReportAgg;
using CompanyManagment.EFCore.Mapping;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
@@ -323,6 +324,11 @@ public class CompanyContext : DbContext
public DbSet<Employer> Employers { get; set; }
#region BugReport
public DbSet<CameraBugReport> CameraBugReports { get; set; }
public DbSet<CameraBugReportLog> CameraBugReportLogs { get; set; }
public DbSet<CameraBugReportScreenshot> CameraBugReportScreenshots { get; set; }
#endregion
public CompanyContext(DbContextOptions<CompanyContext> options) :base(options)
{

View File

@@ -35,6 +35,10 @@ public class InstitutionContractMapping : IEntityTypeConfiguration<InstitutionCo
builder.Property(x => x.VerificationStatus).HasConversion<string>().HasMaxLength(122);
builder.Property(x=>x.SigningType).HasConversion<string>()
.HasMaxLength(25)
.IsRequired(false);
builder.HasMany(x => x.Installments)
.WithOne(x => x.InstitutionContract)
.HasForeignKey(x => x.InstitutionContractId);
@@ -45,5 +49,10 @@ public class InstitutionContractMapping : IEntityTypeConfiguration<InstitutionCo
builder.HasMany(x => x.Amendments).WithOne(x => x.InstitutionContract)
.HasForeignKey(x => x.InstitutionContractId);
builder.Ignore(x => x.ContractAmountWithTax);
builder.Ignore(x => x.ContractAmountTax);
builder.Ignore(x => x.ContractAmountTax);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace CompanyManagment.EFCore.Migrations
{
/// <inheritdoc />
public partial class testmig : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

View File

@@ -0,0 +1,29 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace CompanyManagment.EFCore.Migrations
{
/// <inheritdoc />
public partial class addsigningTypeforinstitutioncontract : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "SigningType",
table: "InstitutionContracts",
type: "nvarchar(25)",
maxLength: 25,
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "SigningType",
table: "InstitutionContracts");
}
}
}

View File

@@ -18,7 +18,7 @@ namespace CompanyManagment.EFCore.Migrations
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "8.0.10")
.HasAnnotation("ProductVersion", "10.0.1")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
@@ -308,6 +308,155 @@ namespace CompanyManagment.EFCore.Migrations
b.ToTable("BoardTypes", (string)null);
});
modelBuilder.Entity("Company.Domain.CameraBugReportAgg.CameraBugReport", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uniqueidentifier");
b.Property<long?>("AccountId")
.HasColumnType("bigint");
b.Property<string>("AppVersion")
.HasColumnType("nvarchar(max)");
b.Property<int>("BatteryLevel")
.HasColumnType("int");
b.Property<string>("BuildNumber")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("DeviceId")
.HasColumnType("nvarchar(max)");
b.Property<string>("DeviceModel")
.HasColumnType("nvarchar(max)");
b.Property<string>("Flavor")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("InstallTime")
.HasColumnType("datetime2");
b.Property<bool>("IsCharging")
.HasColumnType("bit");
b.Property<DateTime>("LastUpdateTime")
.HasColumnType("datetime2");
b.Property<string>("Manufacturer")
.HasColumnType("nvarchar(max)");
b.Property<int>("MemoryInMB")
.HasColumnType("int");
b.Property<string>("NetworkType")
.HasColumnType("nvarchar(max)");
b.Property<string>("OsVersion")
.HasColumnType("nvarchar(max)");
b.Property<string>("PackageName")
.HasColumnType("nvarchar(max)");
b.Property<string>("Platform")
.HasColumnType("nvarchar(max)");
b.Property<int>("Priority")
.HasColumnType("int");
b.Property<string>("ScreenResolution")
.HasColumnType("nvarchar(max)");
b.Property<string>("StackTrace")
.HasColumnType("nvarchar(max)");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<int>("StorageInMB")
.HasColumnType("int");
b.Property<string>("Title")
.HasColumnType("nvarchar(max)");
b.Property<int>("Type")
.HasColumnType("int");
b.Property<DateTime?>("UpdateDate")
.HasColumnType("datetime2");
b.Property<string>("UserEmail")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("CameraBugReports");
});
modelBuilder.Entity("Company.Domain.CameraBugReportAgg.CameraBugReportLog", b =>
{
b.Property<long>("id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("id"));
b.Property<Guid?>("CameraBugReportId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Message")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("Timestamp")
.HasColumnType("datetime2");
b.HasKey("id");
b.HasIndex("CameraBugReportId");
b.ToTable("CameraBugReportLogs");
});
modelBuilder.Entity("Company.Domain.CameraBugReportAgg.CameraBugReportScreenshot", b =>
{
b.Property<long>("id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("id"));
b.Property<string>("Base64Data")
.HasColumnType("nvarchar(max)");
b.Property<Guid?>("CameraBugReportId")
.HasColumnType("uniqueidentifier");
b.Property<DateTime>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("FileName")
.HasColumnType("nvarchar(max)");
b.Property<DateTime>("UploadDate")
.HasColumnType("datetime2");
b.HasKey("id");
b.HasIndex("CameraBugReportId");
b.ToTable("CameraBugReportScreenshots");
});
modelBuilder.Entity("Company.Domain.ChapterAgg.EntityChapter", b =>
{
b.Property<long>("id")
@@ -3313,6 +3462,10 @@ namespace CompanyManagment.EFCore.Migrations
.HasMaxLength(1)
.HasColumnType("nvarchar(1)");
b.Property<string>("SigningType")
.HasMaxLength(25)
.HasColumnType("nvarchar(25)");
b.Property<string>("State")
.HasMaxLength(20)
.HasColumnType("nvarchar(20)");
@@ -4007,7 +4160,7 @@ namespace CompanyManagment.EFCore.Migrations
.HasMaxLength(4)
.HasColumnType("nvarchar(4)");
b.ComplexProperty<Dictionary<string, object>>("Debt", "Company.Domain.InsuranceListAgg.InsuranceList.Debt#InsuranceListDebt", b1 =>
b.ComplexProperty(typeof(Dictionary<string, object>), "Debt", "Company.Domain.InsuranceListAgg.InsuranceList.Debt#InsuranceListDebt", b1 =>
{
b1.IsRequired();
@@ -4029,7 +4182,7 @@ namespace CompanyManagment.EFCore.Migrations
.HasColumnType("nvarchar(50)");
});
b.ComplexProperty<Dictionary<string, object>>("EmployerApproval", "Company.Domain.InsuranceListAgg.InsuranceList.EmployerApproval#InsuranceListEmployerApproval", b1 =>
b.ComplexProperty(typeof(Dictionary<string, object>), "EmployerApproval", "Company.Domain.InsuranceListAgg.InsuranceList.EmployerApproval#InsuranceListEmployerApproval", b1 =>
{
b1.IsRequired();
@@ -4046,7 +4199,7 @@ namespace CompanyManagment.EFCore.Migrations
.HasColumnType("nvarchar(50)");
});
b.ComplexProperty<Dictionary<string, object>>("Inspection", "Company.Domain.InsuranceListAgg.InsuranceList.Inspection#InsuranceListInspection", b1 =>
b.ComplexProperty(typeof(Dictionary<string, object>), "Inspection", "Company.Domain.InsuranceListAgg.InsuranceList.Inspection#InsuranceListInspection", b1 =>
{
b1.IsRequired();
@@ -7157,6 +7310,20 @@ namespace CompanyManagment.EFCore.Migrations
b.Navigation("File1");
});
modelBuilder.Entity("Company.Domain.CameraBugReportAgg.CameraBugReportLog", b =>
{
b.HasOne("Company.Domain.CameraBugReportAgg.CameraBugReport", null)
.WithMany("Logs")
.HasForeignKey("CameraBugReportId");
});
modelBuilder.Entity("Company.Domain.CameraBugReportAgg.CameraBugReportScreenshot", b =>
{
b.HasOne("Company.Domain.CameraBugReportAgg.CameraBugReport", null)
.WithMany("Screenshots")
.HasForeignKey("CameraBugReportId");
});
modelBuilder.Entity("Company.Domain.ChapterAgg.EntityChapter", b =>
{
b.HasOne("Company.Domain.SubtitleAgg.EntitySubtitle", "EntitySubtitle")
@@ -10998,6 +11165,13 @@ namespace CompanyManagment.EFCore.Migrations
b.Navigation("PetitionsList");
});
modelBuilder.Entity("Company.Domain.CameraBugReportAgg.CameraBugReport", b =>
{
b.Navigation("Logs");
b.Navigation("Screenshots");
});
modelBuilder.Entity("Company.Domain.CheckoutAgg.Checkout", b =>
{
b.Navigation("CheckoutWarningMessageList");

View File

@@ -64,7 +64,7 @@ public class CheckoutRepository : RepositoryBase<long, Checkout>, ICheckoutRepos
}
/// <summary>
/// چیک میکند که آیا پرسنل در سال و ماه درخواستی در این کارگاه فیش حقوقی دارد یا خیر
/// چک میکند که آیا پرسنل در سال و ماه درخواستی در این کارگاه فیش حقوقی دارد یا خیر
/// </summary>
/// <param name="workshopId"></param>
/// <param name="employeId"></param>
@@ -79,7 +79,16 @@ public class CheckoutRepository : RepositoryBase<long, Checkout>, ICheckoutRepos
x.WorkshopId == workshopId && x.EmployeeId == employeId && x.Year == year && x.Month == farisMonthName &&
x.IsActiveString == "true");
if (res == null)
{
var checkLeftDate = ($"{year}/{month}/01").ToGeorgianDateTime();
var hasLeftwork = _context.LeftWorkList.Any(x =>
x.EmployeeId == employeId && x.WorkshopId == workshopId && x.LeftWorkDate == checkLeftDate);
if(hasLeftwork)
return (true, 0, 0, 0, 0, 0, 0);
return (false, 0, 0, 0, 0, 0, 0);
}
return (true, res.FamilyAllowance, res.OvertimePay, res.ShiftPay, res.NightworkPay, res.FridayPay,res.YearsPay);
}

View File

@@ -1194,41 +1194,99 @@ public class EmployeeDocumentsRepository : RepositoryBase<long, EmployeeDocument
{
return new List<WorkshopWithEmployeeDocumentsViewModel>();
}
var employeeClientTemp = _companyContext.EmployeeClientTemps.Where(x => workshops.Contains(x.WorkshopId));
var query = _companyContext.EmployeeDocuments
.Where(x => workshops.Contains(x.WorkshopId) &&
employeeClientTemp.Any(temp => x.EmployeeId == temp.EmployeeId && temp.WorkshopId == x.WorkshopId) && x.IsConfirmed == false &&x.IsSentToChecker == false)
.Include(x => x.Workshop).Include(x => x.EmployeeDocumentItemCollection)
.GroupBy(x => x.WorkshopId).Select(x => new WorkshopWithEmployeeDocumentsViewModel()
// Step 1: Get employee client temps in memory
var employeeClientTempData = await _companyContext.EmployeeClientTemps
.Where(x => workshops.Contains(x.WorkshopId))
.Select(x => new { x.WorkshopId, x.EmployeeId })
.ToListAsync();
// Step 2: Get employee documents with simplified filter
var employeeDocuments = await _companyContext.EmployeeDocuments
.Where(x => workshops.Contains(x.WorkshopId) && !x.IsConfirmed && !x.IsSentToChecker)
.Select(x => new
{
WorkshopId = x.Key,
WorkshopFullName = x.FirstOrDefault().Workshop.WorkshopFullName,
EmployeesWithoutDocumentCount = x.Count()
});
x.id,
x.WorkshopId,
x.EmployeeId,
x.IsConfirmed,
x.IsSentToChecker,
WorkshopName = x.Workshop.WorkshopName
})
.ToListAsync();
var workshopEmployers = await _companyContext.WorkshopEmployers.Include(x => x.Employer)
.Where(x => query.Any(y => y.WorkshopId == x.WorkshopId))
.GroupBy(x => x.WorkshopId).Select(x => x.FirstOrDefault()).ToListAsync();
var result = await query.ToListAsync();
result.ForEach(x =>
var filteredDocuments = employeeDocuments
.Where(x => employeeClientTempData.Any(temp =>
temp.WorkshopId == x.WorkshopId && temp.EmployeeId == x.EmployeeId))
.ToList();
var groupedByWorkshop = filteredDocuments
.GroupBy(x => x.WorkshopId)
.Select(g => new
{
var employer = workshopEmployers.FirstOrDefault(y => y.WorkshopId == x.WorkshopId)?.Employer;
x.EmployerName = employer?.FullName;
WorkshopId = g.Key,
WorkshopName = g.First().WorkshopName,
Count = g.Count()
})
.ToList();
//x.SubmittedItems.ForEach(y=>y.PicturePath= medias.FirstOrDefault(z=>z.id == y.MediaId)?.Path ?? "");
});
// Step 5: Get workshop employers for the filtered workshops
var workshopIds = groupedByWorkshop.Select(x => x.WorkshopId).ToList();
var workshopEmployers = await _companyContext.WorkshopEmployers
.Where(x => workshopIds.Contains(x.WorkshopId))
.Include(x => x.Employer)
.GroupBy(x => x.WorkshopId)
.Select(g => g.FirstOrDefault())
.ToListAsync();
return result.Where(x => x.EmployeesWithoutDocumentCount > 0).OrderByDescending(x => x.EmployeesWithoutDocumentCount).ToList();
// Step 6: Build result
var res = groupedByWorkshop
.Select(x => new WorkshopWithEmployeeDocumentsViewModel()
{
WorkshopId = x.WorkshopId,
WorkshopFullName = x.WorkshopName,
EmployeesWithoutDocumentCount = x.Count,
EmployerName = workshopEmployers
.FirstOrDefault(y => y.WorkshopId == x.WorkshopId)?
.Employer?.FullName
})
.Where(x => x.EmployeesWithoutDocumentCount > 0)
.OrderByDescending(x => x.EmployeesWithoutDocumentCount)
.ToList();
return res;
//var employeeClientTemp = _companyContext.EmployeeClientTemps.Where(x => workshops.Contains(x.WorkshopId));
// var query = _companyContext.EmployeeDocuments
// .Where(x => workshops.Contains(x.WorkshopId) &&
// employeeClientTemp.Any(temp => x.EmployeeId == temp.EmployeeId && temp.WorkshopId == x.WorkshopId) && x.IsConfirmed == false &&x.IsSentToChecker == false)
// .Include(x => x.Workshop).Include(x => x.EmployeeDocumentItemCollection)
// .GroupBy(x => x.WorkshopId).Select(x => new WorkshopWithEmployeeDocumentsViewModel()
// {
// WorkshopId = x.Key,
// WorkshopFullName = x.FirstOrDefault().Workshop.WorkshopFullName,
// EmployeesWithoutDocumentCount = x.Count()
// });
// var workshopEmployers = await _companyContext.WorkshopEmployers.Include(x => x.Employer)
// .Where(x => query.Any(y => y.WorkshopId == x.WorkshopId))
// .GroupBy(x => x.WorkshopId).Select(x => x.FirstOrDefault()).ToListAsync();
// var result = await query.ToListAsync();
// result.ForEach(x =>
// {
// var employer = workshopEmployers.FirstOrDefault(y => y.WorkshopId == x.WorkshopId)?.Employer;
// x.EmployerName = employer?.FullName;
// //x.SubmittedItems.ForEach(y=>y.PicturePath= medias.FirstOrDefault(z=>z.id == y.MediaId)?.Path ?? "");
// });
// return result.Where(x => x.EmployeesWithoutDocumentCount > 0).OrderByDescending(x => x.EmployeesWithoutDocumentCount).ToList();
}
public async Task<List<EmployeeDocumentsViewModel>> GetCreatedEmployeesDocumentByWorkshopIdForAdmin(long workshopId)
@@ -1347,33 +1405,37 @@ public class EmployeeDocumentsRepository : RepositoryBase<long, EmployeeDocument
// ترکیب کل لیست‌ها در حافظه
var allActiveEmployees = activeEmployees
.Concat(clientTemp)
.Concat(leftWorkTemp);
.Concat(leftWorkTemp).ToList();
var contractingPartyIds = _companyContext.WorkshopEmployers.Where(x => workshops.Contains(x.WorkshopId))
.Include(x => x.Employer).Select(x => x.Employer.ContractingPartyId).Distinct();
.Include(x => x.Employer).Select(x => x.Employer.ContractingPartyId).Distinct().ToList();
var accountIds = await _companyContext.ContractingPartyAccounts
.Where(x => contractingPartyIds.Contains(x.PersonalContractingPartyId)).Select(x => x.AccountId)
.ToListAsync();
var query = _companyContext.EmployeeDocuments
.Where(x => workshops.Contains(x.WorkshopId) &&
(allActiveEmployees.Any(y => y.WorkshopId == x.WorkshopId && y.EmployeeId == x.EmployeeId)))
var query =await _companyContext.EmployeeDocuments
.Where(x => workshops.Contains(x.WorkshopId))
.Include(x => x.Workshop).Include(x => x.EmployeeDocumentItemCollection)
.Where(x => x.IsSentToChecker == false && x.HasRejectedItems && x.EmployeeDocumentItemCollection.Any(i => i.DocumentStatus == DocumentStatus.Rejected && accountIds.Contains(i.UploaderId)))
.GroupBy(x => x.WorkshopId).Select(x => new WorkshopWithEmployeeDocumentsViewModel()
{
WorkshopId = x.Key,
WorkshopFullName = x.FirstOrDefault().Workshop.WorkshopName,
EmployeesWithoutDocumentCount = x.Count()
});
EmployeesWithoutDocumentCount = x.Count(),
EmployeeId = x.First().EmployeeId
}).ToListAsync();
query = query.Where(x =>
(allActiveEmployees.Any(y => y.WorkshopId == x.WorkshopId && y.EmployeeId == x.EmployeeId))).ToList();
var resWorkshopIds = query.Select(x => x.WorkshopId).ToList();
var workshopEmployers = await _companyContext.WorkshopEmployers.Include(x => x.Employer)
.Where(x => query.Any(y => y.WorkshopId == x.WorkshopId))
.Where(x => resWorkshopIds.Contains(x.WorkshopId))
.GroupBy(x => x.WorkshopId).Select(x => x.FirstOrDefault()).ToListAsync();
var result = await query.ToListAsync();
var result = query;
result.ForEach(x =>

View File

@@ -1,23 +1,10 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.Metrics;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using _0_Framework.Application;
using _0_Framework.Application;
using _0_Framework.Application.Enums;
using _0_Framework.Application.Sms;
using _0_Framework.Exceptions;
using _0_Framework.InfraStructure;
using Company.Domain.ContarctingPartyAgg;
using Company.Domain.ContractingPartyAccountAgg;
using Company.Domain.empolyerAgg;
using Company.Domain.FinancialInvoiceAgg;
using Company.Domain.FinancialStatmentAgg;
using Company.Domain.FinancialTransactionAgg;
using Company.Domain.InstitutionContractAgg;
@@ -28,7 +15,6 @@ using Company.Domain.InstitutionPlanAgg;
using Company.Domain.SmsResultAgg;
using Company.Domain.WorkshopAgg;
using CompanyManagment.App.Contracts.Employer;
using CompanyManagment.App.Contracts.FinancialInvoice;
using CompanyManagment.App.Contracts.FinancialStatment;
using CompanyManagment.App.Contracts.FinancilTransaction;
using CompanyManagment.App.Contracts.Hubs;
@@ -37,20 +23,21 @@ using CompanyManagment.App.Contracts.InstitutionContractContactinfo;
using CompanyManagment.App.Contracts.Law;
using CompanyManagment.App.Contracts.TemporaryClientRegistration;
using CompanyManagment.App.Contracts.Workshop;
using CompanyManagment.App.Contracts.WorkshopPlan;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using MongoDB.Driver;
using OfficeOpenXml.Packaging.Ionic.Zip;
using PersianTools.Core;
using static System.Runtime.InteropServices.JavaScript.JSType;
using static Microsoft.EntityFrameworkCore.DbLoggerCategory.Database;
using SmsResult = CompanyManagment.EFCore.Migrations.SmsResult;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ContractingPartyAccount = Company.Domain.ContractingPartyAccountAgg.ContractingPartyAccount;
using FinancialStatment = Company.Domain.FinancialStatmentAgg.FinancialStatment;
using String = System.String;
using Workshop = Company.Domain.WorkshopAgg.Workshop;
namespace CompanyManagment.EFCore.Repository;
@@ -1372,7 +1359,7 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
.Count(l => l.StartWorkDate <= DateTime.Now && l.LeftWorkDate >= DateTime.Now);
return new GetInstitutionContractListItemsViewModel()
{
ContractAmount = x.contract.ContractAmount,
ContractAmount = x.contract.ContractAmountWithTax,
Balance = statement?.FinancialTransactionList.Sum(ft => ft.Deptor - ft.Creditor) ?? 0,
WorkshopsCount = workshops.Count(),
ContractStartFa = x.contract.ContractStartGr.ToFarsi(),
@@ -1392,9 +1379,7 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
Workshops = workshopDetails,
IsInPersonContract = x.contract.WorkshopGroup?.CurrentWorkshops
.Any(y => y.Services.ContractInPerson) ?? true,
IsOldContract = x.contract.WorkshopGroup?.CurrentWorkshops == null
|| x.contract.WorkshopGroup.CurrentWorkshops.Count == 0
|| x.contract.WorkshopGroup.CurrentWorkshops.Any(y => y.Price == 0)
IsOldContract = x.contract.SigningType == InstitutionContractSigningType.Legacy
};
}).ToList()
};
@@ -3213,6 +3198,9 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
PaymentPrice = institution.TotalAmount.ToMoney(),
TotalPrice = (institution.TotalAmount - institution.ValueAddedTax).ToMoney(),
TaxPrice = institution.ValueAddedTax.ToMoney(),
OneMonthPrice = institution.ContractAmountWithTax.ToMoney(),
OneMonthWithoutTax = institution.ContractAmount.ToMoney(),
OneMonthTax = institution.ContractAmountTax.ToMoney(),
VerifierFullName = institution.VerifierFullName,
VerifierPhoneNumber = institution.VerifierPhoneNumber,
VerifyCode = institution.VerifyCode,
@@ -3679,9 +3667,12 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
{
smsList.Add(new BlockSmsListData()
{
PhoneNumber = number.PhoneNumber, PartyName = partyName,
AccountType = accountType, Amount = amount,
ContractingPartyId = contractingParty.id, InstitutionContractId = item.Id,
PhoneNumber = number.PhoneNumber,
PartyName = partyName,
AccountType = accountType,
Amount = amount,
ContractingPartyId = contractingParty.id,
InstitutionContractId = item.Id,
AproveId = aprove
});
}
@@ -3869,11 +3860,16 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
smsList.Add(new SmsListData()
{
PhoneNumber = number.PhoneNumber, TemplateId = templateId,
PartyName = partyName, Amount = balanceToMoney,
ContractingPartyId = contractingParty.id, AproveId = aprove,
TypeOfSmsMethod = "MonthlyBillNew", Code1 = code1,
Code2 = code2, InstitutionContractId = item.Id
PhoneNumber = number.PhoneNumber,
TemplateId = templateId,
PartyName = partyName,
Amount = balanceToMoney,
ContractingPartyId = contractingParty.id,
AproveId = aprove,
TypeOfSmsMethod = "MonthlyBillNew",
Code1 = code1,
Code2 = code2,
InstitutionContractId = item.Id
});
}
else
@@ -3887,10 +3883,15 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
smsList.Add(new SmsListData()
{
PhoneNumber = number.PhoneNumber, TemplateId = templateId,
PartyName = partyName, Amount = balanceToMoney,
ContractingPartyId = contractingParty.id, AproveId = aprove,
TypeOfSmsMethod = "MonthlyBill", Code1 = "", Code2 = "",
PhoneNumber = number.PhoneNumber,
TemplateId = templateId,
PartyName = partyName,
Amount = balanceToMoney,
ContractingPartyId = contractingParty.id,
AproveId = aprove,
TypeOfSmsMethod = "MonthlyBill",
Code1 = "",
Code2 = "",
InstitutionContractId = item.Id
});
}
@@ -3922,11 +3923,16 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
smsList.Add(new SmsListData()
{
PhoneNumber = number.PhoneNumber, TemplateId = templateId,
PartyName = partyName, Amount = balanceToMoney,
ContractingPartyId = contractingParty.id, AproveId = aprove,
TypeOfSmsMethod = "MonthlyBillNew", Code1 = code1,
Code2 = code2, InstitutionContractId = item.Id
PhoneNumber = number.PhoneNumber,
TemplateId = templateId,
PartyName = partyName,
Amount = balanceToMoney,
ContractingPartyId = contractingParty.id,
AproveId = aprove,
TypeOfSmsMethod = "MonthlyBillNew",
Code1 = code1,
Code2 = code2,
InstitutionContractId = item.Id
});
}
else
@@ -3940,10 +3946,15 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
smsList.Add(new SmsListData()
{
PhoneNumber = number.PhoneNumber, TemplateId = templateId,
PartyName = partyName, Amount = balanceToMoney,
ContractingPartyId = contractingParty.id, AproveId = aprove,
TypeOfSmsMethod = "MonthlyBill", Code1 = "", Code2 = "",
PhoneNumber = number.PhoneNumber,
TemplateId = templateId,
PartyName = partyName,
Amount = balanceToMoney,
ContractingPartyId = contractingParty.id,
AproveId = aprove,
TypeOfSmsMethod = "MonthlyBill",
Code1 = "",
Code2 = "",
InstitutionContractId = item.Id
});
}
@@ -3979,11 +3990,16 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
smsList.Add(new SmsListData()
{
PhoneNumber = number.PhoneNumber, TemplateId = templateId,
PartyName = partyName, Amount = balanceToMoney,
ContractingPartyId = contractingParty.id, AproveId = aprove,
TypeOfSmsMethod = "MonthlyBillNew", Code1 = code1,
Code2 = code2, InstitutionContractId = item.Id
PhoneNumber = number.PhoneNumber,
TemplateId = templateId,
PartyName = partyName,
Amount = balanceToMoney,
ContractingPartyId = contractingParty.id,
AproveId = aprove,
TypeOfSmsMethod = "MonthlyBillNew",
Code1 = code1,
Code2 = code2,
InstitutionContractId = item.Id
});
}
else
@@ -3997,10 +4013,15 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
smsList.Add(new SmsListData()
{
PhoneNumber = number.PhoneNumber, TemplateId = templateId,
PartyName = partyName, Amount = balanceToMoney,
ContractingPartyId = contractingParty.id, AproveId = aprove,
TypeOfSmsMethod = "MonthlyBill", Code1 = "", Code2 = "",
PhoneNumber = number.PhoneNumber,
TemplateId = templateId,
PartyName = partyName,
Amount = balanceToMoney,
ContractingPartyId = contractingParty.id,
AproveId = aprove,
TypeOfSmsMethod = "MonthlyBill",
Code1 = "",
Code2 = "",
InstitutionContractId = item.Id
});
}
@@ -4035,11 +4056,16 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
string code2 = publicId.Substring(25);
smsList.Add(new SmsListData()
{
PhoneNumber = number.PhoneNumber, TemplateId = templateId,
PartyName = partyName, Amount = balanceToMoney,
ContractingPartyId = contractingParty.id, AproveId = aprove,
TypeOfSmsMethod = "MonthlyBillNew", Code1 = code1,
Code2 = code2, InstitutionContractId = item.Id
PhoneNumber = number.PhoneNumber,
TemplateId = templateId,
PartyName = partyName,
Amount = balanceToMoney,
ContractingPartyId = contractingParty.id,
AproveId = aprove,
TypeOfSmsMethod = "MonthlyBillNew",
Code1 = code1,
Code2 = code2,
InstitutionContractId = item.Id
});
}
else
@@ -4053,10 +4079,15 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
smsList.Add(new SmsListData()
{
PhoneNumber = number.PhoneNumber, TemplateId = templateId,
PartyName = partyName, Amount = balanceToMoney,
ContractingPartyId = contractingParty.id, AproveId = aprove,
TypeOfSmsMethod = "MonthlyBill", Code1 = "", Code2 = "",
PhoneNumber = number.PhoneNumber,
TemplateId = templateId,
PartyName = partyName,
Amount = balanceToMoney,
ContractingPartyId = contractingParty.id,
AproveId = aprove,
TypeOfSmsMethod = "MonthlyBill",
Code1 = "",
Code2 = "",
InstitutionContractId = item.Id
});
}
@@ -4217,6 +4248,9 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
#endregion
}
#region PrivateMetods
/// <summary>
@@ -4258,6 +4292,88 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
.FirstOrDefaultAsync(x => x.ContractingPartyId == contractingPartyId);
}
#endregion
#region InstitutionContractConfirm
/// <summary>
/// ارسال پیامک یادآور تایید قراداد مالی
/// </summary>
/// <returns></returns>
public async Task SendInstitutionContractConfirmSmsTask()
{
var now = DateTime.Now;
// تبدیل تاریخ میلادی به شمسی
var persianNow = now.ToFarsi();
var persianEndOfMonth = int.Parse(persianNow.FindeEndOfMonth().Substring(8, 2));
var dayOfMonth = int.Parse(persianNow.Substring(8, 2));
var hour = now.Hour;
var minute = now.Minute;
var checkAnyToExecute = false;
//اگر آخرین روز ماه باشد
//اگر روز مثلا عدد روز 31 بود ولی آخرین روز ماه 30 بود
if (dayOfMonth == persianEndOfMonth)
{
checkAnyToExecute = await _context.SmsSettings
.AnyAsync(x =>
x.DayOfMonth >= dayOfMonth && /// اگر بزرگتر یا مساوی رو جاری بود
x.TimeOfDay.Hours == hour &&
x.TimeOfDay.Minutes == minute &&
x.TypeOfSmsSetting == TypeOfSmsSetting.InstitutionContractConfirm &&
x.IsActive
);
}
else
{
checkAnyToExecute = await _context.SmsSettings
.AnyAsync(x =>
x.DayOfMonth == dayOfMonth &&
x.TimeOfDay.Hours == hour &&
x.TimeOfDay.Minutes == minute &&
x.TypeOfSmsSetting == TypeOfSmsSetting.InstitutionContractConfirm &&
x.IsActive
);
}
if (checkAnyToExecute)
{
//اجرای تسک
//دریافت لیست قراداد های تایید نشده
var fromAmonthAgo = now.AddDays(-30);
var pendingContracts = await _context.InstitutionContractSet
.Where(x => x.CreationDate >= fromAmonthAgo && x.CreationDate.Date != now.Date && x.VerificationStatus == InstitutionContractVerificationStatus.PendingForVerify)
.Join(_context.PersonalContractingParties,
contract => contract.ContractingPartyId,
contractingParty => contractingParty.id,
(contract, contractingParty) => new { contract, contractingParty }).Select(x => new InstitutionCreationVerificationSmsDto
{
Number = x.contractingParty.Phone,
FullName = x.contractingParty.IsLegal == "حقیقی" ? $"{x.contractingParty.FName} {x.contractingParty.LName}" : $"{x.contractingParty.LName}",
ContractingPartyId = x.contract.ContractingPartyId,
InstitutionContractId = x.contract.id,
InstitutionId = x.contract.PublicId,
}).ToListAsync();
string typeOfSms = "یادآور تایید قرارداد مالی";
foreach (var item in pendingContracts)
{
var sendResult = await _smsService.SendInstitutionCreationVerificationLink(item.Number, item.FullName,
item.InstitutionId, item.ContractingPartyId, item.InstitutionContractId, typeOfSms);
}
Console.WriteLine("executed at : " + persianNow + " - " + hour + ":" + minute);
}
}
#endregion
#endregion
@@ -4643,6 +4759,7 @@ public class InstitutionContractRepository : RepositoryBase<long, InstitutionCon
.Select(x => x.id).FirstOrDefaultAsync();
}
#endregion

View File

@@ -1777,6 +1777,49 @@ public class InsuranceListRepository : RepositoryBase<long, InsuranceList>, IIns
return res;
}
public async Task<PagedResult<InsuranceClientListViewModel>> GetInsuranceClientList(InsuranceClientSearchModel searchModel)
{
var workshopId = _authHelper.GetWorkshopId();
var query = _context.InsuranceListSet
.Select(x => new InsuranceClientListViewModel
{
Id = x.id,
WorkShopId = x.WorkshopId,
Year = x.Year,
YearInt = Convert.ToInt32(x.Year),
Month = x.Month,
MonthName = x.Month.ToFarsiMonthByNumber(),
MonthInt = Convert.ToInt32(x.Month),
}).Where(x => x.WorkShopId == workshopId);
if (searchModel.Year>0)
{
query = query.Where(x => x.YearInt == searchModel.Year);
}
if (searchModel.Month > 0)
{
query = query.Where(x => x.MonthInt == searchModel.Month);
}
var res = new PagedResult<InsuranceClientListViewModel>
{
TotalCount = query.Count()
};
query = searchModel.Sorting switch
{
"CreationDate-Max" => query.OrderByDescending(x => x.Id),
"CreationDate-Min" => query.OrderBy(x => x.Id),
"Month-Max" => query.OrderByDescending(x => x.MonthInt),
"Month-Min" => query.OrderBy(x => x.MonthInt),
"Year-Max" => query.OrderByDescending(x => x.YearInt),
"Year-Min" => query.OrderBy(x => x.YearInt),
_ => query.OrderByDescending(x => x.Id),
};
res.List =await query.ApplyPagination(searchModel.PageIndex,searchModel.PageSize).ToListAsync();
return res;
}
public async Task<List<InsuranceListViewModel>> GetNotCreatedWorkshop(InsuranceListSearchModel searchModel)
{
if (string.IsNullOrEmpty(searchModel.Month) || string.IsNullOrEmpty(searchModel.Year))

Some files were not shown because too many files have changed in this diff Show More