Merge dc0f3e4c9d into 9ff61cf937
This commit is contained in:
commit
85b084800a
|
|
@ -72,16 +72,34 @@ public class AuthController : ControllerBase
|
||||||
[HttpPost("login")]
|
[HttpPost("login")]
|
||||||
public async Task<IActionResult> Login(LoginRequest req)
|
public async Task<IActionResult> Login(LoginRequest req)
|
||||||
{
|
{
|
||||||
// ✅ normaliza e evita null
|
|
||||||
var email = (req.Email ?? "").Trim().ToLowerInvariant();
|
var email = (req.Email ?? "").Trim().ToLowerInvariant();
|
||||||
var password = req.Password ?? "";
|
var password = req.Password ?? "";
|
||||||
var normalizedEmail = _userManager.NormalizeEmail(email);
|
var normalizedEmail = _userManager.NormalizeEmail(email);
|
||||||
|
|
||||||
// ✅ SOLUÇÃO A: ignora filtros globais (multi-tenant / HasQueryFilter)
|
var tenantId = ResolveTenantId(req);
|
||||||
// e pega 1 usuário (pra você logar logo).
|
ApplicationUser? user;
|
||||||
var user = await _userManager.Users
|
|
||||||
|
if (tenantId == null)
|
||||||
|
{
|
||||||
|
var users = await _userManager.Users
|
||||||
.IgnoreQueryFilters()
|
.IgnoreQueryFilters()
|
||||||
.FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail);
|
.Where(u => u.NormalizedEmail == normalizedEmail)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
if (users.Count == 0)
|
||||||
|
return Unauthorized("Credenciais inválidas.");
|
||||||
|
|
||||||
|
if (users.Count > 1)
|
||||||
|
return BadRequest("Informe o tenant para realizar o login.");
|
||||||
|
|
||||||
|
user = users[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
user = await _userManager.Users
|
||||||
|
.IgnoreQueryFilters()
|
||||||
|
.FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail && u.TenantId == tenantId);
|
||||||
|
}
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
return Unauthorized("Credenciais inválidas.");
|
return Unauthorized("Credenciais inválidas.");
|
||||||
|
|
@ -97,6 +115,15 @@ public class AuthController : ControllerBase
|
||||||
return Ok(new AuthResponse(token));
|
return Ok(new AuthResponse(token));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Guid? ResolveTenantId(LoginRequest req)
|
||||||
|
{
|
||||||
|
if (req.TenantId.HasValue)
|
||||||
|
return req.TenantId.Value;
|
||||||
|
|
||||||
|
var headerValue = Request.Headers["X-Tenant-Id"].FirstOrDefault();
|
||||||
|
return Guid.TryParse(headerValue, out var parsed) ? parsed : null;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<string> GenerateJwtAsync(ApplicationUser user)
|
private async Task<string> GenerateJwtAsync(ApplicationUser user)
|
||||||
{
|
{
|
||||||
var key = _config["Jwt:Key"]!;
|
var key = _config["Jwt:Key"]!;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
using line_gestao_api.Data;
|
||||||
|
using line_gestao_api.Dtos;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace line_gestao_api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/consistency")]
|
||||||
|
[Authorize(Roles = "admin")]
|
||||||
|
public class ConsistencyController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly AppDbContext _db;
|
||||||
|
|
||||||
|
public ConsistencyController(AppDbContext db)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("gaps")]
|
||||||
|
public async Task<ActionResult<ConsistencyReportDto>> GetGaps()
|
||||||
|
{
|
||||||
|
var totalLinhas = await _db.MobileLines.AsNoTracking().CountAsync();
|
||||||
|
var totalClientes = await _db.MobileLines.AsNoTracking()
|
||||||
|
.Where(x => x.Cliente != null && x.Cliente != "")
|
||||||
|
.Select(x => x.Cliente!)
|
||||||
|
.Distinct()
|
||||||
|
.CountAsync();
|
||||||
|
|
||||||
|
var muregLinhas = await _db.MuregLines.AsNoTracking()
|
||||||
|
.Select(x => x.MobileLineId)
|
||||||
|
.Distinct()
|
||||||
|
.CountAsync();
|
||||||
|
|
||||||
|
var trocaLinhas = await _db.TrocaNumeroLines.AsNoTracking()
|
||||||
|
.Select(x => x.Item)
|
||||||
|
.Distinct()
|
||||||
|
.CountAsync();
|
||||||
|
|
||||||
|
var userDataLinhas = await _db.UserDatas.AsNoTracking()
|
||||||
|
.Select(x => x.Item)
|
||||||
|
.Distinct()
|
||||||
|
.CountAsync();
|
||||||
|
|
||||||
|
var vigenciaLinhas = await _db.VigenciaLines.AsNoTracking()
|
||||||
|
.Select(x => x.Item)
|
||||||
|
.Distinct()
|
||||||
|
.CountAsync();
|
||||||
|
|
||||||
|
var billingClientes = await _db.BillingClients.AsNoTracking()
|
||||||
|
.Where(x => x.Cliente != null && x.Cliente != "")
|
||||||
|
.Select(x => x.Cliente)
|
||||||
|
.Distinct()
|
||||||
|
.CountAsync();
|
||||||
|
|
||||||
|
var report = new ConsistencyReportDto
|
||||||
|
{
|
||||||
|
TotalLinhasGeral = totalLinhas,
|
||||||
|
TotalClientesGeral = totalClientes,
|
||||||
|
LinhasPorAba = new List<ConsistencyGapDto>
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Nome = "Mureg",
|
||||||
|
TotalGeral = totalLinhas,
|
||||||
|
TotalAtual = muregLinhas
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Nome = "TrocaNumero",
|
||||||
|
TotalGeral = totalLinhas,
|
||||||
|
TotalAtual = trocaLinhas
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Nome = "UserData",
|
||||||
|
TotalGeral = totalLinhas,
|
||||||
|
TotalAtual = userDataLinhas
|
||||||
|
},
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Nome = "Vigencia",
|
||||||
|
TotalGeral = totalLinhas,
|
||||||
|
TotalAtual = vigenciaLinhas
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ClientesPorAba = new List<ConsistencyGapDto>
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Nome = "Faturamento",
|
||||||
|
TotalGeral = totalClientes,
|
||||||
|
TotalAtual = billingClientes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(report);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
using line_gestao_api.Data;
|
using line_gestao_api.Data;
|
||||||
using line_gestao_api.Dtos;
|
using line_gestao_api.Dtos;
|
||||||
using line_gestao_api.Models;
|
using line_gestao_api.Models;
|
||||||
|
using line_gestao_api.Services;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
@ -20,10 +21,12 @@ namespace line_gestao_api.Controllers
|
||||||
public class LinesController : ControllerBase
|
public class LinesController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly AppDbContext _db;
|
private readonly AppDbContext _db;
|
||||||
|
private readonly IDataConsistencyService _consistencyService;
|
||||||
|
|
||||||
public LinesController(AppDbContext db)
|
public LinesController(AppDbContext db, IDataConsistencyService consistencyService)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
|
_consistencyService = consistencyService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImportExcelForm
|
public class ImportExcelForm
|
||||||
|
|
@ -480,6 +483,8 @@ namespace line_gestao_api.Controllers
|
||||||
try { await _db.SaveChangesAsync(); }
|
try { await _db.SaveChangesAsync(); }
|
||||||
catch (DbUpdateException) { return Conflict(new { message = "Conflito ao salvar." }); }
|
catch (DbUpdateException) { return Conflict(new { message = "Conflito ao salvar." }); }
|
||||||
|
|
||||||
|
await _consistencyService.SyncFromMobileLineAsync(x);
|
||||||
|
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using line_gestao_api.Data;
|
using line_gestao_api.Data;
|
||||||
using line_gestao_api.Dtos;
|
using line_gestao_api.Dtos;
|
||||||
using line_gestao_api.Models;
|
using line_gestao_api.Models;
|
||||||
|
using line_gestao_api.Services;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
@ -13,10 +14,12 @@ namespace line_gestao_api.Controllers
|
||||||
public class TrocaNumeroController : ControllerBase
|
public class TrocaNumeroController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly AppDbContext _db;
|
private readonly AppDbContext _db;
|
||||||
|
private readonly IDataConsistencyService _consistencyService;
|
||||||
|
|
||||||
public TrocaNumeroController(AppDbContext db)
|
public TrocaNumeroController(AppDbContext db, IDataConsistencyService consistencyService)
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
|
_consistencyService = consistencyService;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
|
|
@ -124,6 +127,8 @@ namespace line_gestao_api.Controllers
|
||||||
_db.TrocaNumeroLines.Add(e);
|
_db.TrocaNumeroLines.Add(e);
|
||||||
await _db.SaveChangesAsync();
|
await _db.SaveChangesAsync();
|
||||||
|
|
||||||
|
await _consistencyService.SyncFromTrocaNumeroAsync(e);
|
||||||
|
|
||||||
return CreatedAtAction(nameof(GetById), new { id = e.Id }, ToDetailDto(e));
|
return CreatedAtAction(nameof(GetById), new { id = e.Id }, ToDetailDto(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -149,6 +154,7 @@ namespace line_gestao_api.Controllers
|
||||||
x.UpdatedAt = DateTime.UtcNow;
|
x.UpdatedAt = DateTime.UtcNow;
|
||||||
|
|
||||||
await _db.SaveChangesAsync();
|
await _db.SaveChangesAsync();
|
||||||
|
await _consistencyService.SyncFromTrocaNumeroAsync(x);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,12 @@ namespace line_gestao_api.Controllers;
|
||||||
[Authorize]
|
[Authorize]
|
||||||
public class UsersController : ControllerBase
|
public class UsersController : ControllerBase
|
||||||
{
|
{
|
||||||
|
private static readonly HashSet<string> AllowedRoles = new(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
"admin",
|
||||||
|
"gestor"
|
||||||
|
};
|
||||||
|
|
||||||
private readonly AppDbContext _db;
|
private readonly AppDbContext _db;
|
||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
private readonly RoleManager<IdentityRole<Guid>> _roleManager;
|
private readonly RoleManager<IdentityRole<Guid>> _roleManager;
|
||||||
|
|
@ -65,7 +71,7 @@ public class UsersController : ControllerBase
|
||||||
}
|
}
|
||||||
|
|
||||||
var role = req.Permissao.Trim().ToLowerInvariant();
|
var role = req.Permissao.Trim().ToLowerInvariant();
|
||||||
if (!await _roleManager.RoleExistsAsync(role))
|
if (!AllowedRoles.Contains(role) || !await _roleManager.RoleExistsAsync(role))
|
||||||
{
|
{
|
||||||
return BadRequest(new ValidationErrorResponse
|
return BadRequest(new ValidationErrorResponse
|
||||||
{
|
{
|
||||||
|
|
@ -211,12 +217,33 @@ public class UsersController : ControllerBase
|
||||||
[Authorize(Roles = "admin")]
|
[Authorize(Roles = "admin")]
|
||||||
public async Task<IActionResult> Update(Guid id, [FromBody] UserUpdateRequest req)
|
public async Task<IActionResult> Update(Guid id, [FromBody] UserUpdateRequest req)
|
||||||
{
|
{
|
||||||
|
var errors = await ValidateUpdateAsync(id, req);
|
||||||
|
if (errors.Count > 0)
|
||||||
|
{
|
||||||
|
return BadRequest(new ValidationErrorResponse { Errors = errors });
|
||||||
|
}
|
||||||
|
|
||||||
var user = await _userManager.Users.FirstOrDefaultAsync(u => u.Id == id);
|
var user = await _userManager.Users.FirstOrDefaultAsync(u => u.Id == id);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(req.Nome))
|
||||||
|
{
|
||||||
|
user.Name = req.Nome.Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(req.Email))
|
||||||
|
{
|
||||||
|
var email = req.Email.Trim().ToLowerInvariant();
|
||||||
|
if (!string.Equals(user.Email, email, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
await _userManager.SetEmailAsync(user, email);
|
||||||
|
await _userManager.SetUserNameAsync(user, email);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (req.Ativo.HasValue)
|
if (req.Ativo.HasValue)
|
||||||
{
|
{
|
||||||
user.IsActive = req.Ativo.Value;
|
user.IsActive = req.Ativo.Value;
|
||||||
|
|
@ -225,7 +252,7 @@ public class UsersController : ControllerBase
|
||||||
if (!string.IsNullOrWhiteSpace(req.Permissao))
|
if (!string.IsNullOrWhiteSpace(req.Permissao))
|
||||||
{
|
{
|
||||||
var roleName = req.Permissao.Trim().ToLowerInvariant();
|
var roleName = req.Permissao.Trim().ToLowerInvariant();
|
||||||
if (!await _roleManager.RoleExistsAsync(roleName))
|
if (!AllowedRoles.Contains(roleName) || !await _roleManager.RoleExistsAsync(roleName))
|
||||||
{
|
{
|
||||||
return BadRequest(new ValidationErrorResponse
|
return BadRequest(new ValidationErrorResponse
|
||||||
{
|
{
|
||||||
|
|
@ -245,6 +272,23 @@ public class UsersController : ControllerBase
|
||||||
await _userManager.AddToRoleAsync(user, roleName);
|
await _userManager.AddToRoleAsync(user, roleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(req.Senha))
|
||||||
|
{
|
||||||
|
var token = await _userManager.GeneratePasswordResetTokenAsync(user);
|
||||||
|
var resetResult = await _userManager.ResetPasswordAsync(user, token, req.Senha);
|
||||||
|
if (!resetResult.Succeeded)
|
||||||
|
{
|
||||||
|
return BadRequest(new ValidationErrorResponse
|
||||||
|
{
|
||||||
|
Errors = resetResult.Errors.Select(e => new ValidationErrorDto
|
||||||
|
{
|
||||||
|
Field = "senha",
|
||||||
|
Message = e.Description
|
||||||
|
}).ToList()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await _userManager.UpdateAsync(user);
|
await _userManager.UpdateAsync(user);
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
@ -277,6 +321,64 @@ public class UsersController : ControllerBase
|
||||||
{
|
{
|
||||||
errors.Add(new ValidationErrorDto { Field = "permissao", Message = "Permissão é obrigatória." });
|
errors.Add(new ValidationErrorDto { Field = "permissao", Message = "Permissão é obrigatória." });
|
||||||
}
|
}
|
||||||
|
else if (!AllowedRoles.Contains(req.Permissao.Trim()))
|
||||||
|
{
|
||||||
|
errors.Add(new ValidationErrorDto { Field = "permissao", Message = "Permissão inválida." });
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<ValidationErrorDto>> ValidateUpdateAsync(Guid userId, UserUpdateRequest req)
|
||||||
|
{
|
||||||
|
var errors = new List<ValidationErrorDto>();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(req.Nome) && req.Nome.Trim().Length < 2)
|
||||||
|
{
|
||||||
|
errors.Add(new ValidationErrorDto { Field = "nome", Message = "Nome inválido." });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(req.Email))
|
||||||
|
{
|
||||||
|
var email = req.Email.Trim().ToLowerInvariant();
|
||||||
|
var normalized = _userManager.NormalizeEmail(email);
|
||||||
|
|
||||||
|
var tenantId = _tenantProvider.TenantId;
|
||||||
|
if (tenantId == null)
|
||||||
|
{
|
||||||
|
errors.Add(new ValidationErrorDto { Field = "email", Message = "Tenant inválido." });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var exists = await _userManager.Users.AnyAsync(u =>
|
||||||
|
u.Id != userId &&
|
||||||
|
u.TenantId == tenantId &&
|
||||||
|
u.NormalizedEmail == normalized);
|
||||||
|
|
||||||
|
if (exists)
|
||||||
|
{
|
||||||
|
errors.Add(new ValidationErrorDto { Field = "email", Message = "E-mail já cadastrado." });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(req.Senha))
|
||||||
|
{
|
||||||
|
if (req.Senha.Length < 6)
|
||||||
|
{
|
||||||
|
errors.Add(new ValidationErrorDto { Field = "senha", Message = "Senha deve ter pelo menos 6 caracteres." });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.Senha != req.ConfirmarSenha)
|
||||||
|
{
|
||||||
|
errors.Add(new ValidationErrorDto { Field = "confirmarSenha", Message = "Confirmação de senha inválida." });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(req.Permissao) && !AllowedRoles.Contains(req.Permissao.Trim()))
|
||||||
|
{
|
||||||
|
errors.Add(new ValidationErrorDto { Field = "permissao", Message = "Permissão inválida." });
|
||||||
|
}
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
namespace line_gestao_api.Dtos;
|
||||||
|
|
||||||
|
public class ConsistencyGapDto
|
||||||
|
{
|
||||||
|
public string Nome { get; set; } = string.Empty;
|
||||||
|
public int TotalGeral { get; set; }
|
||||||
|
public int TotalAtual { get; set; }
|
||||||
|
public int Faltando => Math.Max(0, TotalGeral - TotalAtual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ConsistencyReportDto
|
||||||
|
{
|
||||||
|
public int TotalLinhasGeral { get; set; }
|
||||||
|
public int TotalClientesGeral { get; set; }
|
||||||
|
public List<ConsistencyGapDto> LinhasPorAba { get; set; } = new();
|
||||||
|
public List<ConsistencyGapDto> ClientesPorAba { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
namespace line_gestao_api.Dtos;
|
namespace line_gestao_api.Dtos;
|
||||||
|
|
||||||
public record LoginRequest(string Email, string Password);
|
public record LoginRequest(string Email, string Password, Guid? TenantId = null);
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,10 @@ public class UserCreateRequest
|
||||||
|
|
||||||
public class UserUpdateRequest
|
public class UserUpdateRequest
|
||||||
{
|
{
|
||||||
|
public string? Nome { get; set; }
|
||||||
|
public string? Email { get; set; }
|
||||||
|
public string? Senha { get; set; }
|
||||||
|
public string? ConfirmarSenha { get; set; }
|
||||||
public string? Permissao { get; set; }
|
public string? Permissao { get; set; }
|
||||||
public bool? Ativo { get; set; }
|
public bool? Ativo { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ builder.Services.AddDbContext<AppDbContext>(options =>
|
||||||
|
|
||||||
builder.Services.AddHttpContextAccessor();
|
builder.Services.AddHttpContextAccessor();
|
||||||
builder.Services.AddScoped<ITenantProvider, TenantProvider>();
|
builder.Services.AddScoped<ITenantProvider, TenantProvider>();
|
||||||
|
builder.Services.AddScoped<IDataConsistencyService, DataConsistencyService>();
|
||||||
|
|
||||||
builder.Services.AddIdentityCore<ApplicationUser>(options =>
|
builder.Services.AddIdentityCore<ApplicationUser>(options =>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
using line_gestao_api.Data;
|
||||||
|
using line_gestao_api.Models;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace line_gestao_api.Services;
|
||||||
|
|
||||||
|
public class DataConsistencyService : IDataConsistencyService
|
||||||
|
{
|
||||||
|
private readonly AppDbContext _db;
|
||||||
|
|
||||||
|
public DataConsistencyService(AppDbContext db)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SyncFromMobileLineAsync(MobileLine line, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
await ApplyMobileLineToSatellitesAsync(line, cancellationToken);
|
||||||
|
await _db.SaveChangesAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SyncFromTrocaNumeroAsync(TrocaNumeroLine trocaNumero, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var linhaAntiga = OnlyDigits(trocaNumero.LinhaAntiga);
|
||||||
|
if (string.IsNullOrWhiteSpace(linhaAntiga))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var mobile = await _db.MobileLines
|
||||||
|
.FirstOrDefaultAsync(x => x.Linha != null && OnlyDigits(x.Linha) == linhaAntiga, cancellationToken);
|
||||||
|
|
||||||
|
if (mobile == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var linhaNova = OnlyDigits(trocaNumero.LinhaNova);
|
||||||
|
if (!string.IsNullOrWhiteSpace(linhaNova))
|
||||||
|
{
|
||||||
|
mobile.Linha = linhaNova;
|
||||||
|
}
|
||||||
|
|
||||||
|
var iccid = OnlyDigits(trocaNumero.ICCID);
|
||||||
|
if (!string.IsNullOrWhiteSpace(iccid))
|
||||||
|
{
|
||||||
|
mobile.Chip = iccid;
|
||||||
|
}
|
||||||
|
|
||||||
|
mobile.UpdatedAt = DateTime.UtcNow;
|
||||||
|
await _db.SaveChangesAsync(cancellationToken);
|
||||||
|
await ApplyMobileLineToSatellitesAsync(mobile, cancellationToken);
|
||||||
|
await _db.SaveChangesAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string OnlyDigits(string? value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
var chars = value.Where(char.IsDigit).ToArray();
|
||||||
|
return new string(chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ApplyMobileLineToSatellitesAsync(MobileLine line, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var item = line.Item;
|
||||||
|
|
||||||
|
var vigencias = await _db.VigenciaLines
|
||||||
|
.Where(x => x.Item == item)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
foreach (var vigencia in vigencias)
|
||||||
|
{
|
||||||
|
vigencia.Conta = line.Conta;
|
||||||
|
vigencia.Linha = line.Linha;
|
||||||
|
vigencia.Cliente = line.Cliente;
|
||||||
|
vigencia.Usuario = line.Usuario;
|
||||||
|
vigencia.PlanoContrato = line.PlanoContrato;
|
||||||
|
vigencia.UpdatedAt = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
|
||||||
|
var userDatas = await _db.UserDatas
|
||||||
|
.Where(x => x.Item == item)
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
foreach (var userData in userDatas)
|
||||||
|
{
|
||||||
|
userData.Linha = line.Linha;
|
||||||
|
userData.Cliente = line.Cliente;
|
||||||
|
userData.UpdatedAt = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
using line_gestao_api.Models;
|
||||||
|
|
||||||
|
namespace line_gestao_api.Services;
|
||||||
|
|
||||||
|
public interface IDataConsistencyService
|
||||||
|
{
|
||||||
|
Task SyncFromMobileLineAsync(MobileLine line, CancellationToken cancellationToken = default);
|
||||||
|
Task SyncFromTrocaNumeroAsync(TrocaNumeroLine trocaNumero, CancellationToken cancellationToken = default);
|
||||||
|
}
|
||||||
|
|
@ -16,11 +16,16 @@ public class TenantMiddleware
|
||||||
Guid? tenantId = null;
|
Guid? tenantId = null;
|
||||||
var claim = context.User.FindFirst("tenantId")?.Value
|
var claim = context.User.FindFirst("tenantId")?.Value
|
||||||
?? context.User.FindFirst("tenant")?.Value;
|
?? context.User.FindFirst("tenant")?.Value;
|
||||||
|
var headerValue = context.Request.Headers["X-Tenant-Id"].FirstOrDefault();
|
||||||
|
|
||||||
if (Guid.TryParse(claim, out var parsed))
|
if (Guid.TryParse(claim, out var parsed))
|
||||||
{
|
{
|
||||||
tenantId = parsed;
|
tenantId = parsed;
|
||||||
}
|
}
|
||||||
|
else if (Guid.TryParse(headerValue, out var headerTenant))
|
||||||
|
{
|
||||||
|
tenantId = headerTenant;
|
||||||
|
}
|
||||||
|
|
||||||
tenantProvider.SetTenantId(tenantId);
|
tenantProvider.SetTenantId(tenantId);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue