From e355c8be62b399b81f4cba06ed7ab9e38e0da2b6 Mon Sep 17 00:00:00 2001 From: SEAN Date: Tue, 10 Feb 2026 14:49:07 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EB=94=94=EB=B0=94=EC=9D=B4=EC=8A=A4=20?= =?UTF-8?q?=ED=83=9C=EA=B7=B8/=EB=8F=99=EC=9D=98=20=EC=84=A4=EC=A0=95=20AP?= =?UTF-8?q?I=20=EA=B5=AC=ED=98=84=20(#96)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SPMS.API/Controllers/DeviceController.cs | 18 +++++++++++++ .../DTOs/Device/DeviceAgreeRequestDto.cs | 19 +++++++++++++ .../DTOs/Device/DeviceTagsRequestDto.cs | 15 +++++++++++ SPMS.Application/Interfaces/IDeviceService.cs | 2 ++ SPMS.Application/Services/DeviceService.cs | 27 +++++++++++++++++++ 5 files changed, 81 insertions(+) create mode 100644 SPMS.Application/DTOs/Device/DeviceAgreeRequestDto.cs create mode 100644 SPMS.Application/DTOs/Device/DeviceTagsRequestDto.cs diff --git a/SPMS.API/Controllers/DeviceController.cs b/SPMS.API/Controllers/DeviceController.cs index b4658c0..77112cd 100644 --- a/SPMS.API/Controllers/DeviceController.cs +++ b/SPMS.API/Controllers/DeviceController.cs @@ -55,6 +55,24 @@ public class DeviceController : ControllerBase return Ok(ApiResponse.Success()); } + [HttpPost("tags")] + [SwaggerOperation(Summary = "태그 설정", Description = "디바이스 태그를 설정합니다. 빈 배열 전달 시 모든 태그 해제.")] + public async Task SetTagsAsync([FromBody] DeviceTagsRequestDto request) + { + var serviceId = GetServiceId(); + await _deviceService.SetTagsAsync(serviceId, request); + return Ok(ApiResponse.Success()); + } + + [HttpPost("agree")] + [SwaggerOperation(Summary = "동의 설정", Description = "푸시/마케팅 수신 동의를 설정합니다.")] + public async Task SetAgreeAsync([FromBody] DeviceAgreeRequestDto request) + { + var serviceId = GetServiceId(); + await _deviceService.SetAgreeAsync(serviceId, request); + return Ok(ApiResponse.Success()); + } + [HttpPost("list")] [Authorize] [SwaggerOperation(Summary = "디바이스 목록", Description = "대시보드에서 디바이스 목록을 조회합니다. JWT 인증 필요.")] diff --git a/SPMS.Application/DTOs/Device/DeviceAgreeRequestDto.cs b/SPMS.Application/DTOs/Device/DeviceAgreeRequestDto.cs new file mode 100644 index 0000000..6d783cd --- /dev/null +++ b/SPMS.Application/DTOs/Device/DeviceAgreeRequestDto.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace SPMS.Application.DTOs.Device; + +public class DeviceAgreeRequestDto +{ + [Required] + [JsonPropertyName("device_id")] + public long DeviceId { get; set; } + + [Required] + [JsonPropertyName("push_agreed")] + public bool PushAgreed { get; set; } + + [Required] + [JsonPropertyName("marketing_agreed")] + public bool MarketingAgreed { get; set; } +} diff --git a/SPMS.Application/DTOs/Device/DeviceTagsRequestDto.cs b/SPMS.Application/DTOs/Device/DeviceTagsRequestDto.cs new file mode 100644 index 0000000..d2fe449 --- /dev/null +++ b/SPMS.Application/DTOs/Device/DeviceTagsRequestDto.cs @@ -0,0 +1,15 @@ +using System.ComponentModel.DataAnnotations; +using System.Text.Json.Serialization; + +namespace SPMS.Application.DTOs.Device; + +public class DeviceTagsRequestDto +{ + [Required] + [JsonPropertyName("device_id")] + public long DeviceId { get; set; } + + [Required] + [JsonPropertyName("tags")] + public List Tags { get; set; } = new(); +} diff --git a/SPMS.Application/Interfaces/IDeviceService.cs b/SPMS.Application/Interfaces/IDeviceService.cs index 582eceb..9de2ff6 100644 --- a/SPMS.Application/Interfaces/IDeviceService.cs +++ b/SPMS.Application/Interfaces/IDeviceService.cs @@ -9,4 +9,6 @@ public interface IDeviceService Task UpdateAsync(long serviceId, DeviceUpdateRequestDto request); Task DeleteAsync(long serviceId, DeviceDeleteRequestDto request); Task GetListAsync(long serviceId, DeviceListRequestDto request); + Task SetTagsAsync(long serviceId, DeviceTagsRequestDto request); + Task SetAgreeAsync(long serviceId, DeviceAgreeRequestDto request); } diff --git a/SPMS.Application/Services/DeviceService.cs b/SPMS.Application/Services/DeviceService.cs index f3d18ea..69c232f 100644 --- a/SPMS.Application/Services/DeviceService.cs +++ b/SPMS.Application/Services/DeviceService.cs @@ -144,6 +144,33 @@ public class DeviceService : IDeviceService }; } + public async Task SetTagsAsync(long serviceId, DeviceTagsRequestDto request) + { + var device = await _deviceRepository.GetByIdAndServiceAsync(request.DeviceId, serviceId); + if (device == null) + throw new SpmsException(ErrorCodes.DeviceNotFound, "존재하지 않는 디바이스입니다.", 404); + + device.Tags = JsonSerializer.Serialize(request.Tags); + device.UpdatedAt = DateTime.UtcNow; + _deviceRepository.Update(device); + await _unitOfWork.SaveChangesAsync(); + } + + public async Task SetAgreeAsync(long serviceId, DeviceAgreeRequestDto request) + { + var device = await _deviceRepository.GetByIdAndServiceAsync(request.DeviceId, serviceId); + if (device == null) + throw new SpmsException(ErrorCodes.DeviceNotFound, "존재하지 않는 디바이스입니다.", 404); + + device.PushAgreed = request.PushAgreed; + device.MarketingAgreed = request.MarketingAgreed; + device.AgreeUpdatedAt = DateTime.UtcNow; + if (request.MarketingAgreed != device.MarketingAgreed) + device.MktAgreeUpdatedAt = DateTime.UtcNow; + _deviceRepository.Update(device); + await _unitOfWork.SaveChangesAsync(); + } + private static Platform ParsePlatform(string platform) { return platform.ToLowerInvariant() switch