Refactor bug report system to use Guid for identifiers instead of long

This commit is contained in:
2025-12-13 11:19:17 +03:30
parent eb49bf771d
commit b3f42af77c
18 changed files with 44 additions and 149 deletions

View File

@@ -8,15 +8,15 @@ namespace Company.Domain.CameraBugReportAgg;
/// <summary>
/// مدل دامنه برای گزارش خرابی دوربین
/// </summary>
public class CameraBugReport : EntityBase
public class CameraBugReport
{
[BsonId]
[BsonRepresentation(MongoDB.Bson.BsonType.String)]
public new string Id { get; set; }
public Guid Id { get; set; }
public CameraBugReport()
{
Id = Guid.NewGuid().ToString();
Id = Guid.NewGuid();
CreationDate = DateTime.Now;
Status = CameraBugReportStatus.Open;
Screenshots = new List<CameraBugReportScreenshot>();
@@ -163,6 +163,7 @@ public class CameraBugReport : EntityBase
[BsonElement("title")]
public string Title { get; private set; }
public void ChangeStatus(CameraBugReportStatus newStatus)
{
UpdateDate = DateTime.Now;

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@@ -8,16 +9,16 @@ namespace Company.Domain.CameraBugReportAgg;
/// <summary>
/// رابط انبار گزارش خرابی دوربین برای MongoDB
/// </summary>
public interface ICameraBugReportRepository : IRepository<long, CameraBugReport>
public interface ICameraBugReportRepository
{
// Async methods for MongoDB operations
Task CreateAsync(CameraBugReport bugReport);
Task UpdateAsync(CameraBugReport bugReport);
Task<CameraBugReport> GetByIdAsync(string id);
Task<CameraBugReport> GetByIdAsync(Guid id);
Task<List<CameraBugReport>> GetAllAsync();
Task<List<CameraBugReport>> GetAllAsync(int skip, int take);
Task DeleteAsync(string id);
Task<bool> IsExistAsync(string id);
Task DeleteAsync(Guid id);
Task<bool> IsExistAsync(Guid id);
Task<List<CameraBugReport>> FilterAsync(
CameraBugReportType? type = null,
CameraBugPriority? priority = null,

View File

@@ -32,7 +32,7 @@ public class CameraBugReportRepository : ICameraBugReportRepository
bugReport);
}
public async Task<CameraBugReport> GetByIdAsync(string id)
public async Task<CameraBugReport> GetByIdAsync(Guid id)
{
return await _cameraBugReports
.Find(x => x.Id == id)
@@ -56,12 +56,12 @@ public class CameraBugReportRepository : ICameraBugReportRepository
.ToListAsync();
}
public async Task DeleteAsync(string id)
public async Task DeleteAsync(Guid id)
{
await _cameraBugReports.DeleteOneAsync(x => x.Id == id);
}
public async Task<bool> IsExistAsync(string id)
public async Task<bool> IsExistAsync(Guid id)
{
var result = await _cameraBugReports
.Find(x => x.Id == id)

View File

@@ -5,7 +5,7 @@ namespace CompanyManagment.App.Contracts.CameraBugReport
{
public class CameraBugReportDetailViewModel
{
public string Id { get; set; }
public Guid Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string UserEmail { get; set; }

View File

@@ -4,7 +4,7 @@ namespace CompanyManagment.App.Contracts.CameraBugReport
{
public class CameraBugReportViewModel
{
public string Id { get; set; }
public Guid Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string UserEmail { get; set; }

View File

@@ -1,9 +1,11 @@
using System;
namespace CompanyManagment.App.Contracts.CameraBugReport
{
public class EditCameraBugReportCommand
{
public string Id { get; set; }
public Guid Id { get; set; }
public CameraBugPriority Priority { get; set; }
public CameraBugReportStatus Status { get; set; }
}

View File

@@ -9,18 +9,18 @@ namespace CompanyManagment.App.Contracts.CameraBugReport
{
Task<OperationResult> CreateAsync(CreateCameraBugReportCommand command);
Task<OperationResult> EditAsync(EditCameraBugReportCommand command);
Task<OperationResult> DeleteAsync(string id);
Task<OperationResult> DeleteAsync(Guid id);
Task<List<CameraBugReportViewModel>> GetAllAsync(CameraBugReportSearchModel searchModel);
Task<CameraBugReportDetailViewModel> GetDetailsAsync(string id);
Task<bool> IsExistAsync(string id);
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(long id);
OperationResult Delete(Guid id);
List<CameraBugReportViewModel> GetAll(CameraBugReportSearchModel searchModel);
CameraBugReportDetailViewModel GetDetails(long id);
bool IsExist(long id);
CameraBugReportDetailViewModel GetDetails(Guid id);
bool IsExist(Guid id);
}
public class CameraBugReportSearchModel

View File

@@ -69,7 +69,6 @@ namespace CompanyManagment.Application
}
await _repository.CreateAsync(bugReport);
await _repository.SaveChangesAsync();
return op.Succcedded();
}
@@ -84,7 +83,7 @@ namespace CompanyManagment.Application
var op = new OperationResult();
try
{
var bugReport = await _repository.GetByIdAsync(command.Id.ToString());
var bugReport = await _repository.GetByIdAsync(command.Id);
if (bugReport == null)
return op.Failed("گزارش خرابی یافت نشد.");
@@ -92,7 +91,6 @@ namespace CompanyManagment.Application
bugReport.ChangeStatus(command.Status);
await _repository.UpdateAsync(bugReport);
await _repository.SaveChangesAsync();
return op.Succcedded();
}
@@ -102,7 +100,7 @@ namespace CompanyManagment.Application
}
}
public async Task<OperationResult> DeleteAsync(string id)
public async Task<OperationResult> DeleteAsync(Guid id)
{
var op = new OperationResult();
try
@@ -112,7 +110,6 @@ namespace CompanyManagment.Application
return op.Failed("گزارش خرابی یافت نشد.");
await _repository.DeleteAsync(id);
await _repository.SaveChangesAsync();
return op.Succcedded();
}
@@ -160,7 +157,7 @@ namespace CompanyManagment.Application
}
}
public async Task<CameraBugReportDetailViewModel> GetDetailsAsync(string id)
public async Task<CameraBugReportDetailViewModel> GetDetailsAsync(Guid id)
{
try
{
@@ -213,7 +210,7 @@ namespace CompanyManagment.Application
}
}
public async Task<bool> IsExistAsync(string id)
public async Task<bool> IsExistAsync(Guid id)
{
return await _repository.IsExistAsync(id);
}
@@ -243,11 +240,11 @@ namespace CompanyManagment.Application
}
}
public OperationResult Delete(long id)
public OperationResult Delete(Guid id)
{
try
{
return DeleteAsync(id.ToString()).ConfigureAwait(false).GetAwaiter().GetResult();
return DeleteAsync(id).ConfigureAwait(false).GetAwaiter().GetResult();
}
catch (Exception ex)
{
@@ -267,11 +264,11 @@ namespace CompanyManagment.Application
}
}
public CameraBugReportDetailViewModel GetDetails(long id)
public CameraBugReportDetailViewModel GetDetails(Guid id)
{
try
{
return GetDetailsAsync(id.ToString()).ConfigureAwait(false).GetAwaiter().GetResult();
return GetDetailsAsync(id).ConfigureAwait(false).GetAwaiter().GetResult();
}
catch (Exception ex)
{
@@ -279,11 +276,11 @@ namespace CompanyManagment.Application
}
}
public bool IsExist(long id)
public bool IsExist(Guid id)
{
try
{
return IsExistAsync(id.ToString()).ConfigureAwait(false).GetAwaiter().GetResult();
return IsExistAsync(id).ConfigureAwait(false).GetAwaiter().GetResult();
}
catch (Exception ex)
{

View File

@@ -1,18 +0,0 @@
using Company.Domain.CameraBugReportAgg;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace CompanyManagment.EFCore.Mapping
{
public class CameraBugReportLogMapping : IEntityTypeConfiguration<CameraBugReportLog>
{
public void Configure(EntityTypeBuilder<CameraBugReportLog> builder)
{
builder.HasKey(x => x.id);
builder.ToTable("CameraBugReportLogs");
builder.Property(x => x.Message).HasColumnType("ntext").IsRequired();
}
}
}

View File

@@ -1,38 +0,0 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Company.Domain.CameraBugReportAgg;
namespace CompanyManagment.EFCore.Mapping;
public class CameraBugReportMapping : IEntityTypeConfiguration<CameraBugReport>
{
public void Configure(EntityTypeBuilder<CameraBugReport> builder)
{
builder.HasMany(x => x.Screenshots).WithOne(x => x.CameraBugReport).HasForeignKey(x => x.CameraBugReportId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasMany(x => x.Logs).WithOne(x => x.CameraBugReport).HasForeignKey(x => x.CameraBugReportId)
.OnDelete(DeleteBehavior.Cascade);
builder.Property(x => x.Status).HasConversion<int>();
builder.Property(x => x.Priority).HasConversion<int>();
builder.Property(x => x.Type).HasConversion<int>();
builder.Property(x => x.StackTrace).HasColumnType("ntext");
builder.Property(x => x.Flavor).HasMaxLength(50);
builder.Property(x => x.PackageName).HasMaxLength(150);
builder.Property(x => x.BuildNumber).HasMaxLength(50);
builder.Property(x => x.AppVersion).HasMaxLength(50);
builder.Property(x => x.NetworkType).HasMaxLength(50);
builder.Property(x => x.ScreenResolution).HasMaxLength(50);
builder.Property(x => x.DeviceId).HasMaxLength(200);
builder.Property(x => x.Manufacturer).HasMaxLength(100);
builder.Property(x => x.Platform).HasMaxLength(50);
builder.Property(x => x.OsVersion).HasMaxLength(50);
builder.Property(x => x.DeviceModel).HasMaxLength(100);
builder.Property(x => x.UserEmail).HasMaxLength(150).IsRequired();
builder.Property(x => x.Description).HasColumnType("ntext").IsRequired();
builder.Property(x => x.Title).HasMaxLength(200).IsRequired();
builder.ToTable("CameraBugReports");
builder.HasKey(x => x.id);
}
}

View File

@@ -1,19 +0,0 @@
using Company.Domain.CameraBugReportAgg;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace CompanyManagment.EFCore.Mapping
{
public class CameraBugReportScreenshotMapping : IEntityTypeConfiguration<CameraBugReportScreenshot>
{
public void Configure(EntityTypeBuilder<CameraBugReportScreenshot> builder)
{
builder.HasKey(x => x.id);
builder.ToTable("CameraBugReportScreenshots");
builder.Property(x => x.FileName).HasMaxLength(255);
builder.Property(x => x.Base64Data).HasColumnType("ntext").IsRequired();
}
}
}

View File

@@ -1,31 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using _0_Framework.InfraStructure;
using CompanyManagment.App.Contracts.CameraBugReport;
using Company.Domain.CameraBugReportAgg;
using Microsoft.EntityFrameworkCore;
namespace CompanyManagment.EFCore.Repository
{
public class CameraBugReportRepository : RepositoryBase<long, CameraBugReport>, ICameraBugReportRepository
{
private readonly CompanyContext _companyContext;
public CameraBugReportRepository(CompanyContext companyContext) : base(companyContext)
{
_companyContext = companyContext;
}
IQueryable<CameraBugReport> ICameraBugReportRepository.GetAllAsNoTracking()
{
return _companyContext.CameraBugReports.AsNoTracking();
}
public bool IsExist(long id)
{
return _companyContext.CameraBugReports.Any(x => x.id == id);
}
}
}

View File

@@ -20,12 +20,12 @@ namespace ServiceHost.Areas.AdminNew.Pages.BugReport
return _bugReportApplication.GetAll(searchModel);
}
protected CameraBugReportDetailViewModel GetBugReportDetails(long id)
protected CameraBugReportDetailViewModel GetBugReportDetails(Guid id)
{
return _bugReportApplication.GetDetails(id);
}
protected bool IsExist(long id)
protected bool IsExist(Guid id)
{
return _bugReportApplication.IsExist(id);
}

View File

@@ -8,7 +8,7 @@ public class DeleteModel : BugReportPageModel
{
}
public void OnGet(long id)
public void OnGet(Guid id)
{
BugReportDetails = GetBugReportDetails(id);
if (BugReportDetails == null)
@@ -18,7 +18,7 @@ public class DeleteModel : BugReportPageModel
}
public IActionResult OnPost(long id)
public IActionResult OnPost(Guid id)
{
var result = _bugReportApplication.Delete(id);
if (result.IsSuccedded)

View File

@@ -8,7 +8,7 @@ public class DetailsModel : BugReportPageModel
{
}
public void OnGet(long id)
public void OnGet(Guid id)
{
BugReportDetails = GetBugReportDetails(id);
if (BugReportDetails == null)

View File

@@ -10,7 +10,7 @@ namespace ServiceHost.Areas.AdminNew.Pages.BugReport
}
[BindProperty]
public long Id { get; set; }
public Guid Id { get; set; }
[BindProperty]
public CameraBugPriority Priority { get; set; }
@@ -20,7 +20,7 @@ namespace ServiceHost.Areas.AdminNew.Pages.BugReport
public CameraBugReportDetailViewModel BugReportDetail { get; set; }
public void OnGet(long id)
public void OnGet(Guid id)
{
BugReportDetail = GetBugReportDetails(id);
if (BugReportDetail != null)

View File

@@ -141,7 +141,7 @@
<small>@report.CreationDate.ToString("yyyy-MM-dd HH:mm")</small>
</td>
<td>
<a asp-page="./Details" asp-route-id="@report.Id" class="btn btn-sm btn-info">مشاهده</a>
<a href="./Details?id=@report.Id.ToString()" class="btn btn-sm btn-info">مشاهده</a>
<a asp-page="./Edit" asp-route-id="@report.Id" class="btn btn-sm btn-warning">ویرایش</a>
<a asp-page="./Delete" asp-route-id="@report.Id" class="btn btn-sm btn-danger" onclick="return confirm('آیا مطمئن هستید؟');">حذف</a>
</td>

View File

@@ -60,7 +60,7 @@ namespace ServiceHost.Controllers
/// دریافت جزئیات یک گزارش خرابی
/// </summary>
[HttpGet("{id}")]
public IActionResult GetBugReportDetails(long id)
public IActionResult GetBugReportDetails(Guid id)
{
var bugReport = _bugReportApplication.GetDetails(id);
if (bugReport == null)
@@ -73,7 +73,7 @@ namespace ServiceHost.Controllers
/// ویرایش یک گزارش خرابی
/// </summary>
[HttpPut("{id}")]
public IActionResult EditBugReport(long id, [FromBody] EditCameraBugReportCommand command)
public IActionResult EditBugReport(Guid id, [FromBody] EditCameraBugReportCommand command)
{
if (id != command.Id)
return BadRequest(new { success = false, message = "ID مطابقت ندارد." });
@@ -92,7 +92,7 @@ namespace ServiceHost.Controllers
/// حذف یک گزارش خرابی
/// </summary>
[HttpDelete("{id}")]
public IActionResult DeleteBugReport(long id)
public IActionResult DeleteBugReport(Guid id)
{
var result = _bugReportApplication.Delete(id);
if (result.IsSuccedded)