diff --git a/database/ddl/STR_DSS_Views_Sprint_15.sql b/database/ddl/STR_DSS_Views_Sprint_15.sql index 7227d0db..5654f5fe 100644 --- a/database/ddl/STR_DSS_Views_Sprint_15.sql +++ b/database/ddl/STR_DSS_Views_Sprint_15.sql @@ -10,14 +10,14 @@ SELECT do2.organization_id , do2.managing_organization_id , do2.upd_dtm , do2.upd_user_guid -, docp.organization_contact_person_id as notice_of_takedown_contact_id_1 -, docp.email_address_dsc as notice_of_takedown_contact_email_1 -, docp2.organization_contact_person_id as takedown_request_contact_id_1 -, docp2.email_address_dsc as takedown_request_contact_email_1 -, docp3.organization_contact_person_id as notice_of_takedown_contact_id_2 -, docp3.email_address_dsc as notice_of_takedown_contact_email_2 -, docp4.organization_contact_person_id as takedown_request_contact_id_2 -, docp4.email_address_dsc as takedown_request_contact_email_2 +, docp.organization_contact_person_id as primary_notice_of_takedown_contact_id +, docp.email_address_dsc as primary_notice_of_takedown_contact_email +, docp2.organization_contact_person_id as primary_takedown_request_contact_id +, docp2.email_address_dsc as primary_takedown_request_contact_email +, docp3.organization_contact_person_id as secondary_notice_of_takedown_contact_id +, docp3.email_address_dsc as secondary_notice_of_takedown_contact_email +, docp4.organization_contact_person_id as secondary_takedown_request_contact_id +, docp4.email_address_dsc as secondary_takedown_request_contact_email FROM dss_organization do2 left join dss_organization_contact_person docp on docp.contacted_through_organization_id = do2.organization_id and docp.email_message_type = 'Notice of Takedown' and docp.is_primary = true left join dss_organization_contact_person docp2 on docp2.contacted_through_organization_id = do2.organization_id and docp2.email_message_type = 'Takedown Request' and docp2.is_primary = true diff --git a/postman/str-dss.postman_collection.json b/postman/str-dss.postman_collection.json index 4bf6d676..b4bc60b0 100644 --- a/postman/str-dss.postman_collection.json +++ b/postman/str-dss.postman_collection.json @@ -1605,7 +1605,7 @@ "method": "GET", "header": [], "url": { - "raw": "{{host}}/api/organizations/platforms/592", + "raw": "{{host}}/api/organizations/platforms/1402", "host": [ "{{host}}" ], @@ -1613,7 +1613,123 @@ "api", "organizations", "platforms", - "592" + "1402" + ] + } + }, + "response": [] + }, + { + "name": "Create Platform", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"organizationId\": 0,\r\n \"organizationCd\": \"TESTCD2\",\r\n \"organizationNm\": \"TEST ORG 2\",\r\n \"updDtm\": \"2024-09-27T16:31:12.047Z\",\r\n \"primaryNoticeOfTakedownContactEmail\": \"email1@email.com\",\r\n \"primaryTakedownRequestContactEmail\": \"email2@email.com\",\r\n \"secondaryNoticeOfTakedownContactEmail\": \"email2@email.com\",\r\n \"secondaryTakedownRequestContactEmail\": \"email2@email.com\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{host}}/api/organizations/platforms", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "organizations", + "platforms" + ] + } + }, + "response": [] + }, + { + "name": "Create Sub Platform", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"organizationCd\": \"TESTCDSUB11\",\r\n \"organizationNm\": \"TEST ORG Sub 1\",\r\n \"managingOrganizationId\": 1402\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{host}}/api/organizations/platforms/subsidiaries", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "organizations", + "platforms", + "subsidiaries" + ] + } + }, + "response": [] + }, + { + "name": "Update Platform", + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"organizationNm\": \"TEST ORG11\",\r\n \"updDtm\": \"2024-09-27T18:21:49.159676Z\",\r\n \"primaryNoticeOfTakedownContactEmail\": \"email1@email.com\",\r\n \"primaryTakedownRequestContactEmail\": \"email2@email.com\",\r\n \"secondaryNoticeOfTakedownContactEmail\": \"email2@email.com\",\r\n \"secondaryTakedownRequestContactEmail\": \"email2@email.com\"\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{host}}/api/organizations/platforms/1402", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "organizations", + "platforms", + "1402" + ] + } + }, + "response": [] + }, + { + "name": "Update Subsidiary", + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\r\n \"organizationNm\": \"TEST ORG11111\",\r\n \"updDtm\": \"2024-09-27T19:16:10.035433Z\",\r\n \"managingOrganizationId\": 1402\r\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{host}}/api/organizations/platforms/subsidiaries/1403", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "organizations", + "platforms", + "subsidiaries", + "1403" ] } }, diff --git a/server/StrDss.Api/Controllers/OrganizationsController.cs b/server/StrDss.Api/Controllers/OrganizationsController.cs index eb733fd4..84c1c873 100644 --- a/server/StrDss.Api/Controllers/OrganizationsController.cs +++ b/server/StrDss.Api/Controllers/OrganizationsController.cs @@ -130,5 +130,35 @@ public async Task UpdatePlatform(PlatformUpdateDto dto, long id) return Ok(); } + + [ApiAuthorize(Permissions.UserWrite)] //todo: use platform_write permission when it's ready in the database + [HttpPost("platforms/subsidiaries", Name = "CreatePlatformSub")] + public async Task CreatePlatformSub(PlatformSubCreateDto dto) + { + var (errors, id) = await _orgService.CreatePlatformSubAsync(dto); + + if (errors.Any()) + { + return ValidationUtils.GetValidationErrorResult(errors, ControllerContext); + } + + return Ok(id); + } + + [ApiAuthorize(Permissions.UserWrite)] //todo: use platform_write permission when it's ready in the database + [HttpPut("platforms/subsidiaries/{id}", Name = "UpdatePlatformSub")] + public async Task UpdatePlatformSub(PlatformSubUpdateDto dto, long id) + { + dto.OrganizationId = id; + + var errors = await _orgService.UpdatePlatformSubAsync(dto); + + if (errors.Any()) + { + return ValidationUtils.GetValidationErrorResult(errors, ControllerContext); + } + + return Ok(); + } } } diff --git a/server/StrDss.Data/Entities/DssDbContext.cs b/server/StrDss.Data/Entities/DssDbContext.cs index 653f708a..f6be5d87 100644 --- a/server/StrDss.Data/Entities/DssDbContext.cs +++ b/server/StrDss.Data/Entities/DssDbContext.cs @@ -667,14 +667,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .ToView("dss_platform_vw"); entity.Property(e => e.ManagingOrganizationId).HasColumnName("managing_organization_id"); - entity.Property(e => e.NoticeOfTakedownContactEmail1) - .HasMaxLength(320) - .HasColumnName("notice_of_takedown_contact_email_1"); - entity.Property(e => e.NoticeOfTakedownContactEmail2) - .HasMaxLength(320) - .HasColumnName("notice_of_takedown_contact_email_2"); - entity.Property(e => e.NoticeOfTakedownContactId1).HasColumnName("notice_of_takedown_contact_id_1"); - entity.Property(e => e.NoticeOfTakedownContactId2).HasColumnName("notice_of_takedown_contact_id_2"); entity.Property(e => e.OrganizationCd) .HasMaxLength(25) .HasColumnName("organization_cd"); @@ -685,14 +677,22 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity.Property(e => e.OrganizationType) .HasMaxLength(25) .HasColumnName("organization_type"); - entity.Property(e => e.TakedownRequestContactEmail1) + entity.Property(e => e.PrimaryNoticeOfTakedownContactEmail) + .HasMaxLength(320) + .HasColumnName("primary_notice_of_takedown_contact_email"); + entity.Property(e => e.PrimaryNoticeOfTakedownContactId).HasColumnName("primary_notice_of_takedown_contact_id"); + entity.Property(e => e.PrimaryTakedownRequestContactEmail) + .HasMaxLength(320) + .HasColumnName("primary_takedown_request_contact_email"); + entity.Property(e => e.PrimaryTakedownRequestContactId).HasColumnName("primary_takedown_request_contact_id"); + entity.Property(e => e.SecondaryNoticeOfTakedownContactEmail) .HasMaxLength(320) - .HasColumnName("takedown_request_contact_email_1"); - entity.Property(e => e.TakedownRequestContactEmail2) + .HasColumnName("secondary_notice_of_takedown_contact_email"); + entity.Property(e => e.SecondaryNoticeOfTakedownContactId).HasColumnName("secondary_notice_of_takedown_contact_id"); + entity.Property(e => e.SecondaryTakedownRequestContactEmail) .HasMaxLength(320) - .HasColumnName("takedown_request_contact_email_2"); - entity.Property(e => e.TakedownRequestContactId1).HasColumnName("takedown_request_contact_id_1"); - entity.Property(e => e.TakedownRequestContactId2).HasColumnName("takedown_request_contact_id_2"); + .HasColumnName("secondary_takedown_request_contact_email"); + entity.Property(e => e.SecondaryTakedownRequestContactId).HasColumnName("secondary_takedown_request_contact_id"); entity.Property(e => e.UpdDtm).HasColumnName("upd_dtm"); entity.Property(e => e.UpdUserGuid).HasColumnName("upd_user_guid"); }); diff --git a/server/StrDss.Data/Entities/DssPlatformVw.cs b/server/StrDss.Data/Entities/DssPlatformVw.cs index f0ee5729..eb84b94e 100644 --- a/server/StrDss.Data/Entities/DssPlatformVw.cs +++ b/server/StrDss.Data/Entities/DssPlatformVw.cs @@ -19,19 +19,19 @@ public partial class DssPlatformVw public Guid? UpdUserGuid { get; set; } - public long? NoticeOfTakedownContactId1 { get; set; } + public long? PrimaryNoticeOfTakedownContactId { get; set; } - public string? NoticeOfTakedownContactEmail1 { get; set; } + public string? PrimaryNoticeOfTakedownContactEmail { get; set; } - public long? TakedownRequestContactId1 { get; set; } + public long? PrimaryTakedownRequestContactId { get; set; } - public string? TakedownRequestContactEmail1 { get; set; } + public string? PrimaryTakedownRequestContactEmail { get; set; } - public long? NoticeOfTakedownContactId2 { get; set; } + public long? SecondaryNoticeOfTakedownContactId { get; set; } - public string? NoticeOfTakedownContactEmail2 { get; set; } + public string? SecondaryNoticeOfTakedownContactEmail { get; set; } - public long? TakedownRequestContactId2 { get; set; } + public long? SecondaryTakedownRequestContactId { get; set; } - public string? TakedownRequestContactEmail2 { get; set; } + public string? SecondaryTakedownRequestContactEmail { get; set; } } diff --git a/server/StrDss.Data/Mappings/ModelToEntityProfile.cs b/server/StrDss.Data/Mappings/ModelToEntityProfile.cs index d4f6dfa2..52d7823f 100644 --- a/server/StrDss.Data/Mappings/ModelToEntityProfile.cs +++ b/server/StrDss.Data/Mappings/ModelToEntityProfile.cs @@ -32,6 +32,8 @@ public ModelToEntityProfile() CreateMap(); CreateMap(); CreateMap(); + CreateMap(); + CreateMap(); } } } diff --git a/server/StrDss.Data/Repositories/OrganizationRepository.cs b/server/StrDss.Data/Repositories/OrganizationRepository.cs index 1d94b7fa..dc3d13b1 100644 --- a/server/StrDss.Data/Repositories/OrganizationRepository.cs +++ b/server/StrDss.Data/Repositories/OrganizationRepository.cs @@ -29,6 +29,8 @@ public interface IOrganizationRepository Task CreatePlatformAsync(PlatformCreateDto dto); Task DoesOrgCdExist(string orgCd); Task UpdatePlatformAsync(PlatformUpdateDto dto); + Task CreatePlatformSubAsync(PlatformSubCreateDto dto); + Task UpdatePlatformSubAsync(PlatformSubUpdateDto dto); } public class OrganizationRepository : RepositoryBase, IOrganizationRepository { @@ -188,10 +190,10 @@ public async Task CreatePlatformAsync(PlatformCreateDto dto) await _dbSet.AddAsync(entity); - CreateContact(entity, EmailMessageTypes.NoticeOfTakedown, dto.NoticeOfTakedownContactEmail1, true); - CreateContact(entity, EmailMessageTypes.NoticeOfTakedown, dto.NoticeOfTakedownContactEmail2, false); - CreateContact(entity, EmailMessageTypes.TakedownRequest, dto.TakedownRequestContactEmail1, true); - CreateContact(entity, EmailMessageTypes.TakedownRequest, dto.TakedownRequestContactEmail2, false); + CreateContact(entity, EmailMessageTypes.NoticeOfTakedown, dto.PrimaryNoticeOfTakedownContactEmail, true); + CreateContact(entity, EmailMessageTypes.NoticeOfTakedown, dto.SecondaryNoticeOfTakedownContactEmail, false); + CreateContact(entity, EmailMessageTypes.TakedownRequest, dto.PrimaryTakedownRequestContactEmail, true); + CreateContact(entity, EmailMessageTypes.TakedownRequest, dto.SecondaryTakedownRequestContactEmail, false); return entity; } @@ -222,10 +224,10 @@ public async Task UpdatePlatformAsync(PlatformUpdateDto dto) _mapper.Map(dto, entity); - UpdateContact(entity, EmailMessageTypes.NoticeOfTakedown, dto.NoticeOfTakedownContactEmail1, true); - UpdateContact(entity, EmailMessageTypes.NoticeOfTakedown, dto.NoticeOfTakedownContactEmail2, false); - UpdateContact(entity, EmailMessageTypes.TakedownRequest, dto.TakedownRequestContactEmail1, true); - UpdateContact(entity, EmailMessageTypes.TakedownRequest, dto.TakedownRequestContactEmail2, false); + UpdateContact(entity, EmailMessageTypes.NoticeOfTakedown, dto.PrimaryNoticeOfTakedownContactEmail, true); + UpdateContact(entity, EmailMessageTypes.NoticeOfTakedown, dto.SecondaryNoticeOfTakedownContactEmail, false); + UpdateContact(entity, EmailMessageTypes.TakedownRequest, dto.PrimaryTakedownRequestContactEmail, true); + UpdateContact(entity, EmailMessageTypes.TakedownRequest, dto.SecondaryTakedownRequestContactEmail, false); } private void UpdateContact(DssOrganization entity, string messageType, string? emailAddress, bool isPrimary) @@ -250,5 +252,26 @@ private void UpdateContact(DssOrganization entity, string messageType, string? e } } } + + public async Task CreatePlatformSubAsync(PlatformSubCreateDto dto) + { + var entity = _mapper.Map(dto); + + entity.OrganizationCd = dto.OrganizationCd.ToUpperInvariant(); + entity.OrganizationType = OrganizationTypes.Platform; + + await _dbSet.AddAsync(entity); + + return entity; + } + + public async Task UpdatePlatformSubAsync(PlatformSubUpdateDto dto) + { + var entity = await _dbSet + .Include(x => x.DssOrganizationContactPeople) + .FirstAsync(x => x.OrganizationId == dto.OrganizationId); + + _mapper.Map(dto, entity); + } } } diff --git a/server/StrDss.Model/OrganizationDtos/IPlatformCreateDto.cs b/server/StrDss.Model/OrganizationDtos/IPlatformCreateDto.cs new file mode 100644 index 00000000..a568ca8d --- /dev/null +++ b/server/StrDss.Model/OrganizationDtos/IPlatformCreateDto.cs @@ -0,0 +1,9 @@ +namespace StrDss.Model.OrganizationDtos +{ + public interface IPlatformCreateDto + { + public string OrganizationCd { get; set; } + public string OrganizationNm { get; set; } + + } +} diff --git a/server/StrDss.Model/OrganizationDtos/IPlatformUpdateDto.cs b/server/StrDss.Model/OrganizationDtos/IPlatformUpdateDto.cs new file mode 100644 index 00000000..1448d378 --- /dev/null +++ b/server/StrDss.Model/OrganizationDtos/IPlatformUpdateDto.cs @@ -0,0 +1,8 @@ +namespace StrDss.Model.OrganizationDtos +{ + public interface IPlatformUpdateDto + { + public long OrganizationId { get; set; } + public string OrganizationNm { get; set; } + } +} diff --git a/server/StrDss.Model/OrganizationDtos/PlatformCreateDto.cs b/server/StrDss.Model/OrganizationDtos/PlatformCreateDto.cs index d20e9a99..8076c98d 100644 --- a/server/StrDss.Model/OrganizationDtos/PlatformCreateDto.cs +++ b/server/StrDss.Model/OrganizationDtos/PlatformCreateDto.cs @@ -1,13 +1,13 @@ namespace StrDss.Model.OrganizationDtos { - public class PlatformCreateDto + public class PlatformCreateDto : IPlatformCreateDto { public string OrganizationCd { get; set; } = null!; public string OrganizationNm { get; set; } = null!; public DateTime UpdDtm { get; set; } - public string? NoticeOfTakedownContactEmail1 { get; set; } - public string? TakedownRequestContactEmail1 { get; set; } - public string? NoticeOfTakedownContactEmail2 { get; set; } - public string? TakedownRequestContactEmail2 { get; set; } + public string? PrimaryNoticeOfTakedownContactEmail { get; set; } + public string? PrimaryTakedownRequestContactEmail { get; set; } + public string? SecondaryNoticeOfTakedownContactEmail { get; set; } + public string? SecondaryTakedownRequestContactEmail { get; set; } } } diff --git a/server/StrDss.Model/OrganizationDtos/PlatformSubCreateDto.cs b/server/StrDss.Model/OrganizationDtos/PlatformSubCreateDto.cs new file mode 100644 index 00000000..05f9fea0 --- /dev/null +++ b/server/StrDss.Model/OrganizationDtos/PlatformSubCreateDto.cs @@ -0,0 +1,10 @@ +namespace StrDss.Model.OrganizationDtos +{ + public class PlatformSubCreateDto : IPlatformCreateDto + { + public string OrganizationCd { get; set; } = null!; + public string OrganizationNm { get; set; } = null!; + public long ManagingOrganizationId { get; set; } + public DateTime UpdDtm { get; set; } + } +} diff --git a/server/StrDss.Model/OrganizationDtos/PlatformSubUpdateDto.cs b/server/StrDss.Model/OrganizationDtos/PlatformSubUpdateDto.cs new file mode 100644 index 00000000..a271dd55 --- /dev/null +++ b/server/StrDss.Model/OrganizationDtos/PlatformSubUpdateDto.cs @@ -0,0 +1,11 @@ +namespace StrDss.Model.OrganizationDtos +{ + public class PlatformSubUpdateDto : IPlatformUpdateDto + { + public long OrganizationId { get; set; } + public string OrganizationNm { get; set; } = null!; + public long ManagingOrganizationId { get; set; } + + public DateTime UpdDtm { get; set; } + } +} diff --git a/server/StrDss.Model/OrganizationDtos/PlatformUpdateDto.cs b/server/StrDss.Model/OrganizationDtos/PlatformUpdateDto.cs index c52fddb2..6a142938 100644 --- a/server/StrDss.Model/OrganizationDtos/PlatformUpdateDto.cs +++ b/server/StrDss.Model/OrganizationDtos/PlatformUpdateDto.cs @@ -1,13 +1,13 @@ namespace StrDss.Model.OrganizationDtos { - public class PlatformUpdateDto + public class PlatformUpdateDto : IPlatformUpdateDto { public long OrganizationId { get; set; } public string OrganizationNm { get; set; } = null!; public DateTime UpdDtm { get; set; } - public string? NoticeOfTakedownContactEmail1 { get; set; } - public string? TakedownRequestContactEmail1 { get; set; } - public string? NoticeOfTakedownContactEmail2 { get; set; } - public string? TakedownRequestContactEmail2 { get; set; } + public string? PrimaryNoticeOfTakedownContactEmail { get; set; } + public string? PrimaryTakedownRequestContactEmail { get; set; } + public string? SecondaryNoticeOfTakedownContactEmail { get; set; } + public string? SecondaryTakedownRequestContactEmail { get; set; } } } diff --git a/server/StrDss.Model/OrganizationDtos/PlatformViewDto.cs b/server/StrDss.Model/OrganizationDtos/PlatformViewDto.cs index 7137814d..3a9398c8 100644 --- a/server/StrDss.Model/OrganizationDtos/PlatformViewDto.cs +++ b/server/StrDss.Model/OrganizationDtos/PlatformViewDto.cs @@ -13,14 +13,14 @@ public PlatformViewDto() public string OrganizationNm { get; set; } = null!; public DateTime UpdDtm { get; set; } public Guid? UpdUserGuid { get; set; } - public long? NoticeOfTakedownContactId1 { get; set; } - public string? NoticeOfTakedownContactEmail1 { get; set; } - public long? TakedownRequestContactId1 { get; set; } - public string? TakedownRequestContactEmail1 { get; set; } - public long? NoticeOfTakedownContactId2 { get; set; } - public string? NoticeOfTakedownContactEmail2 { get; set; } - public long? TakedownRequestContactId2 { get; set; } - public string? TakedownRequestContactEmail2 { get; set; } + public long? PrimaryNoticeOfTakedownContactId { get; set; } + public string? PrimaryNoticeOfTakedownContactEmail { get; set; } + public long? PrimaryTakedownRequestContactId { get; set; } + public string? PrimaryTakedownRequestContactEmail { get; set; } + public long? SecondaryNoticeOfTakedownContactId { get; set; } + public string? SecondaryNoticeOfTakedownContactEmail { get; set; } + public long? SecondaryTakedownRequestContactId { get; set; } + public string? SecondaryTakedownRequestContactEmail { get; set; } public virtual ICollection Subsidiaries { get; set; } } } diff --git a/server/StrDss.Service/OrganizationService.cs b/server/StrDss.Service/OrganizationService.cs index 5af7d308..8d147aaa 100644 --- a/server/StrDss.Service/OrganizationService.cs +++ b/server/StrDss.Service/OrganizationService.cs @@ -24,6 +24,8 @@ public interface IOrganizationService Task GetPlatform(long id); Task<(Dictionary>, long)> CreatePlatformAsync(PlatformCreateDto dto); Task>> UpdatePlatformAsync(PlatformUpdateDto dto); + Task<(Dictionary>, long)> CreatePlatformSubAsync(PlatformSubCreateDto dto); + Task>> UpdatePlatformSubAsync(PlatformSubUpdateDto dto); } public class OrganizationService : ServiceBase, IOrganizationService { @@ -94,7 +96,7 @@ public async Task> GetPlatforms(int pageSize, int page return (errors, entity.OrganizationId); } - private async Task>> ValidatePlatformCreateDto(PlatformCreateDto dto, Dictionary> errors) + private async Task>> ValidatePlatformCreateDto(IPlatformCreateDto dto, Dictionary> errors) { _validator.Validate(Entities.Platform, dto, errors); @@ -115,6 +117,22 @@ public async Task>> UpdatePlatformAsync(Platform { var errors = new Dictionary>(); + await ValidatePlatformUpdateDto(dto, errors); + + if (errors.Any()) + { + return errors; + } + + await _orgRepo.UpdatePlatformAsync(dto); + + _unitOfWork.Commit(); + + return errors; + } + + private async Task>> ValidatePlatformUpdateDto(IPlatformUpdateDto dto, Dictionary> errors) + { var platformDto = await _orgRepo.GetPlatform(dto.OrganizationId); if (platformDto == null) @@ -123,25 +141,80 @@ public async Task>> UpdatePlatformAsync(Platform return errors; } - await ValidatePlatformUpdateDto(dto, errors); + _validator.Validate(Entities.Platform, dto, errors); + + return errors; + } + + public async Task<(Dictionary>, long)> CreatePlatformSubAsync(PlatformSubCreateDto dto) + { + var errors = new Dictionary>(); + + await ValidateParentPlatform(errors, dto.ManagingOrganizationId); if (errors.Any()) { - return errors; + return (errors, 0); } - await _orgRepo.UpdatePlatformAsync(dto); + await ValidatePlatformCreateDto(dto, errors); + + if (errors.Any()) + { + return (errors, 0); + } + + var entity = await _orgRepo.CreatePlatformSubAsync(dto); _unitOfWork.Commit(); + return (errors, entity.OrganizationId); + } + + private async Task>> ValidateParentPlatform(Dictionary> errors, long parentPlatformId) + { + var parentPlatform = await _orgRepo.GetOrganizationByIdAsync(parentPlatformId); + + if (parentPlatform == null) + { + errors.AddItem("ManagingOrganizationId", $"No parent platform found with ID {parentPlatformId}."); + return errors; + } + + if (parentPlatform.OrganizationType != OrganizationTypes.Platform) + { + errors.AddItem("ManagingOrganizationId", $"The organization with ID {parentPlatformId} is not a platform (current type: {parentPlatform.OrganizationType})."); + } + + if (parentPlatform.ManagingOrganizationId != null) + { + errors.AddItem("ManagingOrganizationId", $"The parent platform with ID {parentPlatformId} is a subsidiary and a subsidiary cannot be added to a subsidiary platform."); + } + return errors; } - private async Task>> ValidatePlatformUpdateDto(PlatformUpdateDto dto, Dictionary> errors) + public async Task>> UpdatePlatformSubAsync(PlatformSubUpdateDto dto) { - await Task.CompletedTask; + var errors = new Dictionary>(); - _validator.Validate(Entities.Platform, dto, errors); + await ValidateParentPlatform(errors, dto.ManagingOrganizationId); + + if (errors.Any()) + { + return errors; + } + + await ValidatePlatformUpdateDto(dto, errors); + + if (errors.Any()) + { + return errors; + } + + await _orgRepo.UpdatePlatformSubAsync(dto); + + _unitOfWork.Commit(); return errors; }