feat: 디바이스 CRUD + 목록 API 구현 (#94) #95
75
SPMS.API/Controllers/DeviceController.cs
Normal file
75
SPMS.API/Controllers/DeviceController.cs
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Swashbuckle.AspNetCore.Annotations;
|
||||
using SPMS.Application.DTOs.Device;
|
||||
using SPMS.Application.Interfaces;
|
||||
using SPMS.Domain.Common;
|
||||
|
||||
namespace SPMS.API.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("v1/in/device")]
|
||||
[ApiExplorerSettings(GroupName = "device")]
|
||||
public class DeviceController : ControllerBase
|
||||
{
|
||||
private readonly IDeviceService _deviceService;
|
||||
|
||||
public DeviceController(IDeviceService deviceService)
|
||||
{
|
||||
_deviceService = deviceService;
|
||||
}
|
||||
|
||||
[HttpPost("register")]
|
||||
[SwaggerOperation(Summary = "디바이스 등록", Description = "앱 최초 설치 시 디바이스를 등록합니다.")]
|
||||
public async Task<IActionResult> RegisterAsync([FromBody] DeviceRegisterRequestDto request)
|
||||
{
|
||||
var serviceId = GetServiceId();
|
||||
var result = await _deviceService.RegisterAsync(serviceId, request);
|
||||
return Ok(ApiResponse<DeviceRegisterResponseDto>.Success(result));
|
||||
}
|
||||
|
||||
[HttpPost("info")]
|
||||
[SwaggerOperation(Summary = "디바이스 조회", Description = "디바이스 정보를 조회합니다.")]
|
||||
public async Task<IActionResult> GetInfoAsync([FromBody] DeviceInfoRequestDto request)
|
||||
{
|
||||
var serviceId = GetServiceId();
|
||||
var result = await _deviceService.GetInfoAsync(serviceId, request);
|
||||
return Ok(ApiResponse<DeviceInfoResponseDto>.Success(result));
|
||||
}
|
||||
|
||||
[HttpPost("update")]
|
||||
[SwaggerOperation(Summary = "디바이스 수정", Description = "앱 실행 시 디바이스 정보를 업데이트합니다.")]
|
||||
public async Task<IActionResult> UpdateAsync([FromBody] DeviceUpdateRequestDto request)
|
||||
{
|
||||
var serviceId = GetServiceId();
|
||||
await _deviceService.UpdateAsync(serviceId, request);
|
||||
return Ok(ApiResponse.Success());
|
||||
}
|
||||
|
||||
[HttpPost("delete")]
|
||||
[SwaggerOperation(Summary = "디바이스 삭제", Description = "앱 삭제/로그아웃 시 디바이스를 비활성화합니다.")]
|
||||
public async Task<IActionResult> DeleteAsync([FromBody] DeviceDeleteRequestDto request)
|
||||
{
|
||||
var serviceId = GetServiceId();
|
||||
await _deviceService.DeleteAsync(serviceId, request);
|
||||
return Ok(ApiResponse.Success());
|
||||
}
|
||||
|
||||
[HttpPost("list")]
|
||||
[Authorize]
|
||||
[SwaggerOperation(Summary = "디바이스 목록", Description = "대시보드에서 디바이스 목록을 조회합니다. JWT 인증 필요.")]
|
||||
public async Task<IActionResult> GetListAsync([FromBody] DeviceListRequestDto request)
|
||||
{
|
||||
var serviceId = GetServiceId();
|
||||
var result = await _deviceService.GetListAsync(serviceId, request);
|
||||
return Ok(ApiResponse<DeviceListResponseDto>.Success(result));
|
||||
}
|
||||
|
||||
private long GetServiceId()
|
||||
{
|
||||
if (HttpContext.Items.TryGetValue("ServiceId", out var serviceIdObj) && serviceIdObj is long serviceId)
|
||||
return serviceId;
|
||||
|
||||
throw new Domain.Exceptions.SpmsException(ErrorCodes.BadRequest, "서비스 식별 정보가 없습니다.", 400);
|
||||
}
|
||||
}
|
||||
|
|
@ -44,6 +44,7 @@ public class ApiKeyMiddleware
|
|||
|
||||
private static bool RequiresApiKey(PathString path)
|
||||
{
|
||||
return path.StartsWithSegments("/v1/in/device");
|
||||
return path.StartsWithSegments("/v1/in/device") &&
|
||||
!path.StartsWithSegments("/v1/in/device/list");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ public class ServiceCodeMiddleware
|
|||
context.Request.Path.StartsWithSegments("/v1/in/account") ||
|
||||
context.Request.Path.StartsWithSegments("/v1/in/public") ||
|
||||
context.Request.Path.StartsWithSegments("/v1/in/service") ||
|
||||
(context.Request.Path.StartsWithSegments("/v1/in/device") &&
|
||||
!context.Request.Path.StartsWithSegments("/v1/in/device/list")) ||
|
||||
context.Request.Path.StartsWithSegments("/swagger") ||
|
||||
context.Request.Path.StartsWithSegments("/health"))
|
||||
{
|
||||
|
|
|
|||
11
SPMS.Application/DTOs/Device/DeviceDeleteRequestDto.cs
Normal file
11
SPMS.Application/DTOs/Device/DeviceDeleteRequestDto.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SPMS.Application.DTOs.Device;
|
||||
|
||||
public class DeviceDeleteRequestDto
|
||||
{
|
||||
[Required]
|
||||
[JsonPropertyName("device_id")]
|
||||
public long DeviceId { get; set; }
|
||||
}
|
||||
11
SPMS.Application/DTOs/Device/DeviceInfoRequestDto.cs
Normal file
11
SPMS.Application/DTOs/Device/DeviceInfoRequestDto.cs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SPMS.Application.DTOs.Device;
|
||||
|
||||
public class DeviceInfoRequestDto
|
||||
{
|
||||
[Required]
|
||||
[JsonPropertyName("device_id")]
|
||||
public long DeviceId { get; set; }
|
||||
}
|
||||
42
SPMS.Application/DTOs/Device/DeviceInfoResponseDto.cs
Normal file
42
SPMS.Application/DTOs/Device/DeviceInfoResponseDto.cs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SPMS.Application.DTOs.Device;
|
||||
|
||||
public class DeviceInfoResponseDto
|
||||
{
|
||||
[JsonPropertyName("device_id")]
|
||||
public long DeviceId { get; set; }
|
||||
|
||||
[JsonPropertyName("device_token")]
|
||||
public string DeviceToken { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("platform")]
|
||||
public string Platform { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("os_version")]
|
||||
public string? OsVersion { get; set; }
|
||||
|
||||
[JsonPropertyName("app_version")]
|
||||
public string? AppVersion { get; set; }
|
||||
|
||||
[JsonPropertyName("model")]
|
||||
public string? Model { get; set; }
|
||||
|
||||
[JsonPropertyName("push_agreed")]
|
||||
public bool PushAgreed { get; set; }
|
||||
|
||||
[JsonPropertyName("marketing_agreed")]
|
||||
public bool MarketingAgreed { get; set; }
|
||||
|
||||
[JsonPropertyName("tags")]
|
||||
public List<int>? Tags { get; set; }
|
||||
|
||||
[JsonPropertyName("is_active")]
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
[JsonPropertyName("last_active_at")]
|
||||
public DateTime? LastActiveAt { get; set; }
|
||||
|
||||
[JsonPropertyName("created_at")]
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
24
SPMS.Application/DTOs/Device/DeviceListRequestDto.cs
Normal file
24
SPMS.Application/DTOs/Device/DeviceListRequestDto.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SPMS.Application.DTOs.Device;
|
||||
|
||||
public class DeviceListRequestDto
|
||||
{
|
||||
[JsonPropertyName("page")]
|
||||
public int Page { get; set; } = 1;
|
||||
|
||||
[JsonPropertyName("size")]
|
||||
public int Size { get; set; } = 20;
|
||||
|
||||
[JsonPropertyName("platform")]
|
||||
public string? Platform { get; set; }
|
||||
|
||||
[JsonPropertyName("push_agreed")]
|
||||
public bool? PushAgreed { get; set; }
|
||||
|
||||
[JsonPropertyName("tags")]
|
||||
public List<int>? Tags { get; set; }
|
||||
|
||||
[JsonPropertyName("is_active")]
|
||||
public bool? IsActive { get; set; }
|
||||
}
|
||||
34
SPMS.Application/DTOs/Device/DeviceListResponseDto.cs
Normal file
34
SPMS.Application/DTOs/Device/DeviceListResponseDto.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
using System.Text.Json.Serialization;
|
||||
using SPMS.Application.DTOs.Notice;
|
||||
|
||||
namespace SPMS.Application.DTOs.Device;
|
||||
|
||||
public class DeviceListResponseDto
|
||||
{
|
||||
[JsonPropertyName("items")]
|
||||
public List<DeviceSummaryDto> Items { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("pagination")]
|
||||
public PaginationDto Pagination { get; set; } = new();
|
||||
}
|
||||
|
||||
public class DeviceSummaryDto
|
||||
{
|
||||
[JsonPropertyName("device_id")]
|
||||
public long DeviceId { get; set; }
|
||||
|
||||
[JsonPropertyName("platform")]
|
||||
public string Platform { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("model")]
|
||||
public string? Model { get; set; }
|
||||
|
||||
[JsonPropertyName("push_agreed")]
|
||||
public bool PushAgreed { get; set; }
|
||||
|
||||
[JsonPropertyName("tags")]
|
||||
public List<int>? Tags { get; set; }
|
||||
|
||||
[JsonPropertyName("last_active_at")]
|
||||
public DateTime? LastActiveAt { get; set; }
|
||||
}
|
||||
24
SPMS.Application/DTOs/Device/DeviceRegisterRequestDto.cs
Normal file
24
SPMS.Application/DTOs/Device/DeviceRegisterRequestDto.cs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SPMS.Application.DTOs.Device;
|
||||
|
||||
public class DeviceRegisterRequestDto
|
||||
{
|
||||
[Required]
|
||||
[JsonPropertyName("device_token")]
|
||||
public string DeviceToken { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
[JsonPropertyName("platform")]
|
||||
public string Platform { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("os_version")]
|
||||
public string? OsVersion { get; set; }
|
||||
|
||||
[JsonPropertyName("app_version")]
|
||||
public string? AppVersion { get; set; }
|
||||
|
||||
[JsonPropertyName("model")]
|
||||
public string? Model { get; set; }
|
||||
}
|
||||
12
SPMS.Application/DTOs/Device/DeviceRegisterResponseDto.cs
Normal file
12
SPMS.Application/DTOs/Device/DeviceRegisterResponseDto.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SPMS.Application.DTOs.Device;
|
||||
|
||||
public class DeviceRegisterResponseDto
|
||||
{
|
||||
[JsonPropertyName("device_id")]
|
||||
public long DeviceId { get; set; }
|
||||
|
||||
[JsonPropertyName("is_new")]
|
||||
public bool IsNew { get; set; }
|
||||
}
|
||||
20
SPMS.Application/DTOs/Device/DeviceUpdateRequestDto.cs
Normal file
20
SPMS.Application/DTOs/Device/DeviceUpdateRequestDto.cs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace SPMS.Application.DTOs.Device;
|
||||
|
||||
public class DeviceUpdateRequestDto
|
||||
{
|
||||
[Required]
|
||||
[JsonPropertyName("device_id")]
|
||||
public long DeviceId { get; set; }
|
||||
|
||||
[JsonPropertyName("device_token")]
|
||||
public string? DeviceToken { get; set; }
|
||||
|
||||
[JsonPropertyName("os_version")]
|
||||
public string? OsVersion { get; set; }
|
||||
|
||||
[JsonPropertyName("app_version")]
|
||||
public string? AppVersion { get; set; }
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ public static class DependencyInjection
|
|||
services.AddScoped<IBannerService, BannerService>();
|
||||
services.AddScoped<IFaqService, FaqService>();
|
||||
services.AddScoped<IAppConfigService, AppConfigService>();
|
||||
services.AddScoped<IDeviceService, DeviceService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
|
|
|||
12
SPMS.Application/Interfaces/IDeviceService.cs
Normal file
12
SPMS.Application/Interfaces/IDeviceService.cs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
using SPMS.Application.DTOs.Device;
|
||||
|
||||
namespace SPMS.Application.Interfaces;
|
||||
|
||||
public interface IDeviceService
|
||||
{
|
||||
Task<DeviceRegisterResponseDto> RegisterAsync(long serviceId, DeviceRegisterRequestDto request);
|
||||
Task<DeviceInfoResponseDto> GetInfoAsync(long serviceId, DeviceInfoRequestDto request);
|
||||
Task UpdateAsync(long serviceId, DeviceUpdateRequestDto request);
|
||||
Task DeleteAsync(long serviceId, DeviceDeleteRequestDto request);
|
||||
Task<DeviceListResponseDto> GetListAsync(long serviceId, DeviceListRequestDto request);
|
||||
}
|
||||
171
SPMS.Application/Services/DeviceService.cs
Normal file
171
SPMS.Application/Services/DeviceService.cs
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
using System.Text.Json;
|
||||
using SPMS.Application.DTOs.Device;
|
||||
using SPMS.Application.Interfaces;
|
||||
using SPMS.Domain.Common;
|
||||
using SPMS.Domain.Entities;
|
||||
using SPMS.Domain.Enums;
|
||||
using SPMS.Domain.Exceptions;
|
||||
using SPMS.Domain.Interfaces;
|
||||
|
||||
namespace SPMS.Application.Services;
|
||||
|
||||
public class DeviceService : IDeviceService
|
||||
{
|
||||
private readonly IDeviceRepository _deviceRepository;
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
|
||||
public DeviceService(IDeviceRepository deviceRepository, IUnitOfWork unitOfWork)
|
||||
{
|
||||
_deviceRepository = deviceRepository;
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public async Task<DeviceRegisterResponseDto> RegisterAsync(long serviceId, DeviceRegisterRequestDto request)
|
||||
{
|
||||
var platform = ParsePlatform(request.Platform);
|
||||
var existing = await _deviceRepository.GetByServiceAndTokenAsync(serviceId, request.DeviceToken);
|
||||
|
||||
if (existing != null)
|
||||
{
|
||||
existing.Platform = platform;
|
||||
existing.OsVersion = request.OsVersion;
|
||||
existing.AppVersion = request.AppVersion;
|
||||
existing.DeviceModel = request.Model;
|
||||
existing.IsActive = true;
|
||||
existing.UpdatedAt = DateTime.UtcNow;
|
||||
_deviceRepository.Update(existing);
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
|
||||
return new DeviceRegisterResponseDto { DeviceId = existing.Id, IsNew = false };
|
||||
}
|
||||
|
||||
var device = new Device
|
||||
{
|
||||
ServiceId = serviceId,
|
||||
DeviceToken = request.DeviceToken,
|
||||
Platform = platform,
|
||||
OsVersion = request.OsVersion,
|
||||
AppVersion = request.AppVersion,
|
||||
DeviceModel = request.Model,
|
||||
PushAgreed = true,
|
||||
MarketingAgreed = false,
|
||||
IsActive = true,
|
||||
CreatedAt = DateTime.UtcNow
|
||||
};
|
||||
|
||||
await _deviceRepository.AddAsync(device);
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
return new DeviceRegisterResponseDto { DeviceId = device.Id, IsNew = true };
|
||||
}
|
||||
|
||||
public async Task<DeviceInfoResponseDto> GetInfoAsync(long serviceId, DeviceInfoRequestDto request)
|
||||
{
|
||||
var device = await _deviceRepository.GetByIdAndServiceAsync(request.DeviceId, serviceId);
|
||||
if (device == null)
|
||||
throw new SpmsException(ErrorCodes.DeviceNotFound, "존재하지 않는 디바이스입니다.", 404);
|
||||
|
||||
return new DeviceInfoResponseDto
|
||||
{
|
||||
DeviceId = device.Id,
|
||||
DeviceToken = device.DeviceToken,
|
||||
Platform = device.Platform.ToString().ToLowerInvariant(),
|
||||
OsVersion = device.OsVersion,
|
||||
AppVersion = device.AppVersion,
|
||||
Model = device.DeviceModel,
|
||||
PushAgreed = device.PushAgreed,
|
||||
MarketingAgreed = device.MarketingAgreed,
|
||||
Tags = ParseTags(device.Tags),
|
||||
IsActive = device.IsActive,
|
||||
LastActiveAt = device.UpdatedAt,
|
||||
CreatedAt = device.CreatedAt
|
||||
};
|
||||
}
|
||||
|
||||
public async Task UpdateAsync(long serviceId, DeviceUpdateRequestDto request)
|
||||
{
|
||||
var device = await _deviceRepository.GetByIdAndServiceAsync(request.DeviceId, serviceId);
|
||||
if (device == null)
|
||||
throw new SpmsException(ErrorCodes.DeviceNotFound, "존재하지 않는 디바이스입니다.", 404);
|
||||
|
||||
if (request.DeviceToken != null)
|
||||
device.DeviceToken = request.DeviceToken;
|
||||
if (request.OsVersion != null)
|
||||
device.OsVersion = request.OsVersion;
|
||||
if (request.AppVersion != null)
|
||||
device.AppVersion = request.AppVersion;
|
||||
|
||||
device.UpdatedAt = DateTime.UtcNow;
|
||||
_deviceRepository.Update(device);
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(long serviceId, DeviceDeleteRequestDto request)
|
||||
{
|
||||
var device = await _deviceRepository.GetByIdAndServiceAsync(request.DeviceId, serviceId);
|
||||
if (device == null)
|
||||
throw new SpmsException(ErrorCodes.DeviceNotFound, "존재하지 않는 디바이스입니다.", 404);
|
||||
|
||||
device.IsActive = false;
|
||||
device.UpdatedAt = DateTime.UtcNow;
|
||||
_deviceRepository.Update(device);
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<DeviceListResponseDto> GetListAsync(long serviceId, DeviceListRequestDto request)
|
||||
{
|
||||
Platform? platform = null;
|
||||
if (!string.IsNullOrWhiteSpace(request.Platform))
|
||||
platform = ParsePlatform(request.Platform);
|
||||
|
||||
var (items, totalCount) = await _deviceRepository.GetPagedAsync(
|
||||
serviceId, request.Page, request.Size,
|
||||
platform, request.PushAgreed, request.IsActive, request.Tags);
|
||||
|
||||
var totalPages = (int)Math.Ceiling((double)totalCount / request.Size);
|
||||
|
||||
return new DeviceListResponseDto
|
||||
{
|
||||
Items = items.Select(d => new DeviceSummaryDto
|
||||
{
|
||||
DeviceId = d.Id,
|
||||
Platform = d.Platform.ToString().ToLowerInvariant(),
|
||||
Model = d.DeviceModel,
|
||||
PushAgreed = d.PushAgreed,
|
||||
Tags = ParseTags(d.Tags),
|
||||
LastActiveAt = d.UpdatedAt
|
||||
}).ToList(),
|
||||
Pagination = new DTOs.Notice.PaginationDto
|
||||
{
|
||||
Page = request.Page,
|
||||
Size = request.Size,
|
||||
TotalCount = totalCount,
|
||||
TotalPages = totalPages
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Platform ParsePlatform(string platform)
|
||||
{
|
||||
return platform.ToLowerInvariant() switch
|
||||
{
|
||||
"ios" => Platform.iOS,
|
||||
"android" => Platform.Android,
|
||||
"web" => Platform.Web,
|
||||
_ => throw new SpmsException(ErrorCodes.BadRequest, "유효하지 않은 플랫폼입니다.", 400)
|
||||
};
|
||||
}
|
||||
|
||||
private static List<int>? ParseTags(string? tagsJson)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(tagsJson))
|
||||
return null;
|
||||
try
|
||||
{
|
||||
return JsonSerializer.Deserialize<List<int>>(tagsJson);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +32,10 @@ public static class ErrorCodes
|
|||
public const string DecryptionFailed = "131";
|
||||
public const string InvalidCredentials = "132";
|
||||
|
||||
// === Device (4) ===
|
||||
public const string DeviceNotFound = "141";
|
||||
public const string DeviceTokenDuplicate = "142";
|
||||
|
||||
// === Push (6) ===
|
||||
public const string PushSendFailed = "161";
|
||||
public const string PushStateChangeNotAllowed = "162";
|
||||
|
|
|
|||
|
|
@ -6,6 +6,11 @@ namespace SPMS.Domain.Interfaces;
|
|||
public interface IDeviceRepository : IRepository<Device>
|
||||
{
|
||||
Task<Device?> GetByServiceAndTokenAsync(long serviceId, string deviceToken);
|
||||
Task<Device?> GetByIdAndServiceAsync(long id, long serviceId);
|
||||
Task<int> GetActiveCountByServiceAsync(long serviceId);
|
||||
Task<IReadOnlyList<Device>> GetByPlatformAsync(long serviceId, Platform platform);
|
||||
Task<(IReadOnlyList<Device> Items, int TotalCount)> GetPagedAsync(
|
||||
long serviceId, int page, int size,
|
||||
Platform? platform = null, bool? pushAgreed = null,
|
||||
bool? isActive = null, List<int>? tags = null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ public static class DependencyInjection
|
|||
services.AddScoped<IBannerRepository, BannerRepository>();
|
||||
services.AddScoped<IFaqRepository, FaqRepository>();
|
||||
services.AddScoped<IAppConfigRepository, AppConfigRepository>();
|
||||
services.AddScoped<IDeviceRepository, DeviceRepository>();
|
||||
|
||||
// External Services
|
||||
services.AddScoped<IJwtService, JwtService>();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using SPMS.Domain.Entities;
|
||||
using SPMS.Domain.Enums;
|
||||
using SPMS.Domain.Interfaces;
|
||||
|
||||
namespace SPMS.Infrastructure.Persistence.Repositories;
|
||||
|
||||
public class DeviceRepository : Repository<Device>, IDeviceRepository
|
||||
{
|
||||
public DeviceRepository(AppDbContext context) : base(context) { }
|
||||
|
||||
public async Task<Device?> GetByServiceAndTokenAsync(long serviceId, string deviceToken)
|
||||
{
|
||||
return await _dbSet.FirstOrDefaultAsync(d => d.ServiceId == serviceId && d.DeviceToken == deviceToken);
|
||||
}
|
||||
|
||||
public async Task<Device?> GetByIdAndServiceAsync(long id, long serviceId)
|
||||
{
|
||||
return await _dbSet.FirstOrDefaultAsync(d => d.Id == id && d.ServiceId == serviceId);
|
||||
}
|
||||
|
||||
public async Task<int> GetActiveCountByServiceAsync(long serviceId)
|
||||
{
|
||||
return await _dbSet.CountAsync(d => d.ServiceId == serviceId && d.IsActive);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<Device>> GetByPlatformAsync(long serviceId, Platform platform)
|
||||
{
|
||||
return await _dbSet
|
||||
.Where(d => d.ServiceId == serviceId && d.Platform == platform && d.IsActive)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<(IReadOnlyList<Device> Items, int TotalCount)> GetPagedAsync(
|
||||
long serviceId, int page, int size,
|
||||
Platform? platform = null, bool? pushAgreed = null,
|
||||
bool? isActive = null, List<int>? tags = null)
|
||||
{
|
||||
var query = _dbSet.Where(d => d.ServiceId == serviceId);
|
||||
|
||||
if (platform.HasValue)
|
||||
query = query.Where(d => d.Platform == platform.Value);
|
||||
|
||||
if (pushAgreed.HasValue)
|
||||
query = query.Where(d => d.PushAgreed == pushAgreed.Value);
|
||||
|
||||
if (isActive.HasValue)
|
||||
query = query.Where(d => d.IsActive == isActive.Value);
|
||||
|
||||
if (tags != null && tags.Count > 0)
|
||||
{
|
||||
foreach (var tag in tags)
|
||||
{
|
||||
var tagStr = tag.ToString();
|
||||
query = query.Where(d => d.Tags != null && EF.Functions.Like(d.Tags, $"%{tagStr}%"));
|
||||
}
|
||||
}
|
||||
|
||||
var totalCount = await query.CountAsync();
|
||||
|
||||
var items = await query
|
||||
.OrderByDescending(d => d.CreatedAt)
|
||||
.Skip((page - 1) * size)
|
||||
.Take(size)
|
||||
.ToListAsync();
|
||||
|
||||
return (items, totalCount);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user