148 lines
5.2 KiB
C#
148 lines
5.2 KiB
C#
using AMREZ.EOP.Abstractions.Applications.Tenancy;
|
|
using AMREZ.EOP.Abstractions.Storage;
|
|
using AMREZ.EOP.Contracts.DTOs.Common;
|
|
using AMREZ.EOP.Contracts.DTOs.MasterData.Route;
|
|
using AMREZ.EOP.Contracts.DTOs.MasterData.RxSchedule;
|
|
using AMREZ.EOP.Domain.Entities.MasterData;
|
|
using AMREZ.EOP.Infrastructures.Data;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace AMREZ.EOP.Infrastructures.Repositories;
|
|
|
|
public sealed class RxScheduleRepository
|
|
{
|
|
private readonly IDbScope _scope;
|
|
private readonly ITenantResolver _tenantResolver;
|
|
private readonly IHttpContextAccessor _http;
|
|
|
|
public RxScheduleRepository(IDbScope scope, ITenantResolver tenantResolver, IHttpContextAccessor http)
|
|
{
|
|
_scope = scope;
|
|
_tenantResolver = tenantResolver;
|
|
_http = http;
|
|
}
|
|
|
|
private Guid EnsureTenant(out AppDbContext db)
|
|
{
|
|
var http = _http.HttpContext ?? throw new InvalidOperationException("No HttpContext");
|
|
var tc = _tenantResolver.Resolve(http) ?? throw new InvalidOperationException("No tenant");
|
|
_scope.EnsureForTenant(tc);
|
|
db = _scope.Get<AppDbContext>();
|
|
|
|
if (!string.IsNullOrWhiteSpace(tc.Id) && Guid.TryParse(tc.Id, out var g) && g != Guid.Empty)
|
|
return g;
|
|
|
|
var key = (http.Items.TryGetValue("TargetTenantKey", out var v) ? v as string : null) ?? tc.Id;
|
|
if (string.IsNullOrWhiteSpace(key)) throw new InvalidOperationException("Tenant key missing");
|
|
|
|
var cfg = db.Set<AMREZ.EOP.Domain.Entities.Tenancy.TenantConfig>()
|
|
.AsNoTracking()
|
|
.FirstOrDefault(x => x.TenantKey == key);
|
|
if (cfg is null) throw new InvalidOperationException($"Tenant '{key}' not found");
|
|
return cfg.TenantId;
|
|
}
|
|
|
|
public async Task<RxSchedule?> GetAsync(Guid id, CancellationToken ct = default)
|
|
{
|
|
var tid = EnsureTenant(out var db);
|
|
return await db.RxSchedules.AsNoTracking()
|
|
.Where(x => x.Id == id && !x.IsDeleted)
|
|
.Where(x => x.Scope == "tenant" ? x.TenantId == tid : true)
|
|
.FirstOrDefaultAsync(ct);
|
|
}
|
|
|
|
public async Task<PagedResponse<RxSchedule>> SearchEffectiveAsync(Guid tenantId, RxScheduleListRequest req,
|
|
CancellationToken ct = default)
|
|
{
|
|
var tid = EnsureTenant(out var db);
|
|
|
|
var tenantQ = db.RxSchedules.AsNoTracking()
|
|
.Where(b => b.Scope == "tenant" && b.TenantId == tid && !b.IsDeleted);
|
|
|
|
var overriddenIds = db.RxSchedules
|
|
.Where(t => t.Scope == "tenant" && t.TenantId == tid && !t.IsDeleted && t.OverridesGlobalId != null)
|
|
.Select(t => t.OverridesGlobalId!.Value);
|
|
|
|
var blockedIds = db.RxScheduleBlocks
|
|
.Where(b => b.TenantId == tid)
|
|
.Select(b => b.GlobalId);
|
|
|
|
var globalsQ = db.RxSchedules.AsNoTracking()
|
|
.Where(g => g.Scope == "global" && !g.IsDeleted)
|
|
.Where(g => !overriddenIds.Contains(g.Id) && !blockedIds.Contains(g.Id));
|
|
|
|
var q = tenantQ.Union(globalsQ);
|
|
|
|
if (!req.IncludeInactive) q = q.Where(x => x.IsActive);
|
|
|
|
if (!string.IsNullOrWhiteSpace(req.Search))
|
|
{
|
|
var s = req.Search.Trim();
|
|
q = q.Where(x => x.Code.Contains(s) || x.Name.Contains(s));
|
|
}
|
|
|
|
var total = await q.CountAsync(ct);
|
|
var items = await q
|
|
.OrderBy(x => x.Code)
|
|
.ThenBy(x => x.Name)
|
|
.Skip((req.Page - 1) * req.PageSize)
|
|
.Take(req.PageSize)
|
|
.ToListAsync(ct);
|
|
|
|
return new PagedResponse<RxSchedule>(req.Page, req.PageSize, total, items);
|
|
}
|
|
|
|
public async Task<bool> CodeExistsAsync(Guid tenantId, string code, CancellationToken ct = default)
|
|
{
|
|
var tid = EnsureTenant(out var db);
|
|
var norm = code.Trim();
|
|
return await db.RxSchedules.AnyAsync(b =>
|
|
!b.IsDeleted &&
|
|
b.Code == norm &&
|
|
(b.Scope == "tenant" && b.TenantId == tid), ct);
|
|
}
|
|
|
|
public async Task AddAsync(RxSchedule entity, CancellationToken ct = default)
|
|
{
|
|
EnsureTenant(out var db);
|
|
await db.RxSchedules.AddAsync(entity, ct);
|
|
await db.SaveChangesAsync(ct);
|
|
}
|
|
|
|
public async Task UpdateAsync(RxSchedule entity, CancellationToken ct = default)
|
|
{
|
|
EnsureTenant(out var db);
|
|
db.RxSchedules.Update(entity);
|
|
await db.SaveChangesAsync(ct);
|
|
}
|
|
|
|
public async Task<int> SoftDeleteAsync(Guid id, Guid tenantId, CancellationToken ct = default)
|
|
{
|
|
var tid = EnsureTenant(out var db);
|
|
|
|
var b = await db.RxSchedules.FirstOrDefaultAsync(x => x.Id == id && !x.IsDeleted, ct);
|
|
if (b is null) return 0;
|
|
|
|
if (b.Scope == "global")
|
|
{
|
|
var exists = await db.RxScheduleBlocks
|
|
.AnyAsync(x => x.TenantId == tid && x.GlobalId == id, ct);
|
|
if (exists) return 0;
|
|
|
|
var block = new RxScheduleBlock()
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
TenantId = tid,
|
|
GlobalId = id
|
|
};
|
|
await db.RxScheduleBlocks.AddAsync(block, ct);
|
|
return await db.SaveChangesAsync(ct);
|
|
}
|
|
|
|
if (b.TenantId != tid) return 0;
|
|
|
|
b.IsDeleted = true;
|
|
return await db.SaveChangesAsync(ct);
|
|
}
|
|
} |