diff --git a/Core.ApplicationServices/AdviceService.cs b/Core.ApplicationServices/AdviceService.cs index 2e6efc0141..cf39fdcf85 100644 --- a/Core.ApplicationServices/AdviceService.cs +++ b/Core.ApplicationServices/AdviceService.cs @@ -18,7 +18,6 @@ using Core.DomainServices.Extensions; using Core.DomainServices.Time; using Infrastructure.Services.DataAccess; - using Core.DomainModel.Shared; using Core.DomainServices.Notifications; using Core.DomainModel.Notification; @@ -134,29 +133,37 @@ public bool SendAdvice(int id) var advice = _adviceRepository.AsQueryable().ById(id); if (advice != null) { - if (advice.AdviceType == AdviceType.Immediate || IsAdviceInScope(advice)) + if (IsDeactivated(advice)) + { + _logger.Warning("SendAdvice has been invoked for deactivated Advice with id: {adviceId}. The hangfire jobs should have been deleted during deactivation. Check the logs.", id); + DeleteJobFromHangfire(advice); + } + else { - if (DispatchEmails(advice)) + if (advice.AdviceType == AdviceType.Immediate || IsAdviceInScope(advice)) { - _adviceRepository.Update(advice); + if (DispatchEmails(advice)) + { + _adviceRepository.Update(advice); - _adviceSentRepository.Insert(new AdviceSent { AdviceId = id, AdviceSentDate = _operationClock.Now }); + _adviceSentRepository.Insert(new AdviceSent { AdviceId = id, AdviceSentDate = _operationClock.Now }); + } } - } - if (advice.AdviceType == AdviceType.Immediate) - { - advice.IsActive = false; - } - else if (IsAdviceExpired(advice)) - { - advice.IsActive = false; - DeleteJobFromHangfire(advice); - } + if (advice.AdviceType == AdviceType.Immediate) + { + advice.IsActive = false; + } + else if (IsAdviceExpired(advice)) + { + advice.IsActive = false; + DeleteJobFromHangfire(advice); + } - _adviceRepository.Save(); - _adviceSentRepository.Save(); - transaction.Commit(); + _adviceRepository.Save(); + _adviceSentRepository.Save(); + transaction.Commit(); + } } else { @@ -173,6 +180,11 @@ public bool SendAdvice(int id) } } + private static bool IsDeactivated(Advice advice) + { + return !advice.IsActive; + } + private bool IsAdviceExpired(Advice advice) { return advice.StopDate != null && advice.StopDate.Value.Date < _operationClock.Now.Date; @@ -397,49 +409,56 @@ public void CreateOrUpdateJob(int adviceId) throw new ArgumentException(nameof(adviceId) + " does not point to a valid id or points to an advice without alarm date or scheduling"); } - var adviceAlarmDate = advice.AlarmDate.Value; - var adviceScheduling = advice.Scheduling.Value; - - var adviceTriggers = AdviceTriggerFactory.CreateFrom(adviceAlarmDate, adviceScheduling); - - foreach (var adviceTrigger in adviceTriggers) + if (IsDeactivated(advice)) { - var jobId = adviceTrigger.PartitionId.Match(partitionId => Advice.CreatePartitionJobId(adviceId, partitionId), () => advice.JobId); - _hangfireApi.AddOrUpdateRecurringJob(jobId, () => SendAdvice(adviceId), adviceTrigger.Cron); + _logger.Warning("Advice with id: {adviceId} will not be scheduled since it has been deactivated.", adviceId); } - - if (advice.StopDate.HasValue) + else { - //Schedule deactivation to happen the day after the stop date (stop date is "last day alive" for the advice) - var deactivateAt = advice.StopDate.Value.Date == DateTime.MaxValue.Date ? DateTime.MaxValue.Date : advice.StopDate.Value.Date.AddDays(1); - _hangfireApi.Schedule(() => DeactivateById(advice.Id), new DateTimeOffset(deactivateAt)); - } + var adviceAlarmDate = advice.AlarmDate.Value; + var adviceScheduling = advice.Scheduling.Value; - //If time has passed the trigger time, Hangfire will not fire until the next trigger date so we must force it. - if (adviceAlarmDate.Date.Equals(_operationClock.Now.Date)) - { - switch (adviceScheduling) + var adviceTriggers = AdviceTriggerFactory.CreateFrom(adviceAlarmDate, adviceScheduling); + + foreach (var adviceTrigger in adviceTriggers) { - case Scheduling.Day: - case Scheduling.Week: - case Scheduling.Month: - case Scheduling.Year: - case Scheduling.Quarter: - case Scheduling.Semiannual: - var mustScheduleAdviceToday = - advice.AdviceSent.Where(x => x.AdviceSentDate.Date == adviceAlarmDate.Date).Any() == false && - WillTriggerInvokeToday() == false; - if (mustScheduleAdviceToday) - { - //Send the first advice now - _hangfireApi.Schedule(() => SendAdvice(adviceId)); - } - break; - //Intentional fallthrough - no corrections here - case Scheduling.Hour: - case Scheduling.Immediate: - default: - break; + var jobId = adviceTrigger.PartitionId.Match(partitionId => Advice.CreatePartitionJobId(adviceId, partitionId), () => advice.JobId); + _hangfireApi.AddOrUpdateRecurringJob(jobId, () => SendAdvice(adviceId), adviceTrigger.Cron); + } + + if (advice.StopDate.HasValue) + { + //Schedule deactivation to happen the day after the stop date (stop date is "last day alive" for the advice) + var deactivateAt = advice.StopDate.Value.Date == DateTime.MaxValue.Date ? DateTime.MaxValue.Date : advice.StopDate.Value.Date.AddDays(1); + _hangfireApi.Schedule(() => DeactivateById(advice.Id), new DateTimeOffset(deactivateAt)); + } + + //If time has passed the trigger time, Hangfire will not fire until the next trigger date so we must force it. + if (adviceAlarmDate.Date.Equals(_operationClock.Now.Date)) + { + switch (adviceScheduling) + { + case Scheduling.Day: + case Scheduling.Week: + case Scheduling.Month: + case Scheduling.Year: + case Scheduling.Quarter: + case Scheduling.Semiannual: + var mustScheduleAdviceToday = + advice.AdviceSent.Where(x => x.AdviceSentDate.Date == adviceAlarmDate.Date).Any() == false && + WillTriggerInvokeToday() == false; + if (mustScheduleAdviceToday) + { + //Send the first advice now + _hangfireApi.Schedule(() => SendAdvice(adviceId)); + } + break; + //Intentional fallthrough - no corrections here + case Scheduling.Hour: + case Scheduling.Immediate: + default: + break; + } } } } diff --git a/Core.ApplicationServices/Authorization/OrganizationAuthorizationContext.cs b/Core.ApplicationServices/Authorization/OrganizationAuthorizationContext.cs index 63d041c025..0670efd5af 100644 --- a/Core.ApplicationServices/Authorization/OrganizationAuthorizationContext.cs +++ b/Core.ApplicationServices/Authorization/OrganizationAuthorizationContext.cs @@ -258,6 +258,8 @@ public bool AllowDelete(IEntity entity) OrganizationRight right => // Only global admin can set other users as global admins AllowAdministerOrganizationRight(right), + OrganizationUnit unit => + IsGlobalAdmin() || IsLocalAdmin(unit.OrganizationId), _ => true }; } diff --git a/Core.ApplicationServices/Contract/IItContractService.cs b/Core.ApplicationServices/Contract/IItContractService.cs index 38ed0c69dc..51d3f507f5 100644 --- a/Core.ApplicationServices/Contract/IItContractService.cs +++ b/Core.ApplicationServices/Contract/IItContractService.cs @@ -5,6 +5,7 @@ using Core.ApplicationServices.Model.Contracts; using Core.DomainModel.GDPR; using Core.DomainModel.ItContract; +using Core.DomainModel.Organization; using Core.DomainServices.Queries; @@ -26,6 +27,10 @@ public interface IItContractService Maybe ValidateNewName(int contractId, string name); IQueryable Query(params IDomainQuery[] conditions); Result GetAssignableContractOptions(int organizationId); - Result,OperationError> GetAppliedProcurementPlans(int organizationId); + Result, OperationError> GetAppliedProcurementPlans(int organizationId); + Maybe SetResponsibleUnit(int contractId, Guid targetUnitUuid); + Maybe RemoveResponsibleUnit(int contractId); + Maybe RemovePaymentResponsibleUnits(int contractId, bool isInternal, IEnumerable paymentIds); + Maybe TransferPayments(int contractId, Guid targetUnitUuid, bool isInternal, IEnumerable paymentIds); } } diff --git a/Core.ApplicationServices/Contract/ItContractService.cs b/Core.ApplicationServices/Contract/ItContractService.cs index 88aa87ed2d..b30805653c 100644 --- a/Core.ApplicationServices/Contract/ItContractService.cs +++ b/Core.ApplicationServices/Contract/ItContractService.cs @@ -13,6 +13,7 @@ using Core.DomainServices.Authorization; using Core.DomainServices.Contract; using Core.DomainServices.Extensions; +using Core.DomainServices.Generic; using Core.DomainServices.Options; using Core.DomainServices.Queries; using Core.DomainServices.Repositories.Contract; @@ -24,7 +25,6 @@ namespace Core.ApplicationServices.Contract { public class ItContractService : IItContractService { - private readonly IGenericRepository _economyStreamRepository; private readonly IReferenceService _referenceService; private readonly ITransactionManager _transactionManager; private readonly IDomainEvents _domainEvents; @@ -42,10 +42,10 @@ public class ItContractService : IItContractService private readonly IOptionsService _paymentFrequencyOptionsService; private readonly IOptionsService _optionExtendOptionsService; private readonly IOptionsService _terminationDeadlineOptionsService; + private readonly IGenericRepository _economyStreamRepository; public ItContractService( IItContractRepository repository, - IGenericRepository economyStreamRepository, IReferenceService referenceService, ITransactionManager transactionManager, IDomainEvents domainEvents, @@ -61,10 +61,10 @@ public ItContractService( IOptionsService paymentModelOptionsService, IOptionsService paymentFrequencyOptionsService, IOptionsService optionExtendOptionsService, - IOptionsService terminationDeadlineOptionsService) + IOptionsService terminationDeadlineOptionsService, + IGenericRepository economyStreamRepository) { _repository = repository; - _economyStreamRepository = economyStreamRepository; _referenceService = referenceService; _transactionManager = transactionManager; _domainEvents = domainEvents; @@ -81,6 +81,7 @@ public ItContractService( _paymentFrequencyOptionsService = paymentFrequencyOptionsService; _optionExtendOptionsService = optionExtendOptionsService; _terminationDeadlineOptionsService = terminationDeadlineOptionsService; + _economyStreamRepository = economyStreamRepository; } public Result Create(int organizationId, string name) @@ -121,6 +122,47 @@ public Result, OperationError> GetAllByOrganization(int o return Result, OperationError>.Success(contracts); } + public Maybe RemovePaymentResponsibleUnits(int contractId, bool isInternal, IEnumerable paymentIds) + { + return Modify(contractId, contract => + { + foreach (var paymentId in paymentIds) + { + var error = contract.ResetEconomyStreamOrganizationUnit(paymentId, isInternal); + if (error.HasValue) + return error.Value; + } + + return Result.Success(contract); + }).MatchFailure(); + } + + public Maybe TransferPayments(int contractId, Guid targetUnitUuid, bool isInternal, IEnumerable paymentIds) + { + return Modify(contractId, contract => + { + return TransferPayments(contract, targetUnitUuid, isInternal, paymentIds) + .Match + ( + error => error, + () => Result.Success(contract) + ); + }).MatchFailure(); + } + + private static Maybe TransferPayments(ItContract contract, Guid targetUnitUuid, bool isInternal, + IEnumerable paymentIds) + { + foreach (var paymentId in paymentIds) + { + var error = contract.TransferEconomyStream(paymentId, targetUnitUuid, isInternal); + if (error.HasValue) + return error.Value; + } + + return Maybe.None; + } + public Result Delete(int id) { var contract = _repository.GetById(id); @@ -134,36 +176,36 @@ public Result Delete(int id) { return OperationFailure.Forbidden; } - using (var transaction = _transactionManager.Begin()) + + using var transaction = _transactionManager.Begin(); + try { - try + //Delete the economy streams to prevent them from being orphaned + foreach (var economyStream in contract.GetAllPayments()) { - //Delete the economy streams to prevent them from being orphaned - foreach (var economyStream in GetEconomyStreams(contract)) - { - DeleteEconomyStream(economyStream); - } - _economyStreamRepository.Save(); - - //Delete the contract - var deleteByContractId = _referenceService.DeleteByContractId(id); - if (deleteByContractId.Failed) - { - transaction.Rollback(); - return deleteByContractId.Error; - } - _domainEvents.Raise(new EntityBeingDeletedEvent(contract)); - _repository.DeleteContract(contract); - - transaction.Commit(); + _economyStreamRepository.DeleteWithReferencePreload(economyStream); } - catch (Exception e) + _economyStreamRepository.Save(); + + //Delete the contract + var deleteByContractId = _referenceService.DeleteByContractId(id); + if (deleteByContractId.Failed) { - _logger.Error(e, $"Failed to delete it contract with id: {contract.Id}"); transaction.Rollback(); - return OperationFailure.UnknownError; + return deleteByContractId.Error; } + _domainEvents.Raise(new EntityBeingDeletedEvent(contract)); + _repository.DeleteContract(contract); + + transaction.Commit(); + } + catch (Exception e) + { + _logger.Error(e, $"Failed to delete it contract with id: {contract.Id}"); + transaction.Rollback(); + return OperationFailure.UnknownError; } + return contract; } @@ -286,6 +328,28 @@ public Result GetAssignableContractOptions(int ); } + public Maybe SetResponsibleUnit(int contractId, Guid targetUnitUuid) + { + return Modify(contractId, contract => + { + return contract.SetResponsibleOrganizationUnit(targetUnitUuid) + .Match + ( + error => error, + () => Result.Success(contract) + ); + }).MatchFailure(); + } + + public Maybe RemoveResponsibleUnit(int contractId) + { + return Modify(contractId, contract => + { + contract.ResetResponsibleOrganizationUnit(); + return Result.Success(contract); + }).MatchFailure(); + } + private Result WithOrganizationReadAccess(int organizationId, Func> authorizedAction) { var readAccessLevel = _authorizationContext.GetOrganizationReadAccessLevel(organizationId); @@ -305,19 +369,6 @@ private Result WithReadAccess(ItContract contract) return _authorizationContext.AllowReads(contract) ? Result.Success(contract) : new OperationError(OperationFailure.Forbidden); } - private static IEnumerable GetEconomyStreams(ItContract contract) - { - return contract - .ExternEconomyStreams - .ToList() - .Concat(contract.InternEconomyStreams.ToList()); - } - - private void DeleteEconomyStream(EconomyStream economyStream) - { - _economyStreamRepository.DeleteWithReferencePreload(economyStream); - } - private Result Modify(int id, Func> mutation) { using var transaction = _transactionManager.Begin(); diff --git a/Core.ApplicationServices/Core.ApplicationServices.csproj b/Core.ApplicationServices/Core.ApplicationServices.csproj index 7b1f726607..e51e88e0e0 100644 --- a/Core.ApplicationServices/Core.ApplicationServices.csproj +++ b/Core.ApplicationServices/Core.ApplicationServices.csproj @@ -145,7 +145,10 @@ + + + @@ -179,7 +182,10 @@ + + + @@ -268,10 +274,11 @@ - + + @@ -279,7 +286,7 @@ Core.Abstractions - {a76a8e41-74f7-4443-a5f3-059b5414d83b} + {A76A8E41-74F7-4443-A5F3-059B5414D83B} Core.DomainModel diff --git a/Core.ApplicationServices/IUserService.cs b/Core.ApplicationServices/IUserService.cs index f95a6e648b..bf38aaeb2c 100644 --- a/Core.ApplicationServices/IUserService.cs +++ b/Core.ApplicationServices/IUserService.cs @@ -18,7 +18,13 @@ public interface IUserService : IDisposable Result, OperationError> GetUsersWithRoleAssignedInAnyOrganization(OrganizationRole role); Result, OperationError> GetUsersInOrganization(Guid organizationUuid, params IDomainQuery[] queries); Result GetUserInOrganization(Guid organizationUuid, Guid userUuid); - Maybe DeleteUserFromKitos(Guid userUuid); + /// + /// + /// + /// + /// If provided the operation will be scoped to the organization identified by this parameter + /// + Maybe DeleteUser(Guid userUuid, int? scopedToOrganizationId = null); Result, OperationError> SearchAllKitosUsers(params IDomainQuery[] queries); } } \ No newline at end of file diff --git a/Core.ApplicationServices/LinqTreeExtensions.cs b/Core.ApplicationServices/LinqTreeExtensions.cs index 083543a554..65fe36acdc 100644 --- a/Core.ApplicationServices/LinqTreeExtensions.cs +++ b/Core.ApplicationServices/LinqTreeExtensions.cs @@ -7,34 +7,6 @@ namespace Core.ApplicationServices { - public static class LinqTreeExtension - { - public static IEnumerable SelectNestedChildren - (this IEnumerable source, Func> selector) - { - foreach (var item in source) - { - yield return item; - foreach (var subItem in SelectNestedChildren(selector(item), selector)) - { - yield return subItem; - } - } - } - - public static IEnumerable SelectNestedParents - (this T source, Func selector) - where T : class - { - var current = selector(source); - while (current != null) - { - yield return current; - current = selector(current); - } - } - } - public static class QueryableExtension { public static IQueryable OrderByField(this IQueryable q, string sortField, bool descending = false) diff --git a/Core.ApplicationServices/Model/Organizations/OrganizationUnitRegistrationChangeParameters.cs b/Core.ApplicationServices/Model/Organizations/OrganizationUnitRegistrationChangeParameters.cs new file mode 100644 index 0000000000..85e7069981 --- /dev/null +++ b/Core.ApplicationServices/Model/Organizations/OrganizationUnitRegistrationChangeParameters.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +namespace Core.ApplicationServices.Model.Organizations +{ + public class OrganizationUnitRegistrationChangeParameters + { + public OrganizationUnitRegistrationChangeParameters( + IEnumerable organizationUnitRights, + IEnumerable itContractRegistrations, + IEnumerable paymentRegistrationDetails, + IEnumerable responsibleSystems, + IEnumerable relevantSystems) + { + OrganizationUnitRights = organizationUnitRights; + ItContractRegistrations = itContractRegistrations; + PaymentRegistrationDetails = paymentRegistrationDetails; + ResponsibleSystems = responsibleSystems; + RelevantSystems = relevantSystems; + } + + public IEnumerable OrganizationUnitRights { get; } + public IEnumerable ItContractRegistrations { get; } + public IEnumerable PaymentRegistrationDetails { get; } + public IEnumerable ResponsibleSystems { get; } + public IEnumerable RelevantSystems { get; } + } +} diff --git a/Core.ApplicationServices/Model/Organizations/PaymentChangeParameters.cs b/Core.ApplicationServices/Model/Organizations/PaymentChangeParameters.cs new file mode 100644 index 0000000000..2a7d00a97f --- /dev/null +++ b/Core.ApplicationServices/Model/Organizations/PaymentChangeParameters.cs @@ -0,0 +1,23 @@ +using Core.DomainModel.ItContract; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.ApplicationServices.Model.Organizations +{ + public class PaymentChangeParameters + { + public PaymentChangeParameters(int contractId, IEnumerable internalPaymentIds, IEnumerable externalPaymentIds) + { + ItContractId = contractId; + InternalPayments = internalPaymentIds; + ExternalPayments = externalPaymentIds; + } + + public int ItContractId { get; } + public IEnumerable InternalPayments { get; } + public IEnumerable ExternalPayments { get; } + } +} diff --git a/Core.ApplicationServices/Model/Organizations/StsOrganizationSynchronizationDetails.cs b/Core.ApplicationServices/Model/Organizations/StsOrganizationSynchronizationDetails.cs new file mode 100644 index 0000000000..83ca24d2b4 --- /dev/null +++ b/Core.ApplicationServices/Model/Organizations/StsOrganizationSynchronizationDetails.cs @@ -0,0 +1,24 @@ +using Core.DomainServices.Model.StsOrganization; + +namespace Core.ApplicationServices.Model.Organizations +{ + public class StsOrganizationSynchronizationDetails + { + public bool Connected { get; } + public int? SynchronizationDepth { get; } + public bool CanCreateConnection { get; } + public bool CanUpdateConnection { get; } + public bool CanDeleteConnection { get; } + public CheckConnectionError? CheckConnectionError { get; } + + public StsOrganizationSynchronizationDetails(bool connected, int? synchronizationDepth, bool canCreateConnection, bool canUpdateConnection, bool canDeleteConnection, CheckConnectionError? checkConnectionError) + { + Connected = connected; + SynchronizationDepth = synchronizationDepth; + CanCreateConnection = canCreateConnection; + CanUpdateConnection = canUpdateConnection; + CanDeleteConnection = canDeleteConnection; + CheckConnectionError = checkConnectionError; + } + } +} diff --git a/Core.ApplicationServices/Organizations/Handlers/HandleOrganizationBeingDeleted.cs b/Core.ApplicationServices/Organizations/Handlers/HandleOrganizationBeingDeleted.cs index f108c8d0a0..5e03e8a82e 100644 --- a/Core.ApplicationServices/Organizations/Handlers/HandleOrganizationBeingDeleted.cs +++ b/Core.ApplicationServices/Organizations/Handlers/HandleOrganizationBeingDeleted.cs @@ -32,7 +32,6 @@ public class HandleOrganizationBeingDeleted : IDomainEventHandler _taskUsageRepository; private readonly IDomainEvents _domainEvents; public HandleOrganizationBeingDeleted( @@ -43,7 +42,6 @@ public HandleOrganizationBeingDeleted( IItInterfaceService interfaceService, IOrganizationService organizationService, IDefaultOrganizationResolver defaultOrganizationResolver, - IGenericRepository taskUsageRepository, IDomainEvents domainEvents) { _contractService = contractService; @@ -53,7 +51,6 @@ public HandleOrganizationBeingDeleted( _interfaceService = interfaceService; _organizationService = organizationService; _defaultOrganizationResolver = defaultOrganizationResolver; - _taskUsageRepository = taskUsageRepository; _domainEvents = domainEvents; } @@ -156,14 +153,6 @@ private void ClearLocalRegistrations(Organization organization) var dprs = organization.DataProcessingRegistrations.ToList(); dprs.ForEach(x => _dataProcessingRegistrationService.Delete(x.Id).ThrowOnFailure()); organization.DataProcessingRegistrations.Clear(); - - //Strip all task usages in the organization - foreach (var organizationUnit in organization.OrgUnits.ToList()) - { - _taskUsageRepository.RemoveRange(organizationUnit.TaskUsages.ToList()); - organizationUnit.TaskUsages.Clear(); - } - _taskUsageRepository.Save(); } private void ResolveRightsHolderConflicts(OrganizationRemovalConflicts conflicts, Organization organization) diff --git a/Core.ApplicationServices/Organizations/Handlers/RemoveOrganizationUnitRegistrationsCommandHandler.cs b/Core.ApplicationServices/Organizations/Handlers/RemoveOrganizationUnitRegistrationsCommandHandler.cs new file mode 100644 index 0000000000..2002e639d0 --- /dev/null +++ b/Core.ApplicationServices/Organizations/Handlers/RemoveOrganizationUnitRegistrationsCommandHandler.cs @@ -0,0 +1,43 @@ +using Core.Abstractions.Types; +using Core.DomainModel.Commands; +using Core.DomainModel.ItSystemUsage; +using Core.DomainServices; +using System; +using System.Linq; + +namespace Core.ApplicationServices.Organizations.Handlers +{ + public class RemoveOrganizationUnitRegistrationsCommandHandler : ICommandHandler> + { + private readonly IOrganizationUnitService _organizationUnitService; + private readonly IGenericRepository _itSystemUsageOrgUnitUsageRepository; + + public RemoveOrganizationUnitRegistrationsCommandHandler(IOrganizationUnitService organizationUnitService, + IGenericRepository itSystemUsageOrgUnitUsageRepository) + { + _organizationUnitService = organizationUnitService; + _itSystemUsageOrgUnitUsageRepository = itSystemUsageOrgUnitUsageRepository; + } + + public Maybe Execute(RemoveOrganizationUnitRegistrationsCommand command) + { + return _organizationUnitService.DeleteRegistrations(command.Organization.Uuid, command.OrganizationUnit.Uuid) + .Match + ( + error => error, + () => + { + RemoveItSystemUsageOrgUnitUsages(command.OrganizationUnit.Uuid); + return Maybe.None; + }); + } + + private void RemoveItSystemUsageOrgUnitUsages(Guid unitUuid) + { + var itSystemUsageOrgUnitUsages = _itSystemUsageOrgUnitUsageRepository.AsQueryable().Where(x => x.OrganizationUnit.Uuid == unitUuid).ToList(); + + _itSystemUsageOrgUnitUsageRepository.RemoveRange(itSystemUsageOrgUnitUsages); + _itSystemUsageOrgUnitUsageRepository.Save(); + } + } +} diff --git a/Core.ApplicationServices/Organizations/IOrganizationRightsService.cs b/Core.ApplicationServices/Organizations/IOrganizationRightsService.cs index 24a2bca386..9f4438e9d4 100644 --- a/Core.ApplicationServices/Organizations/IOrganizationRightsService.cs +++ b/Core.ApplicationServices/Organizations/IOrganizationRightsService.cs @@ -1,5 +1,7 @@ -using Core.Abstractions.Types; +using System; +using Core.Abstractions.Types; using Core.DomainModel.Organization; +using System.Collections.Generic; namespace Core.ApplicationServices.Organizations { @@ -8,5 +10,7 @@ public interface IOrganizationRightsService Result AssignRole(int organizationId, int userId, OrganizationRole roleId); Result RemoveRole(int organizationId, int userId, OrganizationRole rightId); Result RemoveRole(int rightId); + Maybe RemoveUnitRightsByIds(Guid organizationUuid, Guid unitUuid, IEnumerable rightIds); + Maybe TransferUnitRightsByIds(Guid organizationUuid, Guid unitUuid, Guid targetUnitUuid, IEnumerable rightIds); } } diff --git a/Core.ApplicationServices/Organizations/IOrganizationUnitService.cs b/Core.ApplicationServices/Organizations/IOrganizationUnitService.cs new file mode 100644 index 0000000000..048d2cf3a9 --- /dev/null +++ b/Core.ApplicationServices/Organizations/IOrganizationUnitService.cs @@ -0,0 +1,19 @@ +using Core.Abstractions.Types; +using Core.ApplicationServices.Model.Organizations; +using Core.DomainModel.Organization; +using System; +using System.Collections.Generic; + +namespace Core.ApplicationServices.Organizations +{ + public interface IOrganizationUnitService + { + Result GetAccessRights(Guid organizationUuid, Guid unitUuid); + Result, OperationError> GetAccessRightsByOrganization(Guid organizationUuid); + Result GetRegistrations(Guid organizationUuid, Guid unitUuid); + Maybe Delete(Guid organizationUuid, Guid unitUuid); + Maybe DeleteRegistrations(Guid organizationUuid, Guid unitUuid, OrganizationUnitRegistrationChangeParameters parameters); + Maybe DeleteRegistrations(Guid organizationUuid, Guid unitUuid); + Maybe TransferRegistrations(Guid organizationUuid, Guid unitUuid, Guid targetUnitUuid, OrganizationUnitRegistrationChangeParameters parameters); + } +} diff --git a/Core.ApplicationServices/Organizations/IStsOrganizationSynchronizationService.cs b/Core.ApplicationServices/Organizations/IStsOrganizationSynchronizationService.cs index 6733e2ebad..2bf0b92ed6 100644 --- a/Core.ApplicationServices/Organizations/IStsOrganizationSynchronizationService.cs +++ b/Core.ApplicationServices/Organizations/IStsOrganizationSynchronizationService.cs @@ -1,17 +1,51 @@ using System; using Core.Abstractions.Types; -using Core.DomainServices.Model.StsOrganization; +using Core.ApplicationServices.Model.Organizations; +using Core.DomainModel.Organization; namespace Core.ApplicationServices.Organizations { public interface IStsOrganizationSynchronizationService { + /// + /// Gets the synchronization details of the organization + /// + /// + /// + Result GetSynchronizationDetails(Guid organizationId); /// /// Retrieves a view of the organization as it exists in STS Organization /// /// /// /// - Result GetStsOrganizationalHierarchy(Guid organizationId, Maybe levelsToInclude); + Result GetStsOrganizationalHierarchy(Guid organizationId, Maybe levelsToInclude); + /// + /// Connect the organization to "STS Organisation" + /// + /// + /// + /// + Maybe Connect(Guid organizationId, Maybe levelsToInclude); + /// + /// Disconnect the KITOS organization from STS Organisation + /// + /// + /// + Maybe Disconnect(Guid organizationId); + /// + /// Retrieves a view of the consequences of updating the synchronized hierarchy from that which exists in STS Organization + /// + /// + /// + /// + Result GetConnectionExternalHierarchyUpdateConsequences(Guid organizationId, Maybe levelsToInclude); + /// + /// Updates the connection to the STS Organization + /// + /// + /// + /// + Maybe UpdateConnection(Guid organizationId, Maybe levelsToInclude); } } diff --git a/Core.ApplicationServices/Organizations/OrganizationRightsService.cs b/Core.ApplicationServices/Organizations/OrganizationRightsService.cs index 2295f9561d..3a5e2d5165 100644 --- a/Core.ApplicationServices/Organizations/OrganizationRightsService.cs +++ b/Core.ApplicationServices/Organizations/OrganizationRightsService.cs @@ -1,11 +1,15 @@ -using System.Linq; +using System; +using System.Collections.Generic; +using System.Linq; using Core.Abstractions.Types; using Core.ApplicationServices.Authorization; +using Core.DomainModel; using Core.DomainModel.Events; using Core.DomainModel.Organization; using Core.DomainModel.Organization.DomainEvents; using Core.DomainServices; using Core.DomainServices.Extensions; +using Infrastructure.Services.DataAccess; using Serilog; namespace Core.ApplicationServices.Organizations @@ -14,20 +18,29 @@ public class OrganizationRightsService : IOrganizationRightsService { private readonly IAuthorizationContext _authorizationContext; private readonly IGenericRepository _organizationRightRepository; + private readonly IGenericRepository _unitRightRepository; private readonly IOrganizationalUserContext _userContext; private readonly IDomainEvents _domainEvents; private readonly ILogger _logger; + private readonly ITransactionManager _transactionManager; + private readonly IGenericRepository _organizationRepository; public OrganizationRightsService(IAuthorizationContext authorizationContext, IGenericRepository organizationRightRepository, IOrganizationalUserContext userContext, - IDomainEvents domainEvents, ILogger logger) + IDomainEvents domainEvents, ILogger logger, + IGenericRepository unitRightRepository, + ITransactionManager transactionManager, + IGenericRepository organizationRepository) { _authorizationContext = authorizationContext; _organizationRightRepository = organizationRightRepository; _userContext = userContext; _domainEvents = domainEvents; _logger = logger; + _unitRightRepository = unitRightRepository; + _transactionManager = transactionManager; + _organizationRepository = organizationRepository; } public Result AssignRole(int organizationId, int userId, OrganizationRole roleId) @@ -75,6 +88,141 @@ public Result RemoveRole(int rightId) return RemoveRight(right); } + public Maybe RemoveUnitRightsByIds(Guid organizationUuid, Guid unitUuid, IEnumerable rightIds) + { + using var transaction = _transactionManager.Begin(); + + var unitResult = GetOrganizationUnitByUuidAndAuthorizeModification(organizationUuid, unitUuid); + if (unitResult.Failed) + { + return unitResult.Error; + } + var unit = unitResult.Value; + + var rightsToDelete = new List(); + foreach (var rightId in rightIds) + { + var organizationUnitRightResult = unit.GetRight(rightId); + if (organizationUnitRightResult.IsNone) + { + return new OperationError($"Organization unit right with id: {rightId} was not found", OperationFailure.NotFound); + } + var rightToRemove = organizationUnitRightResult.Value; + + var result = unit.RemoveRole(rightToRemove.Role, rightToRemove.User); + if (result.Failed) + { + transaction.Rollback(); + return result.Error; + } + + rightsToDelete.Add(rightToRemove); + } + var userIds = rightsToDelete.Select(x => x.UserId).ToList(); + + _unitRightRepository.RemoveRange(rightsToDelete); + foreach (var userId in userIds.Distinct()) + { + _domainEvents.Raise(new AdministrativeAccessRightsChanged(userId)); + } + _unitRightRepository.Save(); + transaction.Commit(); + + return Maybe.None; + } + + public Maybe TransferUnitRightsByIds(Guid organizationUuid, Guid unitUuid, Guid targetUnitUuid, IEnumerable rightIds) + { + using var transaction = _transactionManager.Begin(); + + var organizationResult = GetOrganizationAndAuthorizeModification(organizationUuid); + if (organizationResult.Failed) + { + return organizationResult.Error; + } + var organization = organizationResult.Value; + + var unitResult = GetOrganizationUnitAndAuthorizeModification(organization, unitUuid); + if (unitResult.Failed) + { + return unitResult.Error; + } + + var targetUnitResult = GetOrganizationUnitAndAuthorizeModification(organization, targetUnitUuid); + if (targetUnitResult.Failed) + { + return targetUnitResult.Error; + } + + var currentUnit = unitResult.Value; + var targetUnit = targetUnitResult.Value; + + var rightsToDelete = new List(); + foreach (var rightId in rightIds) + { + var organizationUnitRightResult = currentUnit.GetRight(rightId); + + if (organizationUnitRightResult.IsNone) + { + return new OperationError($"Organization unit right with id: {rightId} was not found", OperationFailure.NotFound); + } + var right = organizationUnitRightResult.Value; + + var removeRightResult = currentUnit.RemoveRole(right.Role, right.User); + if (removeRightResult.Failed) + { + transaction.Rollback(); + return removeRightResult.Error; + } + var removedRight = removeRightResult.Value; + rightsToDelete.Add(removedRight); + + //Check if a right with the same role and user is already assigned to the target + var rightsWithSameRole = targetUnit.GetRights(removedRight.RoleId); + if (!rightsWithSameRole.Any(x => x.UserId == removedRight.UserId)) + { + var assignRightResult = targetUnit.AssignRole(removedRight.Role, removedRight.User); + if (assignRightResult.Failed) + { + transaction.Rollback(); + return assignRightResult.Error; + } + } + + _domainEvents.Raise(new AdministrativeAccessRightsChanged(removedRight.UserId)); + } + + _unitRightRepository.RemoveRange(rightsToDelete); + _unitRightRepository.Save(); + transaction.Commit(); + + return Maybe.None; + } + + private Result GetOrganizationUnitByUuidAndAuthorizeModification(Guid organizationUuid, Guid unitUuid) + { + return GetOrganizationAndAuthorizeModification(organizationUuid) + .Bind(organization => GetOrganizationUnitAndAuthorizeModification(organization, unitUuid)); + } + + private Result GetOrganizationUnitAndAuthorizeModification(Organization organization, Guid unitUuid) + { + return organization.GetOrganizationUnit(unitUuid) + .Match + ( + WithModificationAccess, + () => new OperationError($"Unit with uuid: {unitUuid} was not found", OperationFailure.NotFound) + ); + } + + private Result GetOrganizationAndAuthorizeModification(Guid uuid) + { + var organization = _organizationRepository.AsQueryable().FirstOrDefault(x => x.Uuid == uuid); + return organization == null + ? new OperationError($"Organization with uuid: {uuid} was not found", OperationFailure.NotFound) + : WithModificationAccess(organization); + } + private Result RemoveRight(OrganizationRight right) { if (right == null) @@ -99,5 +247,10 @@ private Result RemoveRight(OrganizationRigh return right; } + + private Result WithModificationAccess(T entity) where T : IEntity + { + return _authorizationContext.AllowModify(entity) ? Result.Success(entity) : new OperationError(OperationFailure.Forbidden); + } } } diff --git a/Core.ApplicationServices/Organizations/OrganizationUnitService.cs b/Core.ApplicationServices/Organizations/OrganizationUnitService.cs new file mode 100644 index 0000000000..c388ffa94e --- /dev/null +++ b/Core.ApplicationServices/Organizations/OrganizationUnitService.cs @@ -0,0 +1,483 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web.UI.WebControls; +using Core.Abstractions.Extensions; +using Core.Abstractions.Types; +using Core.ApplicationServices.Authorization; +using Core.ApplicationServices.Contract; +using Core.ApplicationServices.Model.Organizations; +using Core.ApplicationServices.SystemUsage; +using Core.DomainModel.Commands; +using Core.DomainModel.Events; +using Core.DomainModel.Organization; +using Core.DomainServices; +using Core.DomainServices.Authorization; +using Infrastructure.Services.DataAccess; + +namespace Core.ApplicationServices.Organizations +{ + public class OrganizationUnitService : IOrganizationUnitService + { + private readonly IOrganizationService _organizationService; + private readonly IOrganizationRightsService _organizationRightsService; + private readonly IItContractService _contractService; + private readonly IItSystemUsageService _usageService; + private readonly IAuthorizationContext _authorizationContext; + private readonly ITransactionManager _transactionManager; + private readonly IDomainEvents _domainEvents; + private readonly IDatabaseControl _databaseControl; + private readonly IGenericRepository _repository; + private readonly ICommandBus _commandBus; + + public OrganizationUnitService(IOrganizationService organizationService, + IOrganizationRightsService organizationRightsService, + IItContractService contractService, + IItSystemUsageService usageService, + IAuthorizationContext authorizationContext, + ITransactionManager transactionManager, + IDomainEvents domainEvents, + IDatabaseControl databaseControl, + IGenericRepository repository, + ICommandBus commandBus) + { + _organizationService = organizationService; + _organizationRightsService = organizationRightsService; + _contractService = contractService; + _usageService = usageService; + _authorizationContext = authorizationContext; + _transactionManager = transactionManager; + _domainEvents = domainEvents; + _databaseControl = databaseControl; + _repository = repository; + _commandBus = commandBus; + } + + public Result GetAccessRights(Guid organizationUuid, Guid unitUuid) + { + return _organizationService + .GetOrganization(organizationUuid, OrganizationDataReadAccessLevel.All) + .Bind<(Organization organization, OrganizationUnit organizationUnit)> + ( + organization => + { + var unit = organization.GetOrganizationUnit(unitUuid); + if (unit.IsNone) + { + return new OperationError($"Organization unit with uuid: {unitUuid} was not found", OperationFailure.NotFound); + } + return (organization, unit.Value); + } + ) + .Select(orgAndUnit => GetAccessRights(orgAndUnit.organization, orgAndUnit.organizationUnit)); + } + + public Result, OperationError> GetAccessRightsByOrganization(Guid organizationUuid) + { + return _organizationService + .GetOrganization(organizationUuid, OrganizationDataReadAccessLevel.All) + .Select + ( + organization => + { + var units = organization.GetAllOrganizationUnits(); + return (organization, units); + } + ) + .Select(orgAndUnits => + orgAndUnits + .units + .Select(unit => new UnitAccessRightsWithUnitData(unit, GetAccessRights(orgAndUnits.organization, unit))) + .ToList() + .AsEnumerable() + ); + } + + public Maybe Delete(Guid organizationUuid, Guid unitUuid) + { + using var transaction = _transactionManager.Begin(); + var deleteResult = GetOrganizationAndAuthorizeModification(organizationUuid) + .Bind(organization => CombineWithOrganizationUnit(unitUuid, organization)) + .Bind(WithDeletionPermission) + .Bind(DeleteOrganizationUnit); + + if (deleteResult.Failed) + { + transaction.Rollback(); + } + else + { + _domainEvents.Raise(new EntityBeingDeletedEvent(deleteResult.Value)); + _databaseControl.SaveChanges(); + transaction.Commit(); + } + return deleteResult.MatchFailure(); + } + + public Maybe DeleteRegistrations(Guid organizationUuid, Guid unitUuid, OrganizationUnitRegistrationChangeParameters parameters) + { + return Modify(organizationUuid, unitUuid, (_, unit) => + { + return _organizationRightsService.RemoveUnitRightsByIds(organizationUuid, unitUuid, parameters.OrganizationUnitRights) + .Match + ( + error => error, + () => RemovePaymentResponsibleUnits(parameters.PaymentRegistrationDetails) + ) + .Match + ( + error => error, + () => RemoveContractRegistrations(parameters.ItContractRegistrations) + ) + .Match + ( + error => error, + () => RemoveSystemResponsibleRegistrations(parameters.ResponsibleSystems) + ) + .Match + ( + error => error, + () => RemoveSystemRelevantUnits(parameters.RelevantSystems, unitUuid) + ) + .Match + ( + error => error, + () => Result.Success(unit) + ); + }).MatchFailure(); + } + + public Maybe DeleteRegistrations(Guid organizationUuid, Guid unitUuid) + { + return Modify(organizationUuid, unitUuid, (_, unit) => + { + return GetRegistrations(organizationUuid, unitUuid) + .Bind + ( + details => + { + var error = DeleteRegistrations(organizationUuid, unitUuid, ToChangeParametersFromRegistrationDetails(details)); + if (error.HasValue) + { + return error.Value; + } + + return unit; + } + ); + }).MatchFailure(); + } + + public Maybe TransferRegistrations(Guid organizationUuid, Guid unitUuid, Guid targetUnitUuid, OrganizationUnitRegistrationChangeParameters parameters) + { + return Modify(organizationUuid, unitUuid, (organization, unit) => + { + var targetUnitResult = organization.GetOrganizationUnit(targetUnitUuid); + if (targetUnitResult.IsNone) + { + return new OperationError($"Unit with uuid: {targetUnitUuid} was not found", + OperationFailure.NotFound); + } + + var targetUnit = targetUnitResult.Value; + + if (!_authorizationContext.AllowModify(targetUnit)) + { + return new OperationError(OperationFailure.Forbidden); + } + + var error = _organizationRightsService.TransferUnitRightsByIds(organizationUuid, unitUuid, + targetUnitUuid, parameters.OrganizationUnitRights) + .Match + ( + error => error, + () => TransferPayments(targetUnitUuid, parameters.PaymentRegistrationDetails) + ) + .Match + ( + error => error, + () => TransferContractRegistrations(targetUnitUuid, parameters.ItContractRegistrations) + ) + .Match + ( + error => error, + () => TransferSystemResponsibleRegistrations(targetUnitUuid, parameters.ResponsibleSystems) + ) + .Match + ( + error => error, + () => TransferSystemRelevantRegistrations(unitUuid, targetUnitUuid, parameters.RelevantSystems) + ); + + if (error.HasValue) + { + return error.Value; + } + + _domainEvents.Raise(new EntityUpdatedEvent(targetUnitResult.Value)); + + return Result.Success(unit); + }).MatchFailure(); + } + + private Result Modify(Guid organizationId, Guid unitUuid, Func> mutation) + { + using var transaction = _transactionManager.Begin(); + + var organizationResult = GetOrganizationAndAuthorizeModification(organizationId); + + if (organizationResult.Failed) + { + return organizationResult.Error; + } + var organization = organizationResult.Value; + + var unitResult = organization.GetOrganizationUnit(unitUuid); + if (unitResult.IsNone) + { + return new OperationError($"Unit with uuid: {unitUuid} was not found", OperationFailure.NotFound); + } + var unit = unitResult.Value; + + if (!_authorizationContext.AllowModify(unit)) + return new OperationError(OperationFailure.Forbidden); + + var mutationResult = mutation(organization, unit); + + if (mutationResult.Failed) + { + transaction.Rollback(); + } + else + { + _repository.Update(unit); + _domainEvents.Raise(new EntityUpdatedEvent(unitResult.Value)); + _databaseControl.SaveChanges(); + transaction.Commit(); + } + + return mutationResult; + } + + private Result GetOrganizationAndAuthorizeModification(Guid uuid) + { + return _organizationService.GetOrganization(uuid, OrganizationDataReadAccessLevel.All) + .Match + ( + organization => + _authorizationContext.AllowModify(organization) == false + ? new OperationError("User is not allowed to modify the organization", OperationFailure.Forbidden) + : Result.Success(organization), + error => error + ); + } + + private UnitAccessRights GetAccessRights(Organization organization, OrganizationUnit unit) + { + if (!_authorizationContext.AllowModify(unit)) + return UnitAccessRights.ReadOnly(); + + const bool canBeModified = true; + var canBeRenamed = false; + const bool canInfoAdditionalfieldsBeModified = true; + var canBeRearranged = false; + var canBeDeleted = false; + + if (unit.IsNativeKitosUnit()) + { + canBeRenamed = true; + + if (organization.GetRoot() != unit) + { + canBeRearranged = true; + canBeDeleted = true; + } + } + if (!_authorizationContext.AllowDelete(unit)) + { + canBeDeleted = false; + } + + return new UnitAccessRights(canBeRead: true, canBeModified, canBeRenamed, canInfoAdditionalfieldsBeModified, canBeRearranged, canBeDeleted); + } + + private Maybe RemovePaymentResponsibleUnits(IEnumerable payments) + { + foreach (var payment in payments) + { + var removeInternalPaymentsError = _contractService.RemovePaymentResponsibleUnits(payment.ItContractId, true, payment.InternalPayments); + if (removeInternalPaymentsError.HasValue) + return removeInternalPaymentsError.Value; + + var removeExternalPaymentsError = _contractService.RemovePaymentResponsibleUnits(payment.ItContractId, false, payment.ExternalPayments); + if (removeExternalPaymentsError.HasValue) + return removeExternalPaymentsError.Value; + } + + return Maybe.None; + } + + private Maybe RemoveContractRegistrations(IEnumerable contractIds) + { + foreach (var contractId in contractIds) + { + var deleteError = _contractService.RemoveResponsibleUnit(contractId); + if (deleteError.HasValue) + return deleteError.Value; + } + + return Maybe.None; + } + + private Maybe RemoveSystemRelevantUnits(IEnumerable systemIds, Guid unitUuid) + { + foreach (var systemId in systemIds) + { + var deleteError = _usageService.RemoveRelevantUnit(systemId, unitUuid); + if (deleteError.HasValue) + return deleteError.Value; + } + + return Maybe.None; + } + + private Maybe RemoveSystemResponsibleRegistrations(IEnumerable systemIds) + { + foreach (var systemId in systemIds) + { + var deleteError = _usageService.RemoveResponsibleUsage(systemId); + if (deleteError.HasValue) + return deleteError.Value; + } + + return Maybe.None; + } + + private Maybe TransferPayments(Guid targetUnitUuid, IEnumerable payments) + { + foreach (var payment in payments) + { + var transferInternalPaymentsError = _contractService.TransferPayments(payment.ItContractId, targetUnitUuid, true, payment.InternalPayments); + if (transferInternalPaymentsError.HasValue) + return transferInternalPaymentsError.Value; + + var transferExternalPaymentsError = _contractService.TransferPayments(payment.ItContractId, targetUnitUuid, false, payment.ExternalPayments); + if (transferExternalPaymentsError.HasValue) + return transferExternalPaymentsError.Value; + } + + return Maybe.None; + } + + private Maybe TransferSystemResponsibleRegistrations(Guid targetUnitUuid, IEnumerable systemIds) + { + foreach (var systemId in systemIds) + { + var transferError = _usageService.TransferResponsibleUsage(systemId, targetUnitUuid); + if (transferError.HasValue) + return transferError.Value; + } + + return Maybe.None; + } + + private Maybe TransferContractRegistrations(Guid targetUnitUuid, IEnumerable contractIds) + { + foreach (var contractId in contractIds) + { + var transferError = _contractService.SetResponsibleUnit(contractId, targetUnitUuid); + if (transferError.HasValue) + return transferError.Value; + } + + return Maybe.None; + } + + private Maybe TransferSystemRelevantRegistrations(Guid unitUuid, Guid targetUnitUuid, IEnumerable systemIds) + { + foreach (var systemId in systemIds) + { + var transferError = _usageService.TransferRelevantUsage(systemId, unitUuid, targetUnitUuid); + if (transferError.HasValue) + return transferError.Value; + } + + return Maybe.None; + } + + private static OrganizationUnitRegistrationChangeParameters ToChangeParametersFromRegistrationDetails( + OrganizationUnitRegistrationDetails unitRegistrations) + { + var itContractRegistrations = unitRegistrations.ItContractRegistrations.Select(x => x.Id).ToList(); + var organizationUnitRights = unitRegistrations.OrganizationUnitRights.Select(x => x.Id).ToList(); + var paymentRegistrationDetails = unitRegistrations.PaymentRegistrationDetails.Select + (x => + new PaymentChangeParameters + ( + x.ItContract.Id, + x.InternalPayments.Select(ip => ip.Id).ToList(), + x.ExternalPayments.Select(ep => ep.Id).ToList() + ) + ).ToList(); + var relevantSystems = unitRegistrations.RelevantSystems.Select(x => x.Id).ToList(); + var responsibleSystems = unitRegistrations.ResponsibleSystems.Select(x => x.Id).ToList(); + + return new OrganizationUnitRegistrationChangeParameters(organizationUnitRights, itContractRegistrations, paymentRegistrationDetails, responsibleSystems, relevantSystems); + } + + private Result DeleteOrganizationUnit((Organization organization, OrganizationUnit organizationUnit) orgAndUnit) + { + var (organization, organizationUnit) = orgAndUnit; + var deleteCommand = new RemoveOrganizationUnitRegistrationsCommand(organization, organizationUnit); + var deleteRegistrationsError = _commandBus.Execute>(deleteCommand); + if (deleteRegistrationsError.HasValue) + { + return deleteRegistrationsError.Value; + } + + var error = organization.DeleteOrganizationUnit(organizationUnit); + if (error.HasValue) + { + return error.Value; + } + + _repository.DeleteWithReferencePreload(organizationUnit); + return organizationUnit; + } + + private Result<(Organization organization, OrganizationUnit organizationUnit), OperationError> WithDeletionPermission((Organization organization, OrganizationUnit organizationUnit) orgAndUnit) + { + var accessRights = GetAccessRights(orgAndUnit.organization, orgAndUnit.organizationUnit); + if (accessRights.CanBeDeleted == false) + return new OperationError("Not authorized to delete org unit", OperationFailure.Forbidden); + + return orgAndUnit; + } + + private static Result<(Organization organization, OrganizationUnit organizationUnit), OperationError> CombineWithOrganizationUnit(Guid unitUuid, Organization organization) + { + var organizationUnit = organization.GetOrganizationUnit(unitUuid); + if (organizationUnit.IsNone) + return new OperationError(OperationFailure.NotFound); + return (organization, organizationUnit.Value); + } + + public Result GetRegistrations(Guid organizationUuid, Guid unitUuid) + { + return _organizationService + .GetOrganization(organizationUuid, OrganizationDataReadAccessLevel.All) + .Bind + ( + organization => + { + var unit = organization.GetOrganizationUnit(unitUuid); + if (unit.IsNone) + return new OperationError($"Organization unit with uuid: {unitUuid} was not found", OperationFailure.NotFound); + + return unit.Value; + } + ) + .Select(unit => unit.GetUnitRegistrations()); + } + } +} diff --git a/Core.ApplicationServices/Organizations/StsOrganizationSynchronizationService.cs b/Core.ApplicationServices/Organizations/StsOrganizationSynchronizationService.cs index 5ace41bf55..90ab624375 100644 --- a/Core.ApplicationServices/Organizations/StsOrganizationSynchronizationService.cs +++ b/Core.ApplicationServices/Organizations/StsOrganizationSynchronizationService.cs @@ -1,11 +1,17 @@ using System; +using System.Linq; using Core.Abstractions.Types; using Core.ApplicationServices.Authorization; using Core.ApplicationServices.Authorization.Permissions; +using Core.ApplicationServices.Model.Organizations; +using Core.DomainModel.Events; using Core.DomainModel.Organization; +using Core.DomainServices; using Core.DomainServices.Model.StsOrganization; using Core.DomainServices.Organizations; +using Infrastructure.Services.DataAccess; using Serilog; +using Organization = Core.DomainModel.Organization.Organization; namespace Core.ApplicationServices.Organizations { @@ -14,38 +20,156 @@ public class StsOrganizationSynchronizationService : IStsOrganizationSynchroniza private readonly IStsOrganizationUnitService _stsOrganizationUnitService; private readonly IOrganizationService _organizationService; private readonly ILogger _logger; + private readonly IStsOrganizationService _stsOrganizationService; + private readonly IDatabaseControl _databaseControl; + private readonly ITransactionManager _transactionManager; + private readonly IDomainEvents _domainEvents; + private readonly IGenericRepository _organizationUnitRepository; private readonly IAuthorizationContext _authorizationContext; public StsOrganizationSynchronizationService( IAuthorizationContext authorizationContext, IStsOrganizationUnitService stsOrganizationUnitService, IOrganizationService organizationService, - ILogger logger) + ILogger logger, + IStsOrganizationService stsOrganizationService, + IDatabaseControl databaseControl, + ITransactionManager transactionManager, + IDomainEvents domainEvents, + IGenericRepository organizationUnitRepository) { _stsOrganizationUnitService = stsOrganizationUnitService; _organizationService = organizationService; _logger = logger; + _stsOrganizationService = stsOrganizationService; + _databaseControl = databaseControl; + _transactionManager = transactionManager; + _domainEvents = domainEvents; + _organizationUnitRepository = organizationUnitRepository; _authorizationContext = authorizationContext; } - public Result GetStsOrganizationalHierarchy(Guid organizationId, Maybe levelsToInclude) + public Result GetSynchronizationDetails(Guid organizationId) { - var orgWithPermission = _organizationService - .GetOrganization(organizationId) - .Bind(WithImportPermission); + return GetOrganizationWithImportPermission(organizationId) + .Select(organization => + { + var currentConnectionStatus = ValidateConnection(organization); + var isConnected = organization.StsOrganizationConnection?.Connected == true; + var canCreateConnection = currentConnectionStatus.IsNone && organization.StsOrganizationConnection?.Connected != true; + var canUpdateConnection = currentConnectionStatus.IsNone && isConnected; + return new StsOrganizationSynchronizationDetails + ( + isConnected, + organization.StsOrganizationConnection?.SynchronizationDepth, + canCreateConnection, + canUpdateConnection, + isConnected, + currentConnectionStatus.Match(error => error.Detail, () => default(CheckConnectionError?)) + ); + }); + } - if (orgWithPermission.Failed) - return orgWithPermission.Error; + private Maybe> ValidateConnection(Organization organization) + { + return _stsOrganizationService.ValidateConnection(organization); + } - var organization = orgWithPermission.Value; - var orgTreeResult = _stsOrganizationUnitService.ResolveOrganizationTree(organization); - if (orgTreeResult.Failed) + public Result GetStsOrganizationalHierarchy(Guid organizationId, Maybe levelsToInclude) + { + return + GetOrganizationWithImportPermission(organizationId) + .Bind(LoadOrganizationUnits) + .Bind(root => FilterByRequestedLevels(root, levelsToInclude)); + } + + public Maybe Connect(Guid organizationId, Maybe levelsToInclude) + { + return Modify(organizationId, organization => { - var detailedOperationError = orgTreeResult.Error; - return new OperationError($"Failed to load organization tree:{detailedOperationError.Detail:G}:{detailedOperationError.FailureType:G}:{detailedOperationError.Message}", detailedOperationError.FailureType); - } + return LoadOrganizationUnits(organization) + .Match + ( + importRoot => + { + var error = organization.ConnectToExternalOrganizationHierarchy(OrganizationUnitOrigin.STS_Organisation, importRoot, levelsToInclude); + if (error.HasValue) + { + _logger.Error("Failed to import org root {rootId} and subtree into organization with id {orgId}. Failed with: {errorCode}:{errorMessage}", importRoot.Uuid, organization.Id, error.Value.FailureType, error.Value.Message.GetValueOrFallback("")); + return new OperationError("Failed to import sub tree", OperationFailure.UnknownError); + } - return FilterByRequestedLevels(orgTreeResult.Value, levelsToInclude); + return Maybe.None; + }, + error => error + ); + }); + } + + public Maybe Disconnect(Guid organizationId) + { + return Modify(organizationId, organization => + { + var result = organization.DisconnectOrganizationFromExternalSource(OrganizationUnitOrigin.STS_Organisation); + if (result.Failed) + { + return result.Error; + } + + var disconnectionResult = result.Value; + foreach (var convertedUnit in disconnectionResult.ConvertedUnits) + { + _domainEvents.Raise(new EntityUpdatedEvent(convertedUnit)); + } + return Maybe.None; + }); + } + + public Result GetConnectionExternalHierarchyUpdateConsequences(Guid organizationId, Maybe levelsToInclude) + { + return GetOrganizationWithImportPermission(organizationId) + .Match(organization => + LoadOrganizationUnits(organization) + .Bind(root => organization + .ComputeExternalOrganizationHierarchyUpdateConsequences( + OrganizationUnitOrigin.STS_Organisation, root, levelsToInclude)) + , + error => error + ); + } + + public Maybe UpdateConnection(Guid organizationId, Maybe levelsToInclude) + { + return Modify(organizationId, organization => + LoadOrganizationUnits(organization) + .Bind(importRoot => organization.UpdateConnectionToExternalOrganizationHierarchy(OrganizationUnitOrigin.STS_Organisation, importRoot, levelsToInclude)) + .Select(consequences => + { + if (consequences.DeletedExternalUnitsBeingDeleted.Any()) + { + _organizationUnitRepository.RemoveRange(consequences.DeletedExternalUnitsBeingDeleted); + } + foreach (var (affectedUnit, _, _) in consequences.OrganizationUnitsBeingRenamed) + { + _domainEvents.Raise(new EntityUpdatedEvent(affectedUnit)); + } + return consequences; + }) + .Match(_ => Maybe.None, error => error) + ); + } + + + private Result LoadOrganizationUnits(Organization organization) + { + return _stsOrganizationUnitService.ResolveOrganizationTree(organization).Match>(root => root, detailedOperationError => new OperationError($"Failed to load organization tree:{detailedOperationError.Detail:G}:{detailedOperationError.FailureType:G}:{detailedOperationError.Message}", detailedOperationError.FailureType)); + } + + private Result GetOrganizationWithImportPermission(Guid organizationId) + { + return _organizationService + .GetOrganization(organizationId) + .Bind(WithImportPermission); } private Result WithImportPermission(Organization organization) @@ -57,21 +181,45 @@ private Result WithImportPermission(Organization o return new OperationError($"The user does not have permission to use the STS Organization Sync functionality for the organization with uuid:{organization.Uuid}", OperationFailure.Forbidden); } - private static Result FilterByRequestedLevels(StsOrganizationUnit root, Maybe levelsToInclude) + private static Result FilterByRequestedLevels(ExternalOrganizationUnit root, Maybe levelsToInclude) { if (levelsToInclude.IsNone) { return root; } - var levels = levelsToInclude.Value; - if (levels < 1) + if (levelsToInclude.Value < 1) { return new OperationError($"{nameof(levelsToInclude)} must be greater than or equal to 1", OperationFailure.BadInput); } - levels--; - return root.Copy(levels); + return root.Copy(levelsToInclude.Select(levels => levels - 1)); + } + + private Maybe Modify(Guid organizationUuid, Func> mutate) + { + using var transaction = _transactionManager.Begin(); + + var organizationResult = GetOrganizationWithImportPermission(organizationUuid); + if (organizationResult.Failed) + { + _logger.Warning("Failed while loading import org ({uuid}) with import permission. {errorCode}:{errorMessage}", organizationUuid, organizationResult.Error.FailureType, organizationResult.Error.Message.GetValueOrFallback("no-error")); + return organizationResult.Error; + } + + var organization = organizationResult.Value; + var mutationError = mutate(organization); + if (mutationError.HasValue) + { + transaction.Rollback(); + return mutationError; + } + + _domainEvents.Raise(new EntityUpdatedEvent(organization)); + _databaseControl.SaveChanges(); + transaction.Commit(); + + return Maybe.None; } } } diff --git a/Core.ApplicationServices/Rights/UserRightsService.cs b/Core.ApplicationServices/Rights/UserRightsService.cs index 2b7341de1b..424233bcf0 100644 --- a/Core.ApplicationServices/Rights/UserRightsService.cs +++ b/Core.ApplicationServices/Rights/UserRightsService.cs @@ -199,7 +199,7 @@ private Maybe MutateUserRights( int organizationId, Func<(Organization organization, User user, IEnumerable dprRights, IEnumerable contractRights, IEnumerable systemRights, IEnumerable organizationUnitRights, IEnumerable rolesInOrganization), Maybe> mutation) { - var transaction = _transactionManager.Begin(); + using var transaction = _transactionManager.Begin(); var uuidResult = _identityResolver.ResolveUuid(organizationId); if (uuidResult.IsNone) diff --git a/Core.ApplicationServices/System/ItSystemService.cs b/Core.ApplicationServices/System/ItSystemService.cs index d75e32ccec..c981306fdc 100644 --- a/Core.ApplicationServices/System/ItSystemService.cs +++ b/Core.ApplicationServices/System/ItSystemService.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Data; using System.Linq; using Core.Abstractions.Extensions; using Core.Abstractions.Types; @@ -8,12 +7,12 @@ using Core.ApplicationServices.Extensions; using Core.ApplicationServices.Helpers; using Core.ApplicationServices.Interface; -using Core.ApplicationServices.Model.Shared; using Core.ApplicationServices.Model.System; using Core.ApplicationServices.References; using Core.ApplicationServices.SystemUsage; using Core.DomainModel; using Core.DomainModel.Events; +using Core.DomainModel.Extensions; using Core.DomainModel.ItSystem; using Core.DomainModel.ItSystemUsage; using Core.DomainModel.Organization; @@ -149,40 +148,12 @@ public IQueryable GetAvailableSystems(int organizationId, string optio public IEnumerable GetHierarchy(int systemId) { - var result = new List(); var system = _itSystemRepository.GetSystem(systemId); if (system == null) throw new ArgumentException("Invalid system id"); - result.Add(system); - result.AddRange(GetHierarchyChildren(system)); - result.AddRange(GetHierarchyParents(system)); - - return result; - } - - private static IEnumerable GetHierarchyChildren(ItSystem itSystem) - { - var systems = new List(); - systems.AddRange(itSystem.Children); - foreach (var child in itSystem.Children) - { - var children = GetHierarchyChildren(child); - systems.AddRange(children); - } - return systems; - } - - private static IEnumerable GetHierarchyParents(ItSystem itSystem) - { - var parents = new List(); - if (itSystem.Parent != null) - { - parents.Add(itSystem.Parent); - parents.AddRange(GetHierarchyParents(itSystem.Parent)); - } - return parents; + return system.FlattenCompleteHierarchy().ToList(); } public SystemDeleteResult Delete(int id, bool breakBindings = false) @@ -204,7 +175,7 @@ public SystemDeleteResult Delete(int id, bool breakBindings = false) { if (breakBindings) { - var failedUsageDeletion = system.Usages.ToList().Select(usage=>_systemUsageService.Delete(usage.Id)).FirstOrDefault(x=>x.Failed); + var failedUsageDeletion = system.Usages.ToList().Select(usage => _systemUsageService.Delete(usage.Id)).FirstOrDefault(x => x.Failed); if (failedUsageDeletion != null) { _logger.Error("Failed to delete system with id {id} because deleting usages failed", id); @@ -246,11 +217,11 @@ public SystemDeleteResult Delete(int id, bool breakBindings = false) var failedUpdate = system .ItInterfaceExhibits .ToList() - .Select(exhibit=>_interfaceService.UpdateExposingSystem(exhibit.ItInterface.Id,null)) - .FirstOrDefault(x=>x.Failed); + .Select(exhibit => _interfaceService.UpdateExposingSystem(exhibit.ItInterface.Id, null)) + .FirstOrDefault(x => x.Failed); if (failedUpdate != null) { - _logger.Error("Failed to delete system with id {id} because deleting interface exposures failed",id); + _logger.Error("Failed to delete system with id {id} because deleting interface exposures failed", id); return SystemDeleteResult.UnknownError; } system.ItInterfaceExhibits.Clear(); diff --git a/Core.ApplicationServices/SystemUsage/IItSystemUsageService.cs b/Core.ApplicationServices/SystemUsage/IItSystemUsageService.cs index b888820018..dfafe0bc8e 100644 --- a/Core.ApplicationServices/SystemUsage/IItSystemUsageService.cs +++ b/Core.ApplicationServices/SystemUsage/IItSystemUsageService.cs @@ -5,6 +5,7 @@ using Core.DomainModel.ItSystem; using Core.DomainModel.ItSystemUsage; using Core.DomainModel.ItSystemUsage.GDPR; +using Core.DomainModel.Organization; using Core.DomainServices.Queries; namespace Core.ApplicationServices.SystemUsage @@ -38,5 +39,9 @@ public interface IItSystemUsageService Result, OperationError> RemoveAllArchivePeriods(int systemUsageId); Result AddArchivePeriod(int systemUsageId, DateTime startDate, DateTime endDate, string archiveId, bool approved); Result GetItSystemUsageById(int usageId); + Maybe TransferResponsibleUsage(int systemId, Guid targetUnitUuid); + Maybe TransferRelevantUsage(int systemId, Guid unitUuid, Guid targetUnitUuid); + Maybe RemoveResponsibleUsage(int id); + Maybe RemoveRelevantUnit(int id, Guid unitUuid); } } \ No newline at end of file diff --git a/Core.ApplicationServices/SystemUsage/ItSystemUsageService.cs b/Core.ApplicationServices/SystemUsage/ItSystemUsageService.cs index e4f961f5a6..00c9d397f0 100644 --- a/Core.ApplicationServices/SystemUsage/ItSystemUsageService.cs +++ b/Core.ApplicationServices/SystemUsage/ItSystemUsageService.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System; -using System.Data; using System.Linq; using Core.Abstractions.Extensions; using Core.Abstractions.Types; @@ -44,7 +43,7 @@ public ItSystemUsageService( IDomainEvents domainEvents, IGenericRepository sensitiveDataLevelRepository, IOrganizationalUserContext userContext, - IItSystemUsageAttachedOptionRepository itSystemUsageAttachedOptionRepository, + IItSystemUsageAttachedOptionRepository itSystemUsageAttachedOptionRepository, IGenericRepository archivePeriodRepository) { _usageRepository = usageRepository; @@ -145,34 +144,32 @@ private static bool AllowUsageInTargetOrganization(ItSystemUsage newSystemUsage, public Result Delete(int id) { - using (var transaction = _transactionManager.Begin()) + using var transaction = _transactionManager.Begin(); + var itSystemUsage = GetById(id); + if (itSystemUsage == null) { - var itSystemUsage = GetById(id); - if (itSystemUsage == null) - { - return new OperationError($"Could not find it system usage with Id: {id}", OperationFailure.NotFound); - } - if (!_authorizationContext.AllowDelete(itSystemUsage)) - { - return new OperationError($"Not allowed to delete it system usage with Id: {id}", OperationFailure.Forbidden); - } - - // delete it system usage - var deleteBySystemUsageId = _referenceService.DeleteBySystemUsageId(id); - if (deleteBySystemUsageId.Failed) - { - transaction.Rollback(); - return new OperationError($"Failed to delete it system usage with Id: {id}. Failed to delete references", deleteBySystemUsageId.Error); - } - - _itSystemUsageAttachedOptionRepository.DeleteAllBySystemUsageId(id); - - _domainEvents.Raise(new EntityBeingDeletedEvent(itSystemUsage)); - _usageRepository.DeleteByKeyWithReferencePreload(id); - _usageRepository.Save(); - transaction.Commit(); - return itSystemUsage; + return new OperationError($"Could not find it system usage with Id: {id}", OperationFailure.NotFound); + } + if (!_authorizationContext.AllowDelete(itSystemUsage)) + { + return new OperationError($"Not allowed to delete it system usage with Id: {id}", OperationFailure.Forbidden); } + + // delete it system usage + var deleteBySystemUsageId = _referenceService.DeleteBySystemUsageId(id); + if (deleteBySystemUsageId.Failed) + { + transaction.Rollback(); + return new OperationError($"Failed to delete it system usage with Id: {id}. Failed to delete references", deleteBySystemUsageId.Error); + } + + _itSystemUsageAttachedOptionRepository.DeleteAllBySystemUsageId(id); + + _domainEvents.Raise(new EntityBeingDeletedEvent(itSystemUsage)); + _usageRepository.DeleteByKeyWithReferencePreload(id); + _usageRepository.Save(); + transaction.Commit(); + return itSystemUsage; } public ItSystemUsage GetByOrganizationAndSystemId(int organizationId, int systemId) @@ -287,6 +284,56 @@ public Result AddArchivePeriod(int systemUsageId, return Modify(systemUsageId, usage => usage.AddArchivePeriod(startDate, endDate, archiveId, approved)); } + public Maybe TransferResponsibleUsage(int systemId, Guid targetUnitUuid) + { + return Modify(systemId, system => + { + var error = system.TransferResponsibleOrganizationalUnit(targetUnitUuid); + return error.HasValue + ? error.Value + : Result.Success(system); + }).MatchFailure(); + } + + public Maybe TransferRelevantUsage(int systemId, Guid unitUuid, Guid targetUnitUuid) + { + return Modify(systemId, system => + { + return system.TransferUsedByUnit(unitUuid, targetUnitUuid) + .Match + ( + error => error, + () => Result.Success(system) + ); + }).MatchFailure(); + } + + public Maybe RemoveResponsibleUsage(int id) + { + return Modify(id, system => + { + return system.RemoveResponsibleOrganizationUnit() + .Match + ( + error => error, + () => Result.Success(system) + ); + }).MatchFailure(); + } + + public Maybe RemoveRelevantUnit(int id, Guid unitUuid) + { + return Modify(id, system => + { + return system.RemoveUsedByUnit(unitUuid) + .Match + ( + error => error, + () => Result.Success(system) + ); + }).MatchFailure(); + } + private Result WithReadAccess(ItSystemUsage usage) { return _authorizationContext.AllowReads(usage) ? Result.Success(usage) : new OperationError(OperationFailure.Forbidden); @@ -306,11 +353,15 @@ private Result Modify(int id, Func(usage)); + _usageRepository.Save(); transaction.Commit(); } diff --git a/Core.ApplicationServices/UIConfiguration/Handlers/HandleUserBeingDeleted.cs b/Core.ApplicationServices/UIConfiguration/Handlers/HandleUserBeingDeleted.cs deleted file mode 100644 index 50560dcfcc..0000000000 --- a/Core.ApplicationServices/UIConfiguration/Handlers/HandleUserBeingDeleted.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Linq; -using Core.Abstractions.Extensions; -using Core.ApplicationServices.Rights; -using Core.DomainModel; -using Core.DomainModel.Events; -using Core.DomainServices.Repositories.SSO; - -namespace Core.ApplicationServices.UIConfiguration.Handlers -{ - public class HandleUserBeingDeleted : IDomainEventHandler> - { - private readonly ISsoUserIdentityRepository _ssoUserIdentityRepository; - private readonly IUserRightsService _userRightsService; - - - public HandleUserBeingDeleted(ISsoUserIdentityRepository ssoUserIdentityRepository, IUserRightsService userRightsService) - { - _ssoUserIdentityRepository = ssoUserIdentityRepository; - _userRightsService = userRightsService; - } - - public void Handle(EntityBeingDeletedEvent domainEvent) - { - var user = domainEvent.Entity; - - var organizationIds = user.GetOrganizationIds().ToList(); - - foreach (var organizationId in organizationIds) - { - _userRightsService.RemoveAllRights(user.Id, organizationId).ThrowOnValue(); - } - - ClearSsoIdentities(user); - } - - private void ClearSsoIdentities(User user) - { - var roles = user.SsoIdentities; - if (roles == null) - return; - - _ssoUserIdentityRepository.DeleteIdentitiesForUser(user); - roles.Clear(); - } - - } -} \ No newline at end of file diff --git a/Core.ApplicationServices/UserService.cs b/Core.ApplicationServices/UserService.cs index f9289a23e9..cf2f049af6 100644 --- a/Core.ApplicationServices/UserService.cs +++ b/Core.ApplicationServices/UserService.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Net.Mail; using System.Security; @@ -13,8 +12,10 @@ using Core.Abstractions.Types; using Core.ApplicationServices.Authorization; using Core.ApplicationServices.Organizations; +using Core.DomainModel.Commands; using Core.DomainModel.Events; using Core.DomainModel.Organization.DomainEvents; +using Core.DomainModel.Users; using Infrastructure.Services.Cryptography; using Core.DomainServices.Authorization; using Core.DomainServices.Extensions; @@ -43,6 +44,7 @@ public class UserService : IUserService private readonly IDomainEvents _domainEvents; private readonly SHA256Managed _crypt; private readonly IOrganizationalUserContext _organizationalUserContext; + private readonly ICommandBus _commandBus; private static readonly RNGCryptoServiceProvider rngCsp = new(); private const string KitosManualsLink = "https://os2.eu/Kitosvejledning"; @@ -61,7 +63,8 @@ public UserService(TimeSpan ttl, IUserRepository repository, IOrganizationService organizationService, ITransactionManager transactionManager, - IOrganizationalUserContext organizationalUserContext) + IOrganizationalUserContext organizationalUserContext, + ICommandBus commandBus) { _ttl = ttl; _baseUrl = baseUrl; @@ -79,6 +82,7 @@ public UserService(TimeSpan ttl, _organizationService = organizationService; _transactionManager = transactionManager; _organizationalUserContext = organizationalUserContext; + _commandBus = commandBus; _crypt = new SHA256Managed(); if (useDefaultUserPassword && string.IsNullOrWhiteSpace(defaultUserPassword)) { @@ -306,43 +310,89 @@ public Result, OperationError> SearchAllKitosUsers(params IDoma .Transform(Result, OperationError>.Success); } - public Maybe DeleteUserFromKitos(Guid userUuid) + public Maybe DeleteUser(Guid userUuid, int? scopedToOrganizationId = null) { - using var transaction = _transactionManager.Begin(); + var hasOrganizationIdValue = scopedToOrganizationId.HasValue; - var user = _userRepository.AsQueryable().ByUuid(userUuid); - if (user == null) - return new OperationError(OperationFailure.NotFound); - if(_organizationalUserContext.UserId == user.Id) - return new OperationError("You cannot delete a user you are currently logged in as", OperationFailure.Forbidden); + var allowByGlobalAdminRights = _organizationalUserContext.IsGlobalAdmin(); + var allowByLocalAdminRights = hasOrganizationIdValue && _organizationalUserContext.HasRole(scopedToOrganizationId.Value, OrganizationRole.LocalAdmin); + if (allowByGlobalAdminRights || allowByLocalAdminRights) + { + var user = _userRepository.AsQueryable().ByUuid(userUuid); + if (user == null) + { + return new OperationError($"User with Uuid {userUuid} was not found", OperationFailure.NotFound); + } - if (!_authorizationContext.AllowDelete(user)) - return new OperationError(OperationFailure.Forbidden); - - _domainEvents.Raise(new EntityBeingDeletedEvent(user)); + if (_organizationalUserContext.UserId == user.Id) + { + return new OperationError("You cannot delete a user you are currently logged in as", OperationFailure.Forbidden); + } - Delete(user); - _userRepository.Save(); - transaction.Commit(); - - _domainEvents.Raise(new AdministrativeAccessRightsChanged(user.Id)); + using var transaction = _transactionManager.Begin(); + var result = hasOrganizationIdValue + ? DeleteUser(scopedToOrganizationId.Value, user) + : DeleteUserFromKitos(user); - return Maybe.None; + if (result.HasValue) + { + transaction.Rollback(); + } + else + { + _userRepository.Save(); + transaction.Commit(); + + _domainEvents.Raise(new AdministrativeAccessRightsChanged(user.Id)); + } + + return result; + } + + return new OperationError(OperationFailure.Forbidden); } - private static void Delete(User user) + private Maybe DeleteUserFromKitos(User userToDelete) { - user.LockedOutDate = DateTime.Now; - user.EmailBeforeDeletion = user.Email; - user.Email = $"{Guid.NewGuid()}_deleted_user@kitos.dk"; - user.PhoneNumber = null; - user.LastName = $"{(user.LastName ?? "").TrimEnd()} (SLETTET)"; - user.DeletedDate = DateTime.Now; - user.Deleted = true; - user.IsGlobalAdmin = false; - user.HasApiAccess = false; - user.HasStakeHolderAccess = false; + return _commandBus.Execute>(new RemoveUserFromKitosCommand(userToDelete)); + } + + private Maybe DeleteUser(int scopedToOrganizationId, User userToDelete) + { + var deletionStrategy = GetOrganizationalUserDeletionStrategy(scopedToOrganizationId, userToDelete); + + if (deletionStrategy.Failed) + return deletionStrategy.Error; + + return deletionStrategy.Value switch + { + OrganizationalUserDeletionStrategy.Global => + DeleteUserFromKitos(userToDelete), + OrganizationalUserDeletionStrategy.Local => _commandBus + .Execute>(new RemoveUserFromOrganizationCommand(userToDelete, scopedToOrganizationId)), + _ => + new OperationError(OperationFailure.Forbidden) + }; + } + + private static Result GetOrganizationalUserDeletionStrategy(int orgId, User userToDelete) + { + if (userToDelete.Deleted) + return new OperationError("User is already deleted", OperationFailure.BadState); + var organizationIds = userToDelete.GetOrganizationIds().ToList(); + + var memberOfTargetOrganization = organizationIds.Contains(orgId); + if (!memberOfTargetOrganization) + return new OperationError("User is part of the current organization", OperationFailure.BadInput); + + var memberOfMoreOrganizations = organizationIds.Count > 1; + if (memberOfMoreOrganizations) + return OrganizationalUserDeletionStrategy.Local; + + return userToDelete.IsGlobalAdmin + ? OrganizationalUserDeletionStrategy.Local //Global admins are not automatically removed from kitos when removed from the last organization + : OrganizationalUserDeletionStrategy.Global; } } } diff --git a/Core.ApplicationServices/Users/Handlers/RemoveUserFromKitosCommandHandler.cs b/Core.ApplicationServices/Users/Handlers/RemoveUserFromKitosCommandHandler.cs new file mode 100644 index 0000000000..dbda529356 --- /dev/null +++ b/Core.ApplicationServices/Users/Handlers/RemoveUserFromKitosCommandHandler.cs @@ -0,0 +1,73 @@ +using System; +using System.Linq; +using Core.Abstractions.Types; +using Core.DomainModel; +using Core.DomainModel.Commands; +using Core.DomainModel.Events; +using Core.DomainServices.Repositories.SSO; + +namespace Core.ApplicationServices.Users.Handlers +{ + public class RemoveUserFromKitosCommandHandler : ICommandHandler> + { + private readonly ISsoUserIdentityRepository _ssoUserIdentityRepository; + private readonly ICommandBus _commandBus; + private readonly IDomainEvents _domainEvents; + + public RemoveUserFromKitosCommandHandler( + ISsoUserIdentityRepository ssoUserIdentityRepository, + ICommandBus commandBus, + IDomainEvents domainEvents) + { + _ssoUserIdentityRepository = ssoUserIdentityRepository; + _commandBus = commandBus; + _domainEvents = domainEvents; + } + + private void ClearSsoIdentities(User user) + { + var roles = user.SsoIdentities; + if (roles == null) + return; + + _ssoUserIdentityRepository.DeleteIdentitiesForUser(user); + roles.Clear(); + } + + public Maybe Execute(RemoveUserFromKitosCommand command) + { + var user = command.User; + + _domainEvents.Raise(new EntityBeingDeletedEvent(user)); + + var organizationIds = user.GetOrganizationIds().ToList(); + + foreach (var organizationId in organizationIds) + { + var error = _commandBus.Execute>(new RemoveUserFromOrganizationCommand(user, organizationId)); + if (error.HasValue) + return error; + } + + ClearSsoIdentities(user); + + Anonymize(user); + + return Maybe.None; + } + + private static void Anonymize(User user) + { + user.LockedOutDate = DateTime.Now; + user.Name = "Slettet bruger"; + user.Email = $"{Guid.NewGuid()}_deleted_user@kitos.dk"; + user.PhoneNumber = null; + user.LastName = ""; + user.DeletedDate = DateTime.Now; + user.Deleted = true; + user.IsGlobalAdmin = false; + user.HasApiAccess = false; + user.HasStakeHolderAccess = false; + } + } +} \ No newline at end of file diff --git a/Core.ApplicationServices/Users/Handlers/RemoveUserFromOrganizationCommandHandler.cs b/Core.ApplicationServices/Users/Handlers/RemoveUserFromOrganizationCommandHandler.cs new file mode 100644 index 0000000000..f22bc50086 --- /dev/null +++ b/Core.ApplicationServices/Users/Handlers/RemoveUserFromOrganizationCommandHandler.cs @@ -0,0 +1,21 @@ +using Core.ApplicationServices.Rights; +using Core.Abstractions.Types; +using Core.DomainModel.Commands; + +namespace Core.ApplicationServices.Users.Handlers +{ + public class RemoveUserFromOrganizationCommandHandler : ICommandHandler> + { + private readonly IUserRightsService _userRightsService; + + public RemoveUserFromOrganizationCommandHandler(IUserRightsService userRightsService) + { + _userRightsService = userRightsService; + } + + public Maybe Execute(RemoveUserFromOrganizationCommand command) + { + return _userRightsService.RemoveAllRights(command.User.Id, command.OrganizationId); + } + } +} diff --git a/Core.BackgroundJobs/Core.BackgroundJobs.csproj b/Core.BackgroundJobs/Core.BackgroundJobs.csproj index 6e9803e495..2b1036c6ef 100644 --- a/Core.BackgroundJobs/Core.BackgroundJobs.csproj +++ b/Core.BackgroundJobs/Core.BackgroundJobs.csproj @@ -104,7 +104,7 @@ Core.ApplicationServices - {a76a8e41-74f7-4443-a5f3-059b5414d83b} + {A76A8E41-74F7-4443-A5F3-059B5414D83B} Core.DomainModel diff --git a/Core.BackgroundJobs/Model/BaseContextToReadModelChangeScheduler.cs b/Core.BackgroundJobs/Model/BaseContextToReadModelChangeScheduler.cs index c43bdfbdac..932e3ab7a3 100644 --- a/Core.BackgroundJobs/Model/BaseContextToReadModelChangeScheduler.cs +++ b/Core.BackgroundJobs/Model/BaseContextToReadModelChangeScheduler.cs @@ -65,11 +65,8 @@ protected int ScheduleRootEntityChanges( Func> getRootIdsQuery) { var updatesExecuted = 0; - foreach (var update in _updateRepository.GetMany(childChangeType, int.MaxValue).ToList()) + foreach (var update in _updateRepository.GetMany(childChangeType, int.MaxValue).ToList().TakeWhile(_ => !token.IsCancellationRequested)) { - if (token.IsCancellationRequested) - break; - using var transaction = _transactionManager.Begin(); var ids = getRootIdsQuery(update).Distinct().ToList(); diff --git a/Core.BackgroundJobs/Model/ReadModels/ScheduleItContractOverviewReadModelUpdates.cs b/Core.BackgroundJobs/Model/ReadModels/ScheduleItContractOverviewReadModelUpdates.cs index 626dfa9299..335722be41 100644 --- a/Core.BackgroundJobs/Model/ReadModels/ScheduleItContractOverviewReadModelUpdates.cs +++ b/Core.BackgroundJobs/Model/ReadModels/ScheduleItContractOverviewReadModelUpdates.cs @@ -59,7 +59,7 @@ private int HandleOptionExtendTypeChanges(CancellationToken token, HashSet private int HandleItSystemChanges(CancellationToken token, HashSet alreadyScheduledIds) { - return ScheduleRootEntityChanges(token, alreadyScheduledIds, PendingReadModelUpdateSourceCategory.ItContract_ItSystem, update => _readModelRepository.GetByItSystem(update.SourceId)); + return ScheduleRootEntityChanges(token, alreadyScheduledIds, PendingReadModelUpdateSourceCategory.ItContract_ItSystem, update => _readModelRepository.GetSourceIdsByItSystem(update.SourceId)); } private int HandleItSystemUsageChanges(CancellationToken token, HashSet alreadyScheduledIds) diff --git a/Core.DomainModel/Commands/ICommand.cs b/Core.DomainModel/Commands/ICommand.cs new file mode 100644 index 0000000000..58be9709bc --- /dev/null +++ b/Core.DomainModel/Commands/ICommand.cs @@ -0,0 +1,9 @@ +namespace Core.DomainModel.Commands +{ + /// + /// Marker interface + /// + public interface ICommand + { + } +} \ No newline at end of file diff --git a/Core.DomainModel/Commands/ICommandBus.cs b/Core.DomainModel/Commands/ICommandBus.cs new file mode 100644 index 0000000000..93e331a253 --- /dev/null +++ b/Core.DomainModel/Commands/ICommandBus.cs @@ -0,0 +1,11 @@ +namespace Core.DomainModel.Commands +{ + public interface ICommandBus + { + /// + /// Handles the command + /// + /// + TResult Execute(TCommand args) where TCommand : ICommand; + } +} \ No newline at end of file diff --git a/Core.DomainModel/Commands/ICommandHandler.cs b/Core.DomainModel/Commands/ICommandHandler.cs new file mode 100644 index 0000000000..46c351823d --- /dev/null +++ b/Core.DomainModel/Commands/ICommandHandler.cs @@ -0,0 +1,7 @@ +namespace Core.DomainModel.Commands +{ + public interface ICommandHandler where TCommand:ICommand + { + TResult Execute(TCommand command); + } +} \ No newline at end of file diff --git a/Core.DomainModel/Commands/RemoveOrganizationUnitRegistrationsCommand.cs b/Core.DomainModel/Commands/RemoveOrganizationUnitRegistrationsCommand.cs new file mode 100644 index 0000000000..cdf6a5b2a4 --- /dev/null +++ b/Core.DomainModel/Commands/RemoveOrganizationUnitRegistrationsCommand.cs @@ -0,0 +1,18 @@ +using System; +using Core.DomainModel.Organization; + +namespace Core.DomainModel.Commands +{ + public class RemoveOrganizationUnitRegistrationsCommand : ICommand + { + public RemoveOrganizationUnitRegistrationsCommand(Organization.Organization organization, OrganizationUnit organizationUnit) + { + Organization = organization; + OrganizationUnit = organizationUnit; + } + + public Organization.Organization Organization { get; } + public OrganizationUnit OrganizationUnit{ get; } + + } +} diff --git a/Core.DomainModel/Commands/RemoveUserFromKitosCommand.cs b/Core.DomainModel/Commands/RemoveUserFromKitosCommand.cs new file mode 100644 index 0000000000..0088ddb10d --- /dev/null +++ b/Core.DomainModel/Commands/RemoveUserFromKitosCommand.cs @@ -0,0 +1,12 @@ +namespace Core.DomainModel.Commands +{ + public class RemoveUserFromKitosCommand : ICommand + { + public User User { get; } + + public RemoveUserFromKitosCommand(User user) + { + User = user; + } + } +} diff --git a/Core.DomainModel/Commands/RemoveUserFromOrganizationCommand.cs b/Core.DomainModel/Commands/RemoveUserFromOrganizationCommand.cs new file mode 100644 index 0000000000..773eb41ae0 --- /dev/null +++ b/Core.DomainModel/Commands/RemoveUserFromOrganizationCommand.cs @@ -0,0 +1,14 @@ +namespace Core.DomainModel.Commands +{ + public class RemoveUserFromOrganizationCommand : ICommand + { + public User User { get; } + public int OrganizationId { get; } + + public RemoveUserFromOrganizationCommand(User user, int organizationId) + { + User = user; + OrganizationId = organizationId; + } + } +} diff --git a/Core.DomainModel/Config.cs b/Core.DomainModel/Config.cs index 26c84c1072..efc0e1c582 100644 --- a/Core.DomainModel/Config.cs +++ b/Core.DomainModel/Config.cs @@ -19,9 +19,6 @@ public class Config : Entity, IIsPartOfOrganization /* IT SUPPORT */ public int ItSupportModuleNameId { get; set; } public string ItSupportGuide { get; set; } - public bool ShowTabOverview { get; set; } - public bool ShowColumnTechnology { get; set; } - public bool ShowColumnUsage { get; set; } public virtual Organization.Organization Organization { get; set; } @@ -33,9 +30,6 @@ public static Config Default(User objectOwner) ShowItSystemModule = true, ShowItContractPrefix = true, ShowItSystemPrefix = true, - ShowColumnTechnology = true, - ShowColumnUsage = true, - ShowTabOverview = true, ShowDataProcessing = true, ObjectOwner = objectOwner, LastChangedByUser = objectOwner diff --git a/Core.DomainModel/Core.DomainModel.csproj b/Core.DomainModel/Core.DomainModel.csproj index 3e342b175c..b7f6d79d6a 100644 --- a/Core.DomainModel/Core.DomainModel.csproj +++ b/Core.DomainModel/Core.DomainModel.csproj @@ -52,7 +52,16 @@ + + + + + + + + + @@ -82,6 +91,17 @@ + + + + + + + + + + + @@ -238,7 +258,6 @@ - @@ -262,7 +281,9 @@ + + diff --git a/Core.DomainModel/Events/IDomainEvent.cs b/Core.DomainModel/Events/IDomainEvent.cs index 59d00b7333..00fad9a607 100644 --- a/Core.DomainModel/Events/IDomainEvent.cs +++ b/Core.DomainModel/Events/IDomainEvent.cs @@ -3,7 +3,7 @@ /// /// Marker interface /// - public abstract class IDomainEvent + public interface IDomainEvent { } } \ No newline at end of file diff --git a/Core.DomainModel/Events/IDomainEventHandler.cs b/Core.DomainModel/Events/IDomainEventHandler.cs index fba67d2150..08f9fb660e 100644 --- a/Core.DomainModel/Events/IDomainEventHandler.cs +++ b/Core.DomainModel/Events/IDomainEventHandler.cs @@ -1,6 +1,6 @@ namespace Core.DomainModel.Events { - public interface IDomainEventHandler + public interface IDomainEventHandler where T:IDomainEvent { void Handle(T domainEvent); } diff --git a/Core.DomainModel/Extensions/ExternalOrganizationUnitExtensions.cs b/Core.DomainModel/Extensions/ExternalOrganizationUnitExtensions.cs new file mode 100644 index 0000000000..e5ccc97e21 --- /dev/null +++ b/Core.DomainModel/Extensions/ExternalOrganizationUnitExtensions.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using Core.DomainModel.Organization; + +namespace Core.DomainModel.Extensions +{ + public static class ExternalOrganizationUnitExtensions + { + /// + /// Based on the current root, returns a collection containing the current root as well as nodes in the entire subtree + /// + /// + /// + public static IEnumerable Flatten(this ExternalOrganizationUnit root) + { + var unreached = new Queue(); + var reached = new List(); + + unreached.Enqueue(root); + + //Process one level at the time + while (unreached.Count > 0) + { + var orgUnit = unreached.Dequeue(); + + reached.Add(orgUnit); + + foreach (var child in orgUnit.Children) + { + unreached.Enqueue(child); + } + } + + return reached; + } + } +} diff --git a/Core.DomainModel/Extensions/HierarchyExtensions.cs b/Core.DomainModel/Extensions/HierarchyExtensions.cs new file mode 100644 index 0000000000..ffcd84b281 --- /dev/null +++ b/Core.DomainModel/Extensions/HierarchyExtensions.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Core.Abstractions.Types; + +namespace Core.DomainModel.Extensions +{ + public static class HierarchyExtensions + { + + public static bool IsLeaf(this TEntity entity) + where TEntity : class, IHierarchy + { + return entity.Children.Any() == false; + } + + public static bool IsRoot(this TEntity entity) + where TEntity : class, IHierarchy + { + return entity.Parent == null; + } + + /// + /// Based on the current root, returns a collection containing the current root as well as nodes in the entire subtree and the ancestry + /// + /// + /// + public static IEnumerable FlattenCompleteHierarchy(this TEntity root) + where TEntity : class, IHierarchy + + { + return root.FlattenHierarchy().Concat(root.FlattenAncestry()); + } + + /// + /// Based on the current root, returns a collection containing the current root as well as nodes in the entire subtree + /// + /// + /// + public static IEnumerable FlattenHierarchy(this TEntity root) + where TEntity : class, IHierarchy + + { + var unreached = new Queue(); + var reached = new List(); + + unreached.Enqueue(root); + + //Process one level at the time + while (unreached.Count > 0) + { + var orgUnit = unreached.Dequeue(); + + reached.Add(orgUnit); + + foreach (var child in orgUnit.Children) + { + unreached.Enqueue(child); + } + } + + return reached; + } + + public static IEnumerable FlattenAncestry(this TEntity currentEntity) where TEntity : class, IHierarchy + { + var currentRoot = currentEntity; + + //Continue until the root has been located + while (true) + { + var currentParent = currentRoot.Parent; + if (currentParent == null) + { + yield break; + } + + yield return currentParent; + + currentRoot = currentParent; + } + } + + public static Maybe SearchAncestry(this TEntity currentEntity, Predicate condition) where TEntity : class, IHierarchy + { + var currentRoot = currentEntity; + + //Continue until the root has been located + while (true) + { + var currentParent = currentRoot.Parent; + if (currentParent == null) + { + return Maybe.None; + } + + if (condition(currentParent)) + { + return currentParent; + } + + currentRoot = currentParent; + } + } + } +} diff --git a/Core.DomainModel/Extensions/StsOrganizationUnitExtensions.cs b/Core.DomainModel/Extensions/StsOrganizationUnitExtensions.cs new file mode 100644 index 0000000000..c9b7c68f87 --- /dev/null +++ b/Core.DomainModel/Extensions/StsOrganizationUnitExtensions.cs @@ -0,0 +1,27 @@ +using System.Linq; +using Core.DomainModel.Organization; + +namespace Core.DomainModel.Extensions +{ + public static class StsOrganizationUnitExtensions + { + public static OrganizationUnit ToOrganizationUnit(this ExternalOrganizationUnit stsOrganizationUnit, OrganizationUnitOrigin origin, Organization.Organization parentOrganization, bool includeChildren = true) + { + var organizationUnit = new OrganizationUnit + { + Name = stsOrganizationUnit.Name.Length > OrganizationUnit.MaxNameLength ? stsOrganizationUnit.Name.Substring(0, OrganizationUnit.MaxNameLength) : stsOrganizationUnit.Name, + Origin = origin, + ExternalOriginUuid = stsOrganizationUnit.Uuid, + Organization = parentOrganization + }; + if (includeChildren) + { + organizationUnit.Children = stsOrganizationUnit + .Children + .Select(child => child.ToOrganizationUnit(origin, parentOrganization)) + .ToList(); + } + return organizationUnit; + } + } +} diff --git a/Core.DomainModel/HasRightsEntity.cs b/Core.DomainModel/HasRightsEntity.cs index 135093890b..de4f31e343 100644 --- a/Core.DomainModel/HasRightsEntity.cs +++ b/Core.DomainModel/HasRightsEntity.cs @@ -68,7 +68,7 @@ public Result RemoveRole(TRole role, User user) Rights.Remove(right); return right; }, - () => new OperationError($"Role with id {role.Id} is not assigned to user with id ${user.Id}", + () => new OperationError($"Role with id {role.Id} is not assigned to user with id {user.Id}", OperationFailure.BadInput) ); diff --git a/Core.DomainModel/ItContract/EconomyStream.cs b/Core.DomainModel/ItContract/EconomyStream.cs index 96ff48f60f..a3d80e7939 100644 --- a/Core.DomainModel/ItContract/EconomyStream.cs +++ b/Core.DomainModel/ItContract/EconomyStream.cs @@ -161,5 +161,15 @@ public IEnumerable GetOrganizationIds() if (InternPaymentFor != null) yield return InternPaymentFor.OrganizationId; } + + public void SetOrganizationUnit(OrganizationUnit unit) + { + OrganizationUnit = unit; + } + + public void ResetOrganizationUnit() + { + OrganizationUnit = null; + } } } diff --git a/Core.DomainModel/ItContract/ItContract.cs b/Core.DomainModel/ItContract/ItContract.cs index ef3605aa74..0cb73f5cd0 100644 --- a/Core.DomainModel/ItContract/ItContract.cs +++ b/Core.DomainModel/ItContract/ItContract.cs @@ -831,6 +831,61 @@ public Maybe AddExternalEconomyStream(Guid? optionalOrganization return AddEconomyStream(optionalOrganizationUnitUuid, acquisition, operation, other, accountingEntry, auditStatus, auditDate, note, false); } + public IEnumerable GetAllPayments() + { + return ExternEconomyStreams.ToList().Concat(InternEconomyStreams.ToList()); + } + + public IEnumerable GetInternalPaymentsForUnit(int unitId) + { + return InternEconomyStreams.Where(x => x.OrganizationUnitId == unitId).ToList(); + } + + public IEnumerable GetExternalPaymentsForUnit(int unitId) + { + return ExternEconomyStreams.Where(x => x.OrganizationUnitId == unitId).ToList(); + } + + public Maybe ResetEconomyStreamOrganizationUnit(int id, bool isInternal) + { + return isInternal + ? ResetEconomyStreamOrganizationUnit(id, InternEconomyStreams) + : ResetEconomyStreamOrganizationUnit(id, ExternEconomyStreams); + } + + private static Maybe ResetEconomyStreamOrganizationUnit(int id, IEnumerable economyStreams) + { + var stream = economyStreams.FirstOrDefault(x => x.Id == id); + if (stream == null) + return new OperationError($"EconomyStream with id: {id} was not found", OperationFailure.NotFound); + + stream.ResetOrganizationUnit(); + + return Maybe.None; + } + + public Maybe TransferEconomyStream(int id, Guid targetUnitUuid, bool isInternal) + { + return Organization.GetOrganizationUnit(targetUnitUuid) + .Match + ( + targetUnit => isInternal + ? TransferEconomyStream(id, targetUnit, InternEconomyStreams) + : TransferEconomyStream(id, targetUnit, ExternEconomyStreams), + () => new OperationError($"Organization unit with uuid: {targetUnitUuid} was not found", OperationFailure.NotFound) + ); + } + + private static Maybe TransferEconomyStream(int id, OrganizationUnit targetUnit, IEnumerable economyStreams) + { + var stream = economyStreams.FirstOrDefault(x => x.Id == id); + if (stream == null) + return new OperationError($"EconomyStream with id: {id} was not found", OperationFailure.NotFound); + + stream.SetOrganizationUnit(targetUnit); + return Maybe.None; + } + private Maybe AddEconomyStream( Guid? optionalOrganizationUnitUuid, int acquisition, diff --git a/Core.DomainModel/ItSystemUsage/ItSystemUsage.cs b/Core.DomainModel/ItSystemUsage/ItSystemUsage.cs index 8a6446a425..c7fe63018d 100644 --- a/Core.DomainModel/ItSystemUsage/ItSystemUsage.cs +++ b/Core.DomainModel/ItSystemUsage/ItSystemUsage.cs @@ -55,7 +55,7 @@ public ItSystemUsage() public bool IsActiveAccordingToDateFields => CheckDatesValidity(DateTime.UtcNow).Any() == false; public bool IsActiveAccordingToLifeCycle => CheckLifeCycleValidity().IsNone; - public bool IsActiveAccordingToMainContract=> CheckContractValidity().IsNone; + public bool IsActiveAccordingToMainContract => CheckContractValidity().IsNone; /// /// When the system began. (indgået) @@ -610,7 +610,8 @@ public Maybe UpdateOrganizationalUsage(IEnumerable x.Uuid).Distinct().Count() != organizationUnits.Count) return new OperationError("No duplicates allowed in using org units", OperationFailure.BadInput); - if (responsibleOrgUnit.HasValue && (organizationUnits.Any(unit => unit.Uuid == responsibleOrgUnit.Value.Uuid) == false)) + var responsibleOrgUnitIsValid = responsibleOrgUnit.Select(responsible=>organizationUnits.Any(unit=>responsible == unit)).GetValueOrFallback(true); + if (!responsibleOrgUnitIsValid) return new OperationError("Responsible org unit must be one of the using organizations", OperationFailure.BadInput); var newOrgUnitUsages = organizationUnits.Select(organizationUnit => new ItSystemUsageOrgUnitUsage @@ -628,6 +629,105 @@ public Maybe UpdateOrganizationalUsage(IEnumerable.None; } + private Maybe GetOrganizationUnitUsage(int organizationUnitId) + { + return UsedBy.FirstOrDefault(ub => ub.OrganizationUnit.Id == organizationUnitId); + } + + public Maybe RemoveResponsibleOrganizationUnit() + { + return UpdateOrganizationalUsage(GetUsedByOrganizationUnits(), Maybe.None); + } + + public Maybe RemoveUsedByUnit(Guid unitUuid) + { + var unitResult = GetOrganizationUnit(unitUuid); + if (unitResult.IsNone) + { + return new OperationError($"Organization unit with uuid: {unitUuid} was not found", OperationFailure.NotFound); + } + var unit = unitResult.Value; + + var selectedUnit = GetOrganizationUnitUsage(unit.Id); + if (selectedUnit.IsNone) + { + return new OperationError($"Unit with id: {unit.Id} was not found", OperationFailure.NotFound); + } + + var remainingUnits = GetUsedByOrganizationUnits().Where(x => x.Id != unit.Id); + Maybe responsibleUnit = ResponsibleUsage?.OrganizationUnit; + + if (responsibleUnit.Select(organizationUnit => organizationUnit.Id == unit.Id).GetValueOrFallback(false)) + { + responsibleUnit = Maybe.None; + } + + return UpdateOrganizationalUsage(remainingUnits, responsibleUnit); + } + + public Maybe TransferResponsibleOrganizationalUnit(Guid targetUnitUuid) + { + var targetUnitResult = GetOrganizationUnit(targetUnitUuid); + if (targetUnitResult.IsNone) + { + return new OperationError($"Organization unit with uuid: {targetUnitUuid} not found", OperationFailure.NotFound); + } + var targetUnit = targetUnitResult.Value; + + if (targetUnit.Id == ResponsibleUsage?.OrganizationUnitId) + { + return Maybe.None; + } + + var usedByOrganizationUnits = GetUsedByOrganizationUnits().ToList(); + + if (usedByOrganizationUnits.Any(x => x.Id == targetUnit.Id) == false) + { + usedByOrganizationUnits.Add(targetUnit); + } + + return UpdateOrganizationalUsage(usedByOrganizationUnits, targetUnit); + } + + public Maybe TransferUsedByUnit(Guid unitUuid, Guid targetUnitUuid) + { + if (unitUuid == targetUnitUuid) + { + return Maybe.None; + } + + var targetUnitResult = GetOrganizationUnit(targetUnitUuid); + if (targetUnitResult.IsNone) + { + return new OperationError($"Organization unit with uuid: {targetUnitUuid} was not found", OperationFailure.NotFound); + } + var targetUnit = targetUnitResult.Value; + + var unitResult = GetOrganizationUnit(unitUuid); + if (unitResult.IsNone) + { + return new OperationError($"Organization unit with uuid: {unitUuid} was not found", OperationFailure.NotFound); + } + var unit = unitResult.Value; + + var selectedUnit = GetOrganizationUnitUsage(unit.Id); + if (selectedUnit.IsNone) + return new OperationError($"UsedBy organization unit with Id: {unit.Id} was not found", OperationFailure.NotFound); + + var relevantUnits = GetUsedByOrganizationUnits().Where(x => x.Id != unit.Id).ToList(); + if (relevantUnits.Any(x => x.Id == targetUnit.Id) == false) + { + relevantUnits.Add(targetUnit); + } + + if (unit.Id == ResponsibleUsage?.OrganizationUnit?.Id) + { + return UpdateOrganizationalUsage(relevantUnits, Maybe.None); + } + + return UpdateOrganizationalUsage(relevantUnits, ResponsibleUsage?.OrganizationUnit); + } + public Maybe UpdateKLEDeviations(IEnumerable additions, IEnumerable removals) { if (additions == null) @@ -874,6 +974,16 @@ public ItSystemUsageValidationResult CheckSystemValidity() return new ItSystemUsageValidationResult(errors); } + private Maybe GetOrganizationUnit(Guid uuid) + { + return Organization.GetOrganizationUnit(uuid); + } + + private IEnumerable GetUsedByOrganizationUnits() + { + return UsedBy.Select(x => x.OrganizationUnit).ToList(); + } + private IEnumerable CheckDatesValidity(DateTime todayReference) { if (Concluded == null && ExpirationDate == null) diff --git a/Core.DomainModel/Organization/DisconnectOrganizationFromOriginResult.cs b/Core.DomainModel/Organization/DisconnectOrganizationFromOriginResult.cs new file mode 100644 index 0000000000..6f6dfba60a --- /dev/null +++ b/Core.DomainModel/Organization/DisconnectOrganizationFromOriginResult.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Core.DomainModel.Organization +{ + public class DisconnectOrganizationFromOriginResult + { + public IEnumerable ConvertedUnits { get; } + public DisconnectOrganizationFromOriginResult(IEnumerable convertedUnits) + { + ConvertedUnits = convertedUnits.ToList().AsReadOnly(); + } + } +} diff --git a/Core.DomainModel/Organization/ExternalOrganizationUnit.cs b/Core.DomainModel/Organization/ExternalOrganizationUnit.cs new file mode 100644 index 0000000000..082cb29425 --- /dev/null +++ b/Core.DomainModel/Organization/ExternalOrganizationUnit.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Core.Abstractions.Types; + +namespace Core.DomainModel.Organization +{ + /// + /// Represents an external organization unit not part of the KITOS persisted data model + /// + public class ExternalOrganizationUnit + { + public Guid Uuid { get; } + public string Name { get; } + public IReadOnlyDictionary MetaData { get; } + public IEnumerable Children { get; } + + public ExternalOrganizationUnit(Guid uuid, string name, IReadOnlyDictionary metaData, IEnumerable children) + { + Uuid = uuid; + Name = name; + MetaData = metaData ?? new Dictionary(); + Children = children.ToList().AsReadOnly(); + } + + public ExternalOrganizationUnit Copy(Maybe childLevelsToInclude) + { + var children = new List(); + var includeChildren = childLevelsToInclude + .Select(levels=>levels > 0) + .GetValueOrFallback(true); //IF no levels defined, include all + + if (includeChildren) + { + children = Children.Select(child => + { + var levelsToInclude = childLevelsToInclude.Select(levels => levels - 1); + return child.Copy(levelsToInclude); + }).ToList(); + } + + return new ExternalOrganizationUnit(Uuid, Name, MetaData, children); + } + } +} diff --git a/Core.DomainModel/Organization/Organization.cs b/Core.DomainModel/Organization/Organization.cs index f9a1b8cfb6..8fc5c8a4df 100644 --- a/Core.DomainModel/Organization/Organization.cs +++ b/Core.DomainModel/Organization/Organization.cs @@ -3,12 +3,14 @@ using System.Linq; using Core.Abstractions.Extensions; using Core.Abstractions.Types; +using Core.DomainModel.Extensions; using Core.DomainModel.GDPR; using Core.DomainModel.GDPR.Read; using Core.DomainModel.ItContract.Read; using Core.DomainModel.ItSystem; using Core.DomainModel.ItSystemUsage.Read; using Core.DomainModel.Notification; +using Core.DomainModel.Organization.Strategies; using Core.DomainModel.Tracking; using Core.DomainModel.UIConfiguration; @@ -126,6 +128,7 @@ public Organization() public virtual ICollection UIModuleCustomizations { get; set; } public virtual ICollection ArchiveSupplierForItSystems { get; set; } + public virtual StsOrganizationConnection StsOrganizationConnection { get; set; } /// @@ -141,7 +144,7 @@ public Organization() /// public OrganizationUnit GetRoot() { - return OrgUnits.FirstOrDefault(u => u.Parent == null); + return OrgUnits.FirstOrDefault(MatchRoot); } public IEnumerable GetOrganizationIds() => new[] { Id }; @@ -151,11 +154,16 @@ public Maybe GetOrganizationUnit(Guid organizationUnitId) return OrgUnits.FirstOrDefault(unit => unit.Uuid == organizationUnitId); } + public IEnumerable GetAllOrganizationUnits() + { + return OrgUnits.ToList(); + } + public Maybe GetUiModuleCustomization(string module) { if (module == null) throw new ArgumentNullException(nameof(module)); - + return UIModuleCustomizations .SingleOrDefault(config => config.Module == module) .FromNullable(); @@ -164,17 +172,17 @@ public Maybe GetUiModuleCustomization(string module) public Result ModifyModuleCustomization(string module, IEnumerable nodes) { if (string.IsNullOrEmpty(module)) - throw new ArgumentNullException("Module parameter cannot be null"); + throw new ArgumentNullException(nameof(module)); if (nodes == null) - throw new ArgumentNullException("Nodes parameter cannot be null"); - + throw new ArgumentNullException(nameof(nodes)); + var uiNodes = nodes.ToList(); var customizedUiNodes = uiNodes.ToList(); - + var moduleCustomization = GetUiModuleCustomization(module).GetValueOrDefault(); if (moduleCustomization == null) { - moduleCustomization = new UIModuleCustomization {Organization = this, Module = module}; + moduleCustomization = new UIModuleCustomization { Organization = this, Module = module }; UIModuleCustomizations.Add(moduleCustomization); } @@ -185,5 +193,273 @@ public Result ModifyModuleCustomization(s return moduleCustomization; } + + public Result ComputeExternalOrganizationHierarchyUpdateConsequences(OrganizationUnitOrigin origin, ExternalOrganizationUnit root, Maybe levelsIncluded) + { + if (root == null) throw new ArgumentNullException(nameof(root)); + + IExternalOrganizationalHierarchyUpdateStrategy strategy; + //Pre-validate + switch (origin) + { + case OrganizationUnitOrigin.STS_Organisation: + if (StsOrganizationConnection?.Connected != true) + { + return new OperationError($"Not connected to {origin:G}. Please connect before performing an update", OperationFailure.Conflict); + } + strategy = StsOrganizationConnection.GetUpdateStrategy(); + break; + case OrganizationUnitOrigin.Kitos: + return new OperationError("Kitos is not an external source", OperationFailure.BadInput); + default: + throw new ArgumentOutOfRangeException(); + } + + var childLevelsToInclude = levelsIncluded.Select(levels => levels - 1); //subtract the root level before copying + var filteredTree = root.Copy(childLevelsToInclude); + + return strategy.ComputeUpdate(filteredTree); + } + + public Maybe ConnectToExternalOrganizationHierarchy(OrganizationUnitOrigin origin, ExternalOrganizationUnit root, Maybe levelsIncluded) + { + if (root == null) + { + throw new ArgumentNullException(nameof(root)); + } + //Pre-validate + switch (origin) + { + case OrganizationUnitOrigin.STS_Organisation: + if (StsOrganizationConnection?.Connected == true) + { + return new OperationError($"Already connected to {origin:G}", OperationFailure.Conflict); + } + break; + case OrganizationUnitOrigin.Kitos: + return new OperationError("Kitos is not an external source", OperationFailure.BadInput); + default: + throw new ArgumentOutOfRangeException(); + } + + return GetRoot() + .FromNullable() + .Match + ( + currentOrgRoot => + { + var childLevelsToInclude = levelsIncluded.Select(levels => levels - 1); //Subtract one since first level is the root + return currentOrgRoot.ImportNewExternalOrganizationOrgTree(origin, root.Copy(childLevelsToInclude)); + }, + () => new OperationError("Unable to load current root", OperationFailure.UnknownError) + ).Match + (error => error, + () => + { + StsOrganizationConnection ??= new StsOrganizationConnection(); + StsOrganizationConnection.Connected = true; + StsOrganizationConnection.SynchronizationDepth = levelsIncluded.Match(levels => (int?)levels, () => default); + return Maybe.None; + } + ); + } + + public Result DisconnectOrganizationFromExternalSource(OrganizationUnitOrigin origin) + { + switch (origin) + { + case OrganizationUnitOrigin.STS_Organisation: + + if (StsOrganizationConnection?.Connected != true) + { + return new OperationError("Not connected", OperationFailure.BadState); + } + return StsOrganizationConnection.Disconnect(); + case OrganizationUnitOrigin.Kitos: + return new OperationError("Kitos is not an external source and cannot be disconnected", OperationFailure.BadInput); + default: + throw new ArgumentOutOfRangeException(); + } + } + + public Result UpdateConnectionToExternalOrganizationHierarchy(OrganizationUnitOrigin origin, ExternalOrganizationUnit root, Maybe levelsIncluded) + { + if (root == null) throw new ArgumentNullException(nameof(root)); + + IExternalOrganizationalHierarchyUpdateStrategy strategy; + //Pre-validate + switch (origin) + { + case OrganizationUnitOrigin.STS_Organisation: + if (StsOrganizationConnection?.Connected != true) + { + return new OperationError($"Not connected to {origin:G}. Please connect before performing an update", OperationFailure.BadState); + } + strategy = StsOrganizationConnection.GetUpdateStrategy(); + break; + case OrganizationUnitOrigin.Kitos: + return new OperationError("Kitos is not an external source", OperationFailure.BadInput); + default: + throw new ArgumentOutOfRangeException(); + } + + var childLevelsToInclude = levelsIncluded.Select(levels => levels - 1); //subtract the root level before copying + var filteredTree = root.Copy(childLevelsToInclude); + StsOrganizationConnection.SynchronizationDepth = levelsIncluded.Match(levels => (int?)levels, () => default); + + return strategy.PerformUpdate(filteredTree); + } + + /// + /// Adds a organization unit + /// + /// + /// If set to None, the new unit will be added to the organization root + /// + /// + public Maybe AddOrganizationUnit(OrganizationUnit newUnit, Maybe parentUnit) + { + if (newUnit == null) throw new ArgumentNullException(nameof(newUnit)); + if (parentUnit == null) throw new ArgumentNullException(nameof(parentUnit)); + var actualParent = parentUnit.GetValueOrFallback(GetRoot()); + if (newUnit == actualParent) + { + return new OperationError("new unit is the same as the parent", OperationFailure.BadInput); + } + + if (actualParent.Organization != this) + { + return new OperationError("Parent unit is from a different organization", OperationFailure.BadInput); + } + + var duplicateUnit = GetOrganizationUnit(newUnit.Uuid); + if (duplicateUnit.HasValue) + { + return new OperationError("Unit already added", OperationFailure.BadInput); + } + + if (GetOrganizationUnit(actualParent.Uuid).IsNone) + { + return new OperationError("Parent unit has not been added to the organization", OperationFailure.BadInput); + } + + var addedError = actualParent.AddChild(newUnit); + if (addedError.IsNone) + { + newUnit.Organization = this; + OrgUnits.Add(newUnit); + } + + return addedError; + } + + public Maybe RelocateOrganizationUnit(OrganizationUnit movedUnit, OrganizationUnit oldParentUnit, OrganizationUnit newParentUnit, bool includeSubtree) + { + if (movedUnit == null) throw new ArgumentNullException(nameof(movedUnit)); + if (oldParentUnit == null) throw new ArgumentNullException(nameof(oldParentUnit)); + if (newParentUnit == null) throw new ArgumentNullException(nameof(newParentUnit)); + if (GetOrganizationUnit(movedUnit.Uuid).IsNone) + { + return new OperationError($"Moved unit with uuid {movedUnit.Uuid} does not belong to this organization with uuid {Uuid}", OperationFailure.NotFound); + } + + if (GetOrganizationUnit(oldParentUnit.Uuid).IsNone) + { + return new OperationError($"old parent unit with uuid {oldParentUnit.Uuid} does not belong to this organization with uuid {Uuid}", OperationFailure.NotFound); + } + + if (GetOrganizationUnit(newParentUnit.Uuid).IsNone) + { + return new OperationError($"new parent unit with uuid {newParentUnit.Uuid} does not belong to this organization with uuid {Uuid}", OperationFailure.NotFound); + } + + if (movedUnit == oldParentUnit) + { + return new OperationError($"moved unit equals old parent unit with uuid {movedUnit.Uuid} in organization with uuid {Uuid}", OperationFailure.BadInput); + } + + if (movedUnit == newParentUnit) + { + return new OperationError($"moved unit equals new parent unit with uuid {movedUnit.Uuid} in organization with uuid {Uuid}", OperationFailure.BadInput); + } + + if (movedUnit == GetRoot()) + { + return new OperationError($"Cannot move the organization root", OperationFailure.BadInput); + } + + if (!includeSubtree) + { + //If sub tree is not part of the move, move the children to the moved unit's parent + var movedUnitParent = movedUnit.Parent; + foreach (var child in movedUnit.Children.ToList()) + { + RelocateOrganizationUnit(child, movedUnit, movedUnitParent, true); + } + } + else + { + //If subtree is to be moved along with it, then the target unit cannot be a descendant of the moved unit + if (movedUnit.FlattenHierarchy().Contains(newParentUnit)) + { + return new OperationError($"newParentUnit with uuid {newParentUnit.Uuid} is a descendant of org unit with uuid {movedUnit.Uuid}", OperationFailure.BadInput); + } + } + + var removeChildError = oldParentUnit.RemoveChild(movedUnit); + + if (removeChildError.HasValue) + { + return removeChildError.Value; + } + + return newParentUnit.AddChild(movedUnit); + } + + public Maybe DeleteOrganizationUnit(OrganizationUnit unitToDelete) + { + if (unitToDelete == null) throw new ArgumentNullException(nameof(unitToDelete)); + var organizationUnit = GetOrganizationUnit(unitToDelete.Uuid); + if (organizationUnit.IsNone) + { + return new OperationError($"Unit to delete with uuid {unitToDelete.Uuid} Does not belong to this organization with uuid {Uuid}", OperationFailure.NotFound); + } + + if (unitToDelete.IsUsed()) + { + return new OperationError($"Unit to delete with uuid {unitToDelete.Uuid} from organization with uuid {Uuid} cannot be deleted as it is still in use!", OperationFailure.BadInput); + } + + if (unitToDelete == GetRoot()) + { + return new OperationError("Cannot delete the organization root", OperationFailure.BadInput); + } + + //Migrate any children to the parent! + foreach (var child in unitToDelete.Children.ToList()) + { + var relocateOrganizationUnitError = RelocateOrganizationUnit(child, unitToDelete, unitToDelete.Parent, true); + if (relocateOrganizationUnitError.HasValue) + { + return relocateOrganizationUnitError; + } + } + + var removeChildError = unitToDelete.Parent.RemoveChild(unitToDelete); + + if (removeChildError.HasValue) + { + return removeChildError; + } + + OrgUnits.Remove(unitToDelete); + + return Maybe.None; + } + + private static bool MatchRoot(OrganizationUnit unit) + { + return unit.Parent == null; + } } } \ No newline at end of file diff --git a/Core.DomainModel/Organization/OrganizationTreeUpdateConsequences.cs b/Core.DomainModel/Organization/OrganizationTreeUpdateConsequences.cs new file mode 100644 index 0000000000..96528b984e --- /dev/null +++ b/Core.DomainModel/Organization/OrganizationTreeUpdateConsequences.cs @@ -0,0 +1,30 @@ +using System.Collections.Generic; + +namespace Core.DomainModel.Organization +{ + /// + /// Describes the consequences of an organization tree update + /// + public class OrganizationTreeUpdateConsequences + { + public IEnumerable DeletedExternalUnitsBeingConvertedToNativeUnits { get; } + public IEnumerable DeletedExternalUnitsBeingDeleted { get; } + public IEnumerable<(ExternalOrganizationUnit unitToAdd, ExternalOrganizationUnit parent)> AddedExternalOrganizationUnits { get; } + public IEnumerable<(OrganizationUnit affectedUnit, string oldName, string newName)> OrganizationUnitsBeingRenamed { get; } + public IEnumerable<(OrganizationUnit movedUnit, OrganizationUnit oldParent, ExternalOrganizationUnit newParent)> OrganizationUnitsBeingMoved { get; } + + public OrganizationTreeUpdateConsequences( + IEnumerable deletedExternalUnitsBeingConvertedToNativeUnits, + IEnumerable deletedExternalUnitsBeingDeleted, + IEnumerable<(ExternalOrganizationUnit unitToAdd, ExternalOrganizationUnit parent)> addedExternalOrganizationUnits, + IEnumerable<(OrganizationUnit affectedUnit, string oldName, string newName)> organizationUnitsBeingRenamed, + IEnumerable<(OrganizationUnit movedUnit, OrganizationUnit oldParent, ExternalOrganizationUnit newParent)> organizationUnitsBeingMoved) + { + DeletedExternalUnitsBeingConvertedToNativeUnits = deletedExternalUnitsBeingConvertedToNativeUnits; + DeletedExternalUnitsBeingDeleted = deletedExternalUnitsBeingDeleted; + AddedExternalOrganizationUnits = addedExternalOrganizationUnits; + OrganizationUnitsBeingRenamed = organizationUnitsBeingRenamed; + OrganizationUnitsBeingMoved = organizationUnitsBeingMoved; + } + } +} diff --git a/Core.DomainModel/Organization/OrganizationUnit.cs b/Core.DomainModel/Organization/OrganizationUnit.cs index de89420a8e..36e21f3e08 100644 --- a/Core.DomainModel/Organization/OrganizationUnit.cs +++ b/Core.DomainModel/Organization/OrganizationUnit.cs @@ -1,5 +1,8 @@ using System; using System.Collections.Generic; +using System.Linq; +using Core.Abstractions.Types; +using Core.DomainModel.Extensions; using Core.DomainModel.ItContract; using Core.DomainModel.ItSystemUsage; // ReSharper disable VirtualMemberCallInConstructor @@ -14,13 +17,26 @@ public class OrganizationUnit : HasRightsEntity(); OwnedTasks = new List(); DefaultUsers = new List(); Using = new List(); - Uuid = Guid.NewGuid(); + var uuid = Guid.NewGuid(); + Uuid = uuid; + Origin = OrganizationUnitOrigin.Kitos; + Children = new List(); + ResponsibleForItContracts = new List(); + EconomyStreams = new List(); } + /// + /// Determines the origin of the organization unit + /// + public OrganizationUnitOrigin Origin { get; set; } + /// + /// Determines the optional external origin-specific uuid + /// + public Guid? ExternalOriginUuid { get; set; } + public string LocalId { get; set; } public string Name { get; set; } @@ -42,24 +58,10 @@ public OrganizationUnit() /// The organization which the unit belongs to. /// public virtual Organization Organization { get; set; } - - /// - /// The usage of task on this Organization Unit. - /// Should be a subset of the TaskUsages of the parent department. - /// - public virtual ICollection TaskUsages { get; set; } - /// /// Local tasks that was created in this unit /// public virtual ICollection OwnedTasks { get; set; } - /// - /// Gets or sets the delegated system usages. - /// - /// - /// The delegated system usages. - /// - public virtual ICollection DelegatedSystemUsages { get; set; } /// /// Users which have set this as their default OrganizationUnit. @@ -112,5 +114,135 @@ public override OrganizationUnitRight CreateNewRight(OrganizationUnitRole role, } public Guid Uuid { get; set; } + + public Maybe ImportNewExternalOrganizationOrgTree(OrganizationUnitOrigin origin, ExternalOrganizationUnit importRoot) + { + if (importRoot == null) + { + throw new ArgumentNullException(nameof(importRoot)); + } + if (Origin == origin) + { + return new OperationError("Org unit already connected. Please do an update in stead", OperationFailure.BadState); + } + + //Switch the origin of the root + Origin = origin; + ExternalOriginUuid = importRoot.Uuid; + Name = importRoot.Name; + + foreach (var organizationUnit in importRoot.Children.Select(child => child.ToOrganizationUnit(origin, Organization)).ToList()) + { + Children.Add(organizationUnit); + } + + return Maybe.None; + } + + public void ConvertToNativeKitosUnit() + { + if (Origin == OrganizationUnitOrigin.Kitos) + { + throw new InvalidOperationException("Already a KITOS unit"); + } + + Origin = OrganizationUnitOrigin.Kitos; + ExternalOriginUuid = null; + } + + public bool IsNativeKitosUnit() + { + return Origin == OrganizationUnitOrigin.Kitos; + } + + public bool IsUsed() + { + return Using.Any() || EconomyStreams.Any() || ResponsibleForItContracts.Any() || Rights.Any(); + } + + public Maybe AddChild(OrganizationUnit child) + { + if (child == null) throw new ArgumentNullException(nameof(child)); + + if (child.Organization != Organization) + { + return new OperationError($"child with uuid {child.Uuid} is from a different organization", OperationFailure.BadInput); + } + + if (Children.Any(c => c.Uuid == child.Uuid)) + { + return new OperationError($"child with uuid {child.Uuid} already added", OperationFailure.BadInput); + } + + Children.Add(child); + child.Parent = this; + + return Maybe.None; + } + + public Maybe UpdateName(string newName) + { + if (string.IsNullOrWhiteSpace(newName)) + { + return new OperationError($"newName must be defined in this unit with id {Id}", OperationFailure.BadInput); + } + + if (newName.Length > MaxNameLength) + { + return new OperationError($"newName exceeds the max length of {MaxNameLength}", OperationFailure.BadInput); + } + + Name = newName; + return Maybe.None; + } + + public Maybe RemoveChild(OrganizationUnit child) + { + if (child == null) throw new ArgumentNullException(nameof(child)); + if (!Children.Remove(child)) + { + return new OperationError($"Child with id:{child.Id} could not be removed from this unit with id {Id} as it is not a child of this unit", OperationFailure.BadInput); + } + + child.ResetParent(); + return Maybe.None; + } + + public OrganizationUnitRegistrationDetails GetUnitRegistrations() + { + return new OrganizationUnitRegistrationDetails + ( + Rights.ToList(), + ResponsibleForItContracts.ToList(), + GetUnitPayments().ToList(), + Using.Where(x => x.ResponsibleItSystemUsage != null).Select(x => x.ResponsibleItSystemUsage).ToList(), + Using.Select(x => x.ItSystemUsage).ToList() + ); + } + + public Maybe GetRight(int rightId) + { + return Rights.FirstOrDefault(x => x.Id == rightId); + } + + private IEnumerable GetUnitPayments() + { + var internContracts = EconomyStreams.Where(x => x.InternPaymentFor != null).Select(x => x.InternPaymentFor).ToList(); + var externContracts = EconomyStreams.Where(x => x.ExternPaymentFor != null).Select(x => x.ExternPaymentFor).ToList(); + var contracts = internContracts.Concat(externContracts).GroupBy(x => x.Id).Select(x => x.First()).ToList(); + + return contracts + .Select(itContract => + new PaymentRegistrationDetails( + itContract, + itContract.GetInternalPaymentsForUnit(Id), + itContract.GetExternalPaymentsForUnit(Id))) + .ToList(); + } + + public void ResetParent() + { + Parent = null; + } } } diff --git a/Core.DomainModel/Organization/OrganizationUnitOrigin.cs b/Core.DomainModel/Organization/OrganizationUnitOrigin.cs new file mode 100644 index 0000000000..731622ad2e --- /dev/null +++ b/Core.DomainModel/Organization/OrganizationUnitOrigin.cs @@ -0,0 +1,14 @@ +namespace Core.DomainModel.Organization +{ + public enum OrganizationUnitOrigin + { + /// + /// Organization unit is created and maintained in kitos + /// + Kitos = 0, + /// + /// Organization unit was created and is maintained in STS Organisation + /// + STS_Organisation = 1 + } +} diff --git a/Core.DomainModel/Organization/OrganizationUnitRegistrationDetails.cs b/Core.DomainModel/Organization/OrganizationUnitRegistrationDetails.cs new file mode 100644 index 0000000000..cb2e3d5fe3 --- /dev/null +++ b/Core.DomainModel/Organization/OrganizationUnitRegistrationDetails.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +namespace Core.DomainModel.Organization +{ + public class OrganizationUnitRegistrationDetails + { + public OrganizationUnitRegistrationDetails( + IEnumerable organizationUnitRights, + IEnumerable itContractRegistrations, + IEnumerable paymentRegistrationDetails, + IEnumerable responsibleSystems, + IEnumerable relevantSystems) + { + OrganizationUnitRights = organizationUnitRights; + ItContractRegistrations = itContractRegistrations; + PaymentRegistrationDetails = paymentRegistrationDetails; + ResponsibleSystems = responsibleSystems; + RelevantSystems = relevantSystems; + } + + public IEnumerable OrganizationUnitRights { get; } + public IEnumerable ItContractRegistrations { get; } + public IEnumerable PaymentRegistrationDetails { get; } + public IEnumerable ResponsibleSystems { get; } + public IEnumerable RelevantSystems { get; } + } +} diff --git a/Core.DomainModel/Organization/PaymentRegistrationDetails.cs b/Core.DomainModel/Organization/PaymentRegistrationDetails.cs new file mode 100644 index 0000000000..d2f6692b0f --- /dev/null +++ b/Core.DomainModel/Organization/PaymentRegistrationDetails.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using Core.DomainModel.ItContract; + +namespace Core.DomainModel.Organization +{ + public class PaymentRegistrationDetails + { + public PaymentRegistrationDetails(ItContract.ItContract itContract, IEnumerable internalPayments, IEnumerable externalPayments) + { + ItContract = itContract; + InternalPayments = internalPayments; + ExternalPayments = externalPayments; + } + + public ItContract.ItContract ItContract { get; } + public IEnumerable InternalPayments { get; } + public IEnumerable ExternalPayments { get; } + } +} diff --git a/Core.DomainModel/Organization/Strategies/IExternalOrganizationalHierarchyUpdateStrategy.cs b/Core.DomainModel/Organization/Strategies/IExternalOrganizationalHierarchyUpdateStrategy.cs new file mode 100644 index 0000000000..3811c30128 --- /dev/null +++ b/Core.DomainModel/Organization/Strategies/IExternalOrganizationalHierarchyUpdateStrategy.cs @@ -0,0 +1,10 @@ +using Core.Abstractions.Types; + +namespace Core.DomainModel.Organization.Strategies +{ + public interface IExternalOrganizationalHierarchyUpdateStrategy + { + OrganizationTreeUpdateConsequences ComputeUpdate(ExternalOrganizationUnit root); + Result PerformUpdate(ExternalOrganizationUnit root); + } +} diff --git a/Core.DomainModel/Organization/Strategies/StsOrganizationalHierarchyUpdateStrategy.cs b/Core.DomainModel/Organization/Strategies/StsOrganizationalHierarchyUpdateStrategy.cs new file mode 100644 index 0000000000..af314f2b55 --- /dev/null +++ b/Core.DomainModel/Organization/Strategies/StsOrganizationalHierarchyUpdateStrategy.cs @@ -0,0 +1,268 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Core.Abstractions.Types; +using Core.DomainModel.Extensions; + +namespace Core.DomainModel.Organization.Strategies +{ + public class StsOrganizationalHierarchyUpdateStrategy : IExternalOrganizationalHierarchyUpdateStrategy + { + private readonly Organization _organization; + + public StsOrganizationalHierarchyUpdateStrategy(Organization organization) + { + _organization = organization; + } + + public OrganizationTreeUpdateConsequences ComputeUpdate(ExternalOrganizationUnit root) + { + var currentTreeByUuid = _organization + .OrgUnits + .Where(unit => unit.Origin == OrganizationUnitOrigin.STS_Organisation) + .ToDictionary(x => x.ExternalOriginUuid.GetValueOrDefault()); + + if (currentTreeByUuid.Count == 0) + { + throw new InvalidOperationException("No organization units from STS Organisation found in the current hierarchy"); + } + + var importedTreeByUuid = root + .Flatten() + .ToDictionary(x => x.Uuid); + + var importedTreeToParent = importedTreeByUuid + .Values + .SelectMany(parent => parent.Children.Select(child => (child, parent))) + .ToDictionary(x => x.child.Uuid, x => x.parent); + + importedTreeToParent.Add(root.Uuid, null); //Add the root as that will not be part of the collection + + //Keys in both collections + var commonKeys = currentTreeByUuid.Keys.Intersect(importedTreeByUuid.Keys).ToList(); + + //Compute renames and "change of parents" + var renamedUnits = new List<(OrganizationUnit current, ExternalOrganizationUnit imported)>(); + var parentChanges = new List<(OrganizationUnit movedUnit, OrganizationUnit oldParent, ExternalOrganizationUnit newParent)>(); + + foreach (var commonKey in commonKeys) + { + var current = currentTreeByUuid[commonKey]; + var imported = importedTreeByUuid[commonKey]; + + //Renames + if (imported.Name != current.Name) + { + renamedUnits.Add((current, imported)); + } + + //Moving parent + var importedParent = importedTreeToParent[commonKey]; + if (importedParent?.Uuid != current.Parent?.ExternalOriginUuid.GetValueOrDefault()) + { + parentChanges.Add((current, current.Parent, importedParent)); + } + } + + //Compute additions + var additions = new List<(ExternalOrganizationUnit unitToAdd, ExternalOrganizationUnit parent)>(); + foreach (var newUnitUuid in importedTreeByUuid.Keys.Except(commonKeys).ToList()) + { + var imported = importedTreeByUuid[newUnitUuid]; + additions.Add((imported, importedTreeToParent[newUnitUuid])); + } + + //Compute which of the potential removals that will result in removal and which will result in migration + var candidatesForRemovalById = currentTreeByUuid + .Keys + .Except(commonKeys) + .Select(uuid => currentTreeByUuid[uuid]) + .ToDictionary(x => x.Id); + + var removedExternalUnitsWhichMustBeConverted = new List(); + var removedExternalUnitsWhichMustBeRemoved = new List(); + + foreach (var candidateForRemoval in candidatesForRemovalById) + { + var organizationUnit = candidateForRemoval.Value; + var removedSubtreeIds = organizationUnit + .FlattenHierarchy() + .Select(x => x.Id) + .ToHashSet(); + + var partsOfSubtreeWhichAreMoved = parentChanges + .Where(x => removedSubtreeIds.Contains(x.movedUnit.Id)) + .SelectMany(x => x.movedUnit.FlattenHierarchy()) + .ToList(); + + //Remove all "moved" parts of the sub tree + foreach (var movedUnit in partsOfSubtreeWhichAreMoved) + { + removedSubtreeIds.Remove(movedUnit.Id); + } + + //Remove all "removed" parts of the sub tree + bool IsNotCurrentCandidate(KeyValuePair keyValuePair) => keyValuePair.Key != candidateForRemoval.Key; + var otherRemovals = candidatesForRemovalById.Where(IsNotCurrentCandidate).ToList(); + foreach (var removedItem in otherRemovals) + { + removedSubtreeIds.Remove(removedItem.Key); + } + + if (removedSubtreeIds.Count != 1) + { + //Anything left except the candidate, then we must convert the unit to a KITOS-unit? + removedExternalUnitsWhichMustBeConverted.Add(organizationUnit); + } + else if (organizationUnit.IsUsed()) + { + //If there is still registrations, we must convert it + removedExternalUnitsWhichMustBeConverted.Add(organizationUnit); + } + else + { + //Safe to remove since there is no remaining sub tree and no remaining registrations tied to it + removedExternalUnitsWhichMustBeRemoved.Add(organizationUnit); + } + } + + return new OrganizationTreeUpdateConsequences( + removedExternalUnitsWhichMustBeConverted, + removedExternalUnitsWhichMustBeRemoved, + additions, + renamedUnits.Select(x => (x.current, x.current.Name, x.imported.Name)).ToList(), + parentChanges); + } + + public Result PerformUpdate(ExternalOrganizationUnit root) + { + var consequences = ComputeUpdate(root); + var currentTreeByUuid = _organization + .OrgUnits + .Where(unit => unit.Origin == OrganizationUnitOrigin.STS_Organisation) + .ToDictionary(x => x.ExternalOriginUuid.GetValueOrDefault()); + + //Renaming + foreach (var (affectedUnit, _, newName) in consequences.OrganizationUnitsBeingRenamed) + { + var nameToUse = newName ?? ""; + if (nameToUse.Length > OrganizationUnit.MaxNameLength) + { + nameToUse = nameToUse.Substring(0, OrganizationUnit.MaxNameLength); + } + var updateNameError = affectedUnit.UpdateName(nameToUse); + if (updateNameError.HasValue) + { + return updateNameError.Value; + } + } + + //Conversion to native units + foreach (var unitToNativeUnit in consequences.DeletedExternalUnitsBeingConvertedToNativeUnits) + { + unitToNativeUnit.ConvertToNativeKitosUnit(); + } + + //Addition of new units + foreach (var (unitToAdd, parent) in OrderByParentToLeaf(root, consequences.AddedExternalOrganizationUnits)) + { + if (currentTreeByUuid.TryGetValue(parent.Uuid, out var parentUnit)) + { + var newUnit = unitToAdd.ToOrganizationUnit(OrganizationUnitOrigin.STS_Organisation, _organization, false); + + var addOrgUnitError = _organization.AddOrganizationUnit(newUnit, parentUnit); + if (addOrgUnitError.HasValue) + { + return addOrgUnitError.Value; + } + + currentTreeByUuid.Add(unitToAdd.Uuid, newUnit); + } + else + { + return new OperationError($"Parent unit with external uuid {parent.Uuid} could not be found", OperationFailure.BadInput); + } + } + + //Relocation of existing units + foreach (var (movedUnit, oldParent, newParent) in consequences.OrganizationUnitsBeingMoved) + { + if (!currentTreeByUuid.TryGetValue(oldParent.ExternalOriginUuid.GetValueOrDefault(), out var oldParentUnit)) + { + return new OperationError($"Old parent unit with uuid {oldParent.Uuid} could not be found", OperationFailure.BadInput); + } + + if (!currentTreeByUuid.TryGetValue(newParent.Uuid, out var newParentUnit)) + { + return new OperationError($"New parent unit with external uuid {newParent.Uuid} could not be found", OperationFailure.BadInput); + + } + + var nativeUnitsCreatedUnderMovedExternalUnit = movedUnit.Children.Where(child=>child.Origin == OrganizationUnitOrigin.Kitos).ToList(); + + //Move the moved unit without affecting the subtree (let the consequences decide that) + var relocationError = _organization.RelocateOrganizationUnit(movedUnit, oldParentUnit, newParentUnit, false); + if (relocationError.HasValue) + { + return relocationError.Value; + } + //Make sure that "native" children created on the moved unit "tags along" as opposed to connected units which should only be moved if moved in fk org + foreach (var child in nativeUnitsCreatedUnderMovedExternalUnit) + { + //Only native nodes can exist as children to native units, so reloacte the sub tree + var childRelocationError = _organization.RelocateOrganizationUnit(child, child.Parent, movedUnit, true); + if (childRelocationError.HasValue) + { + return childRelocationError.Value; + } + } + } + + //Deletion of units + foreach (var externalUnitToDelete in OrderUnitsToDeleteByLeafToParent(_organization.GetRoot(), consequences.DeletedExternalUnitsBeingDeleted)) + { + externalUnitToDelete.ConvertToNativeKitosUnit(); //Convert to KITOS unit before deleting it (external units cannot be deleted) + var deleteOrganizationUnitError = _organization.DeleteOrganizationUnit(externalUnitToDelete); + if (deleteOrganizationUnitError.HasValue) + { + return deleteOrganizationUnitError.Value; + } + } + + return consequences; + } + + private static IEnumerable OrderUnitsToDeleteByLeafToParent(OrganizationUnit root, IEnumerable deletedUnits) + { + var unitsToDelete = deletedUnits.ToList(); + var relevantIds = unitsToDelete.Select(x => x.Uuid).ToHashSet(); + + var ordering = CreateUuidToIndexMap(root.FlattenHierarchy().Select(x => x.Uuid).ToList(), relevantIds); + + //Make sure leafs are added before children + return unitsToDelete.OrderByDescending(unitToDelete => ordering[unitToDelete.Uuid]).ToList(); + } + + private static IEnumerable<(ExternalOrganizationUnit unitToAdd, ExternalOrganizationUnit parent)> OrderByParentToLeaf(ExternalOrganizationUnit externalRoot, IEnumerable<(ExternalOrganizationUnit unitToAdd, ExternalOrganizationUnit parent)> addedUnits) + { + var unitsToAdd = addedUnits.ToList(); + var relevantIds = unitsToAdd.SelectMany(x => new[] { x.parent.Uuid, x.unitToAdd.Uuid }).ToHashSet(); + var ordering = CreateUuidToIndexMap(externalRoot.Flatten().Select(x => x.Uuid).ToList(), relevantIds); + + //Make sure parents are added before children + return unitsToAdd.OrderBy(unitToAdd => ordering[unitToAdd.unitToAdd.Uuid]).ToList(); + } + + private static Dictionary CreateUuidToIndexMap(IEnumerable flattenedHierarchy, HashSet relevantIds) + { + var ordering = flattenedHierarchy + //Select only the parts that we care about + .Where(relevantIds.Contains) + //Find the ordering key of those units + .Select((uuid, index) => new { uuid, index }) + //Create the lookup + .ToDictionary(x => x.uuid, x => x.index); + return ordering; + } + } +} diff --git a/Core.DomainModel/Organization/StsOrganizationConnection.cs b/Core.DomainModel/Organization/StsOrganizationConnection.cs new file mode 100644 index 0000000000..eb06676fd5 --- /dev/null +++ b/Core.DomainModel/Organization/StsOrganizationConnection.cs @@ -0,0 +1,36 @@ +using System.Linq; +using Core.DomainModel.Organization.Strategies; + +namespace Core.DomainModel.Organization +{ + + /// + /// Determines the properties of the organization's connection to STS Organisation + /// + public class StsOrganizationConnection : Entity, IOwnedByOrganization + { + public int OrganizationId { get; set; } + public virtual Organization Organization { get; set; } + public bool Connected { get; set; } + /// + /// Determines the optional synchronization depth used during synchronization from STS Organisation + /// + public int? SynchronizationDepth { get; set; } + //TODO https://os2web.atlassian.net/browse/KITOSUDV-3317 adds the change logs here + //TODO: https://os2web.atlassian.net/browse/KITOSUDV-3312 adds automatic subscription here + public DisconnectOrganizationFromOriginResult Disconnect() + { + var organizationUnits = Organization.OrgUnits.Where(x => x.Origin == OrganizationUnitOrigin.STS_Organisation).ToList(); + organizationUnits.ForEach(unit => unit.ConvertToNativeKitosUnit()); + + Connected = false; + SynchronizationDepth = null; + return new DisconnectOrganizationFromOriginResult(organizationUnits); + } + + public IExternalOrganizationalHierarchyUpdateStrategy GetUpdateStrategy() + { + return new StsOrganizationalHierarchyUpdateStrategy(Organization); + } + } +} diff --git a/Core.DomainModel/Organization/TaskRef.cs b/Core.DomainModel/Organization/TaskRef.cs index 89726576d6..3e62d6f616 100644 --- a/Core.DomainModel/Organization/TaskRef.cs +++ b/Core.DomainModel/Organization/TaskRef.cs @@ -18,7 +18,6 @@ public TaskRef() this.ItSystems = new List(); this.ItSystemUsages = new List(); this.ItSystemUsagesOptOut = new List(); - this.Usages = new List(); } /// @@ -55,11 +54,6 @@ public TaskRef() public virtual TaskRef Parent { get; set; } public virtual ICollection Children { get; set; } - /// - /// Usages of this task - /// - public virtual ICollection Usages { get; set; } - /// /// ItSystems which have been marked with this task /// diff --git a/Core.DomainModel/Organization/TaskUsage.cs b/Core.DomainModel/Organization/TaskUsage.cs deleted file mode 100644 index 5ecf1dd9f1..0000000000 --- a/Core.DomainModel/Organization/TaskUsage.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Collections.Generic; - -namespace Core.DomainModel.Organization -{ - /// - /// Represents that aTaskRef has been marked as important for an - /// OrganizationUnit. - /// Helper object which can hold comments and status property - /// - public class TaskUsage : Entity, IHierarchy, IOrganizationModule, ISupportsUserSpecificAccessControl - { - public TaskUsage() - { - Children = new List(); - } - - public int TaskRefId { get; set; } - /// - /// The task in use - /// - public virtual TaskRef TaskRef { get; set; } - - public int OrgUnitId { get; set; } - /// - /// The organization unit which uses the task - /// - public virtual OrganizationUnit OrgUnit { get; set; } - - public int? ParentId { get; set; } - /// - /// If the parent of also has marked the , - /// the parent usage is accesible from here. - /// - public virtual TaskUsage Parent { get; set; } - - /// - /// Child usages (see ) - /// - public virtual ICollection Children { get; set; } - - /// - /// Whether the TaskUsage can be found on the overview - /// - public bool Starred { get; set; } - - public TrafficLight TechnologyStatus { get; set; } - public TrafficLight UsageStatus { get; set; } - - public string Comment { get; set; } - - public bool HasUserWriteAccess(User user) - { - return OrgUnit != null && OrgUnit.HasUserWriteAccess(user); - } - } -} diff --git a/Core.DomainModel/Organization/UnitAccessRights.cs b/Core.DomainModel/Organization/UnitAccessRights.cs new file mode 100644 index 0000000000..336cd24d9e --- /dev/null +++ b/Core.DomainModel/Organization/UnitAccessRights.cs @@ -0,0 +1,26 @@ +namespace Core.DomainModel.Organization +{ + public class UnitAccessRights + { + public UnitAccessRights(bool canBeRead, bool canBeModified, bool canBeRenamed, bool canInfoAdditionalfieldsBeModified, bool canBeRearranged, bool canBeDeleted) + { + CanBeRead = canBeRead; + CanBeModified = canBeModified; + CanBeRenamed = canBeRenamed; + CanEanBeModified = canInfoAdditionalfieldsBeModified; + CanDeviceIdBeModified= canInfoAdditionalfieldsBeModified; + CanBeRearranged = canBeRearranged; + CanBeDeleted = canBeDeleted; + } + + public static UnitAccessRights ReadOnly() => new(true, false, false, false, false, false); + + public bool CanBeRead { get; } + public bool CanBeModified { get; } + public bool CanBeRenamed { get; } + public bool CanEanBeModified { get; } + public bool CanDeviceIdBeModified { get; } + public bool CanBeRearranged{ get; } + public bool CanBeDeleted { get; } + } +} diff --git a/Core.DomainModel/Organization/UnitAccessRightsWithUnitData.cs b/Core.DomainModel/Organization/UnitAccessRightsWithUnitData.cs new file mode 100644 index 0000000000..62c9e8d132 --- /dev/null +++ b/Core.DomainModel/Organization/UnitAccessRightsWithUnitData.cs @@ -0,0 +1,14 @@ +namespace Core.DomainModel.Organization +{ + public class UnitAccessRightsWithUnitData + { + public UnitAccessRightsWithUnitData(OrganizationUnit organizationUnit, UnitAccessRights unitAccessRights) + { + OrganizationUnit = organizationUnit; + UnitAccessRights = unitAccessRights; + } + + public OrganizationUnit OrganizationUnit { get; } + public UnitAccessRights UnitAccessRights { get; } + } +} diff --git a/Core.DomainModel/User.cs b/Core.DomainModel/User.cs index c5c0f48da3..5424cdb692 100644 --- a/Core.DomainModel/User.cs +++ b/Core.DomainModel/User.cs @@ -7,6 +7,7 @@ using Core.DomainModel.Organization; using Core.DomainModel.SSO; using Core.DomainModel.Tracking; +using Core.DomainModel.Users; // ReSharper disable VirtualMemberCallInConstructor @@ -41,7 +42,6 @@ public User() public string Password { get; set; } public string Salt { get; set; } public DateTime? LastAdvisDate { get; set; } - public string EmailBeforeDeletion { get; set; } public DateTime? DeletedDate { get; set; } public bool Deleted { get; set; } @@ -50,6 +50,22 @@ public User() /// User has been granted api access /// public bool? HasApiAccess { get; set; } + + public IEnumerable GetAuthenticationSchemes() + { + if (CanAuthenticate()) + { + if (HasApiAccess == true) + { + //API users can only authenticate with tokens + yield return AuthenticationScheme.Token; + } + else + { + yield return AuthenticationScheme.Cookie; + } + } + } /// /// User has been marked as a user with stake holder access /// diff --git a/Core.DomainModel/Users/AuthenticationScheme.cs b/Core.DomainModel/Users/AuthenticationScheme.cs new file mode 100644 index 0000000000..926b9de9ef --- /dev/null +++ b/Core.DomainModel/Users/AuthenticationScheme.cs @@ -0,0 +1,8 @@ +namespace Core.DomainModel.Users +{ + public enum AuthenticationScheme + { + Cookie, + Token + } +} diff --git a/Core.DomainModel/Users/OrganizationalUserDeletionStrategy.cs b/Core.DomainModel/Users/OrganizationalUserDeletionStrategy.cs new file mode 100644 index 0000000000..62c741b91b --- /dev/null +++ b/Core.DomainModel/Users/OrganizationalUserDeletionStrategy.cs @@ -0,0 +1,8 @@ +namespace Core.DomainModel.Users +{ + public enum OrganizationalUserDeletionStrategy + { + Local = 0, + Global = 1 + } +} diff --git a/Core.DomainServices/Core.DomainServices.csproj b/Core.DomainServices/Core.DomainServices.csproj index ce9a997d10..4289aa1cbd 100644 --- a/Core.DomainServices/Core.DomainServices.csproj +++ b/Core.DomainServices/Core.DomainServices.csproj @@ -90,8 +90,8 @@ + - @@ -262,7 +262,7 @@ Core.Abstractions - {a76a8e41-74f7-4443-a5f3-059b5414d83b} + {A76A8E41-74F7-4443-A5F3-059B5414D83B} Core.DomainModel diff --git a/Core.DomainServices/IOrgUnitService.cs b/Core.DomainServices/IOrgUnitService.cs index 2164a18981..1538a64068 100644 --- a/Core.DomainServices/IOrgUnitService.cs +++ b/Core.DomainServices/IOrgUnitService.cs @@ -9,14 +9,9 @@ namespace Core.DomainServices { public interface IOrgUnitService { - OrganizationUnit GetRoot(OrganizationUnit unit); - ICollection GetSubTree(int orgUnitId); - ICollection GetSubTree(OrganizationUnit unit); - bool IsAncestorOf(OrganizationUnit unitA, OrganizationUnit unitB); - bool IsAncestorOf(int unitIdA, int unitIdB); - void Delete(int id); + bool DescendsFrom(int descendantUnitId, int ancestorUnitId); IQueryable GetOrganizationUnits(Organization organization); Maybe GetOrganizationUnit(Guid uuid); } diff --git a/Core.DomainServices/Model/StsOrganization/CheckConnectionError.cs b/Core.DomainServices/Model/StsOrganization/CheckConnectionError.cs new file mode 100644 index 0000000000..079ef094b4 --- /dev/null +++ b/Core.DomainServices/Model/StsOrganization/CheckConnectionError.cs @@ -0,0 +1,10 @@ +namespace Core.DomainServices.Model.StsOrganization +{ + public enum CheckConnectionError + { + InvalidCvrOnOrganization = 0, + MissingServiceAgreement = 1, + ExistingServiceAgreementIssue = 2, + Unknown = 3 + } +} diff --git a/Core.DomainServices/Model/StsOrganization/ResolveOrganizationUuidError.cs b/Core.DomainServices/Model/StsOrganization/ResolveOrganizationUuidError.cs index 6ba86f118f..2252c56de7 100644 --- a/Core.DomainServices/Model/StsOrganization/ResolveOrganizationUuidError.cs +++ b/Core.DomainServices/Model/StsOrganization/ResolveOrganizationUuidError.cs @@ -6,6 +6,8 @@ public enum ResolveOrganizationUuidError FailedToLookupOrganizationCompany, FailedToSearchForOrganizationByCompanyUuid, DuplicateOrganizationResults, - FailedToSaveUuidOnKitosOrganization + FailedToSaveUuidOnKitosOrganization, + MissingServiceAgreement, + ExistingServiceAgreementIssue } } diff --git a/Core.DomainServices/Model/StsOrganization/StsOrganizationUnit.cs b/Core.DomainServices/Model/StsOrganization/StsOrganizationUnit.cs deleted file mode 100644 index c9f4ff5699..0000000000 --- a/Core.DomainServices/Model/StsOrganization/StsOrganizationUnit.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Core.DomainServices.Model.StsOrganization -{ - public class StsOrganizationUnit - { - public Guid Uuid { get; } - public string Name { get; } - public string UserFacingKey { get; } - public IEnumerable Children { get; } - - public StsOrganizationUnit(Guid uuid, string name, string userFacingKey, IEnumerable children) - { - Uuid = uuid; - Name = name; - UserFacingKey = userFacingKey; - Children = children.ToList().AsReadOnly(); - } - - public StsOrganizationUnit Copy(uint? childLevelsToInclude = null) - { - var children = new List(); - var includeChildren = childLevelsToInclude is > 0 or null; - if (includeChildren) - { - if (childLevelsToInclude.HasValue) - { - childLevelsToInclude--; - } - children = Children.Select(child => child.Copy(childLevelsToInclude)).ToList(); - } - - return new StsOrganizationUnit(Uuid, Name, UserFacingKey, children); - } - } -} diff --git a/Core.DomainServices/Organizations/IStsOrganizationCompanyLookupService.cs b/Core.DomainServices/Organizations/IStsOrganizationCompanyLookupService.cs index 4e7f476e33..6e049132fc 100644 --- a/Core.DomainServices/Organizations/IStsOrganizationCompanyLookupService.cs +++ b/Core.DomainServices/Organizations/IStsOrganizationCompanyLookupService.cs @@ -1,11 +1,12 @@ using System; using Core.Abstractions.Types; using Core.DomainModel.Organization; +using Infrastructure.STS.Common.Model; namespace Core.DomainServices.Organizations { public interface IStsOrganizationCompanyLookupService { - Result ResolveStsOrganizationCompanyUuid(Organization organization); + Result> ResolveStsOrganizationCompanyUuid(Organization organization); } } diff --git a/Core.DomainServices/Organizations/IStsOrganizationService.cs b/Core.DomainServices/Organizations/IStsOrganizationService.cs index 0d705c69a3..3b4c87e135 100644 --- a/Core.DomainServices/Organizations/IStsOrganizationService.cs +++ b/Core.DomainServices/Organizations/IStsOrganizationService.cs @@ -7,6 +7,7 @@ namespace Core.DomainServices.Organizations { public interface IStsOrganizationService { + Maybe> ValidateConnection(Organization organization); Result> ResolveStsOrganizationUuid(Organization organization); } } diff --git a/Core.DomainServices/Organizations/IStsOrganizationUnitService.cs b/Core.DomainServices/Organizations/IStsOrganizationUnitService.cs index 78e320f582..f2d8ad7468 100644 --- a/Core.DomainServices/Organizations/IStsOrganizationUnitService.cs +++ b/Core.DomainServices/Organizations/IStsOrganizationUnitService.cs @@ -6,6 +6,6 @@ namespace Core.DomainServices.Organizations { public interface IStsOrganizationUnitService { - Result> ResolveOrganizationTree(Organization organization); + Result> ResolveOrganizationTree(Organization organization); } } diff --git a/Core.DomainServices/Organizations/OrgUnitService.cs b/Core.DomainServices/Organizations/OrgUnitService.cs index 0c01a7c26a..c57d931ca6 100644 --- a/Core.DomainServices/Organizations/OrgUnitService.cs +++ b/Core.DomainServices/Organizations/OrgUnitService.cs @@ -3,7 +3,7 @@ using System.Linq; using Core.Abstractions.Extensions; using Core.Abstractions.Types; -using Core.DomainModel.ItSystemUsage; +using Core.DomainModel.Extensions; using Core.DomainModel.Organization; using Core.DomainServices.Extensions; @@ -13,118 +13,28 @@ namespace Core.DomainServices.Organizations public class OrgUnitService : IOrgUnitService { private readonly IGenericRepository _orgUnitRepository; - private readonly IGenericRepository _itSystemUsageOrgUnitUsageRepository; - private readonly IGenericRepository _taskUsageRepository; - public OrgUnitService(IGenericRepository orgUnitRepository, IGenericRepository taskUsageRepository, IGenericRepository itSystemUsageOrgUnitUsageRepository) + public OrgUnitService(IGenericRepository orgUnitRepository) { _orgUnitRepository = orgUnitRepository; - _taskUsageRepository = taskUsageRepository; - _itSystemUsageOrgUnitUsageRepository = itSystemUsageOrgUnitUsageRepository; - } - - public OrganizationUnit GetRoot(OrganizationUnit unit) - { - var whereWeStarted = unit; - - while (unit.Parent != null) - { - unit = unit.Parent; - - //did we get a loop? - if (unit.Id == whereWeStarted.Id) throw new Exception("Loop in Organization Units"); - } - - return unit; } public ICollection GetSubTree(int orgUnitId) { var orgUnit = _orgUnitRepository.GetByKey(orgUnitId); - return GetSubTree(orgUnit); - } - - public ICollection GetSubTree(OrganizationUnit unit) - { - var unreached = new Queue(); - var reached = new List(); - - unreached.Enqueue(unit); - while (unreached.Count > 0) - { - var orgUnit = unreached.Dequeue(); - - reached.Add(orgUnit); - - foreach (var child in orgUnit.Children) - { - unreached.Enqueue(child); - } - } - - return reached; + return orgUnit.FlattenHierarchy().ToList(); } - public bool IsAncestorOf(OrganizationUnit unit, OrganizationUnit ancestor) + public bool DescendsFrom(int descendantUnitId, int ancestorUnitId) { - if (unit == null || ancestor == null) return false; - - do - { - if (unit.Id == ancestor.Id) return true; - - unit = unit.Parent; - - } while (unit != null); - - return false; - } - - public bool IsAncestorOf(int unitId, int ancestorId) - { - var unit = _orgUnitRepository.GetByKey(unitId); - var ancestor = _orgUnitRepository.GetByKey(ancestorId); - - return IsAncestorOf(unit, ancestor); - } - - public void Delete(int id) - { - // delete task usages - var taskUsages = _taskUsageRepository.Get(x => x.OrgUnitId == id); - foreach (var taskUsage in taskUsages) - { - _taskUsageRepository.DeleteByKey(taskUsage.Id); - } - _taskUsageRepository.Save(); - - - // Remove OrgUnit from ItSystemUsages - var itSystemUsageOrgUnitUsages = _itSystemUsageOrgUnitUsageRepository.Get(x => x.OrganizationUnitId == id); - foreach (var itSystemUsage in itSystemUsageOrgUnitUsages) - { - if (itSystemUsage.ResponsibleItSystemUsage != null) - { - throw new ArgumentException($"OrganizationUnit is ResponsibleOrgUnit for ItSystemUsage: {itSystemUsage.ItSystemUsageId}"); - } - - _itSystemUsageOrgUnitUsageRepository.Delete(itSystemUsage); - - } - _itSystemUsageOrgUnitUsageRepository.Save(); - - var orgUnit = _orgUnitRepository.GetByKey(id); - - // attach children to parent of this instance to avoid orphans - // parent id will never be null because users aren't allowed to delete the root node - foreach (var child in orgUnit.Children) + var unit = _orgUnitRepository.GetByKey(descendantUnitId); + if (unit == null) { - child.ParentId = orgUnit.ParentId; + throw new ArgumentException($"Invalid org unit id:{descendantUnitId}"); } - _orgUnitRepository.DeleteWithReferencePreload(orgUnit); - _orgUnitRepository.Save(); + return unit.SearchAncestry(ancestor => ancestor.Id == ancestorUnitId).HasValue; } public IQueryable GetOrganizationUnits(Organization organization) diff --git a/Core.DomainServices/Repositories/Contract/IItContractOverviewReadModelRepository.cs b/Core.DomainServices/Repositories/Contract/IItContractOverviewReadModelRepository.cs index 5a94490221..b7e9b4f54c 100644 --- a/Core.DomainServices/Repositories/Contract/IItContractOverviewReadModelRepository.cs +++ b/Core.DomainServices/Repositories/Contract/IItContractOverviewReadModelRepository.cs @@ -15,7 +15,7 @@ public interface IItContractOverviewReadModelRepository IQueryable GetByParentContract(int parentContractId); IQueryable GetByTerminationDeadlineType(int terminationDeadlineId); IQueryable GetByOptionExtendType(int optionExtendTypeId); - IQueryable GetByItSystem(int itSystemId); + IQueryable GetSourceIdsByItSystem(int itSystemId); IQueryable GetByItSystemUsage(int systemUsageId); IQueryable GetByDataProcessingRegistration(int dprId); IQueryable GetByUser(int userId); diff --git a/Core.DomainServices/Repositories/Contract/ItContractOverviewReadModelRepository.cs b/Core.DomainServices/Repositories/Contract/ItContractOverviewReadModelRepository.cs index d4b948123a..fc6557d610 100644 --- a/Core.DomainServices/Repositories/Contract/ItContractOverviewReadModelRepository.cs +++ b/Core.DomainServices/Repositories/Contract/ItContractOverviewReadModelRepository.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using Core.Abstractions.Extensions; using Core.Abstractions.Types; @@ -92,32 +93,30 @@ public IQueryable GetByOptionExtendType(int optionE return BeginQuery().Where(x => x.OptionExtendId == optionExtendTypeId); } - public IQueryable GetByItSystem(int itSystemId) + public IQueryable GetSourceIdsByItSystem(int itSystemId) { var itSystem = _itSystemRepository.GetSystem(itSystemId); - var emptyQuery = Enumerable.Empty().AsQueryable(); + var sourceIds = new List(); if (itSystem == null) { - return emptyQuery; + return sourceIds.AsQueryable(); } var usageIds = itSystem.Usages.Select(x => x.Id).ToList(); if (!usageIds.Any()) { - return emptyQuery; + return sourceIds.AsQueryable(); } - IQueryable query = null; foreach (var usageId in usageIds) { - var byUsageQuery = GetByItSystemUsage(usageId); + sourceIds.AddRange(GetByItSystemUsage(usageId).Select(x => x.SourceEntityId).ToList()); - query = query == null ? byUsageQuery : query.Union(byUsageQuery); } - return query; + return sourceIds.AsQueryable(); } diff --git a/Core.DomainServices/Repositories/KLE/KLEStandardRepository.cs b/Core.DomainServices/Repositories/KLE/KLEStandardRepository.cs index db4fa80f1b..18770fa2ae 100644 --- a/Core.DomainServices/Repositories/KLE/KLEStandardRepository.cs +++ b/Core.DomainServices/Repositories/KLE/KLEStandardRepository.cs @@ -23,7 +23,6 @@ public class KLEStandardRepository : IKLEStandardRepository private readonly ITransactionManager _transactionManager; private readonly IGenericRepository _existingTaskRefRepository; private readonly IGenericRepository _systemUsageRepository; - private readonly IGenericRepository _taskUsageRepository; private readonly IKLEParentHelper _kleParentHelper; private readonly IKLEConverterHelper _kleConverterHelper; private readonly ILogger _logger; @@ -34,10 +33,9 @@ public KLEStandardRepository( ITransactionManager transactionManager, IGenericRepository existingTaskRefRepository, IGenericRepository systemUsageRepository, - IGenericRepository taskUsageRepository, IOperationClock clock, ILogger logger, - IDomainEvents domainEvents) : this(new KLEParentHelper(), new KLEConverterHelper(clock), taskUsageRepository) + IDomainEvents domainEvents) : this(new KLEParentHelper(), new KLEConverterHelper(clock)) { _kleDataBridge = kleDataBridge; _transactionManager = transactionManager; @@ -47,11 +45,10 @@ public KLEStandardRepository( _domainEvents = domainEvents; } - private KLEStandardRepository(IKLEParentHelper kleParentHelper, IKLEConverterHelper kleConverterHelper, IGenericRepository taskUsageRepository) + private KLEStandardRepository(IKLEParentHelper kleParentHelper, IKLEConverterHelper kleConverterHelper) { _kleParentHelper = kleParentHelper; _kleConverterHelper = kleConverterHelper; - _taskUsageRepository = taskUsageRepository; } public KLEStatus GetKLEStatus(Maybe lastUpdated) @@ -186,7 +183,6 @@ private void UpdateRemovedTaskRefs(IEnumerable changes) RemoveSystemUsageOptOutTaskRefs(kleChange); } RemoveSystemUsageTaskRefs(removals); - RemoveTaskUsageTaskRef(removals); RemoveTaskRef(removals); } @@ -235,17 +231,6 @@ private void RemoveSystemUsageTaskRefs(List kleChanges) } } - private void RemoveTaskUsageTaskRef(IEnumerable kleChanges) - { - var keys = kleChanges.Select(x => x.TaskKey).ToList(); - var taskUsages = _taskUsageRepository - .GetWithReferencePreload(t => t.TaskRef) - .Where(t => keys.Contains(t.TaskRef.TaskKey)) - .ToList(); - - _taskUsageRepository.RemoveRange(taskUsages); - } - private void RemoveTaskRef(IEnumerable kleChanges) { var removedTaskKeys = kleChanges diff --git a/Core.DomainServices/SSO/StsBrugerInfoService.cs b/Core.DomainServices/SSO/StsBrugerInfoService.cs index 16146f3b29..63f4fccfcd 100644 --- a/Core.DomainServices/SSO/StsBrugerInfoService.cs +++ b/Core.DomainServices/SSO/StsBrugerInfoService.cs @@ -78,7 +78,7 @@ public Maybe GetStsBrugerInfo(Guid uuid, string cvrNumber) var stdOutput = laesResponseResult.LaesResponse1?.LaesOutput?.StandardRetur; var returnCode = stdOutput?.StatusKode ?? "unknown"; var errorCode = stdOutput?.FejlbeskedTekst ?? string.Empty; - var stsError = stdOutput?.StatusKode.ParseStsError() ?? Maybe.None; + var stsError = stdOutput?.StatusKode.ParseStsErrorFromStandardResultCode() ?? Maybe.None; if (stsError.Select(error => error == StsError.NotFound).GetValueOrDefault()) return $"Requested user '{uuid}' from cvr '{cvrNumber}' was not found. STS Bruger endpoint returned '{returnCode}:{errorCode}'"; @@ -179,7 +179,7 @@ private Result, string> GetStsAdresseEmailFromUuid(string em var stdOutput = laesResponse.LaesResponse1?.LaesOutput?.StandardRetur; var returnCode = stdOutput?.StatusKode ?? "unknown"; var errorCode = stdOutput?.FejlbeskedTekst ?? string.Empty; - var stsError = stdOutput?.StatusKode.ParseStsError() ?? Maybe.None; + var stsError = stdOutput?.StatusKode.ParseStsErrorFromStandardResultCode() ?? Maybe.None; if (stsError.Select(error => error == StsError.NotFound).GetValueOrDefault()) return $"Requested email address '{emailAdresseUuid}' from cvr '{cvrNumber}' was not found. STS Adresse endpoint returned '{returnCode}:{errorCode}'"; @@ -237,7 +237,7 @@ private Result GetStsPersonFromUuid(string personUuid, st var returnCode = stdOutput?.StatusKode ?? "unknown"; var errorCode = stdOutput?.FejlbeskedTekst ?? string.Empty; - var stsError = stdOutput?.StatusKode.ParseStsError() ?? Maybe.None; + var stsError = stdOutput?.StatusKode.ParseStsErrorFromStandardResultCode() ?? Maybe.None; if (stsError.Select(error => error == StsError.NotFound).GetValueOrDefault()) return $"Requested person '{personUuid}' from cvr '{cvrNumber}' was not found. STS Person endpoint returned '{returnCode}:{errorCode}'"; diff --git a/DeploymentScripts/DbMigrations.ps1 b/DeploymentScripts/DbMigrations.ps1 index 659668c65a..bba5c2ffdc 100644 --- a/DeploymentScripts/DbMigrations.ps1 +++ b/DeploymentScripts/DbMigrations.ps1 @@ -8,14 +8,15 @@ Function Run-DB-Migrations([bool]$newDb = $false, [string]$migrationsFolder, [st Write-Host "Disabling seed for new database" $Env:SeedNewDb="no" } - + & "$migrationsFolder\ef6.exe" ` database update ` --assembly "$migrationsFolder\Infrastructure.DataAccess.dll" ` --connection-string "$connectionString" ` --connection-provider "System.Data.SqlClient" ` - --verbose ` --project-dir "$migrationsFolder" + + # NOTE: add the --verbose flag to get full statement output (for debugging) if($LASTEXITCODE -ne 0) { Throw "FAILED TO MIGRATE DB" } } \ No newline at end of file diff --git a/Infrastructure.DataAccess/Infrastructure.DataAccess.csproj b/Infrastructure.DataAccess/Infrastructure.DataAccess.csproj index 612fe68770..a7d561e070 100644 --- a/Infrastructure.DataAccess/Infrastructure.DataAccess.csproj +++ b/Infrastructure.DataAccess/Infrastructure.DataAccess.csproj @@ -95,6 +95,7 @@ + @@ -134,7 +135,6 @@ - @@ -939,8 +939,26 @@ 202209290951403_Add_SystemActive_To_ItSystemUsageOverview.cs + + + 202210050759373_Remove_TaskUsage.cs + + + + 202210051041189_RemovedEmailBeforeDeletion.cs + + + + 202210060603461_Add_Sts_Org_Import_Tables.cs + + + + 202210271249212_Removed_Delegated_SystemUsages.cs + + + @@ -1565,6 +1583,18 @@ 202209290951403_Add_SystemActive_To_ItSystemUsageOverview.cs + + 202210050759373_Remove_TaskUsage.cs + + + 202210051041189_RemovedEmailBeforeDeletion.cs + + + 202210060603461_Add_Sts_Org_Import_Tables.cs + + + 202210271249212_Removed_Delegated_SystemUsages.cs + @@ -1581,7 +1611,9 @@ - + + + @@ -1651,6 +1683,7 @@ + diff --git a/Infrastructure.DataAccess/KitosContext.cs b/Infrastructure.DataAccess/KitosContext.cs index 3b3d6a5999..88cd7ff359 100644 --- a/Infrastructure.DataAccess/KitosContext.cs +++ b/Infrastructure.DataAccess/KitosContext.cs @@ -80,7 +80,6 @@ public KitosContext(string nameOrConnectionString) public DbSet SensitiveDataTypes { get; set; } public DbSet TerminationDeadlineTypes { get; set; } public DbSet TaskRefs { get; set; } - public DbSet TaskUsages { get; set; } public DbSet Texts { get; set; } public DbSet Users { get; set; } public DbSet ArchivePeriods { get; set; } @@ -159,6 +158,7 @@ public KitosContext(string nameOrConnectionString) public DbSet ItContractOverviewReadModelItSystemUsages { get; set; } public DbSet ItContractOverviewRoleAssignmentReadModels { get; set; } public DbSet ItContractOverviewReadModelSystemRelations { get; set; } + public DbSet StsOrganizationConnections { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { @@ -204,7 +204,6 @@ protected override void OnModelCreating(DbModelBuilder modelBuilder) modelBuilder.Configurations.Add(new PurchaseFormTypeMap()); modelBuilder.Configurations.Add(new SensitiveDataTypeMap()); modelBuilder.Configurations.Add(new TaskRefMap()); - modelBuilder.Configurations.Add(new TaskUsageMap()); modelBuilder.Configurations.Add(new TextMap()); modelBuilder.Configurations.Add(new TerminationDeadlineTypeMap()); modelBuilder.Configurations.Add(new UserMap()); @@ -256,6 +255,7 @@ protected override void OnModelCreating(DbModelBuilder modelBuilder) modelBuilder.Configurations.Add(new ItContractOverviewReadModelItSystemUsageMap()); modelBuilder.Configurations.Add(new ItContractOverviewRoleAssignmentReadModelMap()); modelBuilder.Configurations.Add(new ItContractOverviewReadModelSystemRelationMap()); + modelBuilder.Configurations.Add(new StsOrganizationConnectionMap()); } } } diff --git a/Infrastructure.DataAccess/Mapping/OrganizationUnitMap.cs b/Infrastructure.DataAccess/Mapping/OrganizationUnitMap.cs index d1a7f814e7..03abbf57c0 100644 --- a/Infrastructure.DataAccess/Mapping/OrganizationUnitMap.cs +++ b/Infrastructure.DataAccess/Mapping/OrganizationUnitMap.cs @@ -1,4 +1,3 @@ -using Core.DomainModel; using Core.DomainModel.Organization; namespace Infrastructure.DataAccess.Mapping @@ -9,7 +8,7 @@ public OrganizationUnitMap() { // Properties this.Property(x => x.OrganizationId).HasUniqueIndexAnnotation("UX_LocalId", 0); - this.Property(x => x.LocalId).HasMaxLength(100).HasUniqueIndexAnnotation("UX_LocalId", 1); + this.Property(x => x.LocalId).HasMaxLength(OrganizationUnit.MaxNameLength).HasUniqueIndexAnnotation("UX_LocalId", 1); // Table & Column Mappings this.ToTable("OrganizationUnit"); @@ -33,6 +32,16 @@ public OrganizationUnitMap() Property(x => x.Uuid) .IsRequired() .HasUniqueIndexAnnotation("UX_OrganizationUnit_UUID", 0); + + + Property(x => x.ExternalOriginUuid) + .IsOptional() + //Non-unique index since it's an external origin uuid determined by an external system + .HasIndexAnnotation("IX_OrganizationUnit_UUID"); + + Property(x => x.Origin) + .IsRequired() + .HasIndexAnnotation("IX_OrganizationUnit_Origin"); } } } diff --git a/Infrastructure.DataAccess/Mapping/StsOrganizationConnectionMap.cs b/Infrastructure.DataAccess/Mapping/StsOrganizationConnectionMap.cs new file mode 100644 index 0000000000..fab565d855 --- /dev/null +++ b/Infrastructure.DataAccess/Mapping/StsOrganizationConnectionMap.cs @@ -0,0 +1,17 @@ +using Core.DomainModel.Organization; + +namespace Infrastructure.DataAccess.Mapping +{ + public class StsOrganizationConnectionMap : EntityMap + { + public StsOrganizationConnectionMap() + { + HasRequired(x => x.Organization) + .WithOptional(x => x.StsOrganizationConnection); + + Property(x => x.Connected) + .IsRequired() + .HasIndexAnnotation("IX_Connected"); + } + } +} diff --git a/Infrastructure.DataAccess/Mapping/TaskUsageMap.cs b/Infrastructure.DataAccess/Mapping/TaskUsageMap.cs deleted file mode 100644 index 7cbb46db2b..0000000000 --- a/Infrastructure.DataAccess/Mapping/TaskUsageMap.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Core.DomainModel; -using Core.DomainModel.Organization; - -namespace Infrastructure.DataAccess.Mapping -{ - public class TaskUsageMap : EntityMap - { - public TaskUsageMap() - { - // Properties - // Table & Column Mappings - this.ToTable("TaskUsage"); - - // Relationships - this.HasRequired(t => t.OrgUnit) - .WithMany(o => o.TaskUsages) - .HasForeignKey(t => t.OrgUnitId) - .WillCascadeOnDelete(false); - - this.HasRequired(t => t.TaskRef) - .WithMany(r => r.Usages) - .HasForeignKey(t => t.TaskRefId); - - this.HasOptional(t => t.Parent) - .WithMany(d => d.Children) - .HasForeignKey(t => t.ParentId) - .WillCascadeOnDelete(false); - } - } -} diff --git a/Infrastructure.DataAccess/Migrations/202210050759373_Remove_TaskUsage.Designer.cs b/Infrastructure.DataAccess/Migrations/202210050759373_Remove_TaskUsage.Designer.cs new file mode 100644 index 0000000000..78f73ede54 --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/202210050759373_Remove_TaskUsage.Designer.cs @@ -0,0 +1,29 @@ +// +namespace Infrastructure.DataAccess.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.4.4")] + public sealed partial class Remove_TaskUsage : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(Remove_TaskUsage)); + + string IMigrationMetadata.Id + { + get { return "202210050759373_Remove_TaskUsage"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/Infrastructure.DataAccess/Migrations/202210050759373_Remove_TaskUsage.cs b/Infrastructure.DataAccess/Migrations/202210050759373_Remove_TaskUsage.cs new file mode 100644 index 0000000000..e831060a97 --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/202210050759373_Remove_TaskUsage.cs @@ -0,0 +1,66 @@ +namespace Infrastructure.DataAccess.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class Remove_TaskUsage : DbMigration + { + public override void Up() + { + DropForeignKey("dbo.TaskUsage", "LastChangedByUserId", "dbo.User"); + DropForeignKey("dbo.TaskUsage", "ObjectOwnerId", "dbo.User"); + DropForeignKey("dbo.TaskUsage", "OrgUnitId", "dbo.OrganizationUnit"); + DropForeignKey("dbo.TaskUsage", "ParentId", "dbo.TaskUsage"); + DropForeignKey("dbo.TaskUsage", "TaskRefId", "dbo.TaskRef"); + DropIndex("dbo.TaskUsage", new[] { "TaskRefId" }); + DropIndex("dbo.TaskUsage", new[] { "OrgUnitId" }); + DropIndex("dbo.TaskUsage", new[] { "ParentId" }); + DropIndex("dbo.TaskUsage", new[] { "ObjectOwnerId" }); + DropIndex("dbo.TaskUsage", new[] { "LastChangedByUserId" }); + DropColumn("dbo.Config", "ShowTabOverview"); + DropColumn("dbo.Config", "ShowColumnTechnology"); + DropColumn("dbo.Config", "ShowColumnUsage"); + DropTable("dbo.TaskUsage"); + + //Fix old preferences + Sql(@" UPDATE dbo.[User] + SET DefaultUserStartPreference = 'organization.structure' + WHERE DefaultUserStartPreference = 'organization.overview';"); + } + + public override void Down() + { + CreateTable( + "dbo.TaskUsage", + c => new + { + Id = c.Int(nullable: false, identity: true), + TaskRefId = c.Int(nullable: false), + OrgUnitId = c.Int(nullable: false), + ParentId = c.Int(), + Starred = c.Boolean(nullable: false), + TechnologyStatus = c.Int(nullable: false), + UsageStatus = c.Int(nullable: false), + Comment = c.String(), + ObjectOwnerId = c.Int(nullable: false), + LastChanged = c.DateTime(nullable: false, precision: 7, storeType: "datetime2"), + LastChangedByUserId = c.Int(nullable: false), + }) + .PrimaryKey(t => t.Id); + + AddColumn("dbo.Config", "ShowColumnUsage", c => c.Boolean(nullable: false)); + AddColumn("dbo.Config", "ShowColumnTechnology", c => c.Boolean(nullable: false)); + AddColumn("dbo.Config", "ShowTabOverview", c => c.Boolean(nullable: false)); + CreateIndex("dbo.TaskUsage", "LastChangedByUserId"); + CreateIndex("dbo.TaskUsage", "ObjectOwnerId"); + CreateIndex("dbo.TaskUsage", "ParentId"); + CreateIndex("dbo.TaskUsage", "OrgUnitId"); + CreateIndex("dbo.TaskUsage", "TaskRefId"); + AddForeignKey("dbo.TaskUsage", "TaskRefId", "dbo.TaskRef", "Id", cascadeDelete: true); + AddForeignKey("dbo.TaskUsage", "ParentId", "dbo.TaskUsage", "Id"); + AddForeignKey("dbo.TaskUsage", "OrgUnitId", "dbo.OrganizationUnit", "Id"); + AddForeignKey("dbo.TaskUsage", "ObjectOwnerId", "dbo.User", "Id"); + AddForeignKey("dbo.TaskUsage", "LastChangedByUserId", "dbo.User", "Id"); + } + } +} diff --git a/Infrastructure.DataAccess/Migrations/202210050759373_Remove_TaskUsage.resx b/Infrastructure.DataAccess/Migrations/202210050759373_Remove_TaskUsage.resx new file mode 100644 index 0000000000..fd327af1d5 --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/202210050759373_Remove_TaskUsage.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/Infrastructure.DataAccess/Migrations/202210051041189_RemovedEmailBeforeDeletion.cs b/Infrastructure.DataAccess/Migrations/202210051041189_RemovedEmailBeforeDeletion.cs new file mode 100644 index 0000000000..ec4beb4175 --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/202210051041189_RemovedEmailBeforeDeletion.cs @@ -0,0 +1,27 @@ +using Infrastructure.DataAccess.Tools; + +namespace Infrastructure.DataAccess.Migrations +{ + using System.Data.Entity.Migrations; + + public partial class RemovedEmailBeforeDeletion : DbMigration + { + public override void Up() + { + DropColumn("dbo.User", "EmailBeforeDeletion"); + Sql(@" + UPDATE [User] + SET Name = 'Slettet bruger', + LastName = '' + WHERE Deleted = 1;" + ); + + SqlResource(SqlMigrationScriptRepository.GetResourceName("Migrate_Users_Not_Associated_With_Any_Org.sql")); + } + + public override void Down() + { + AddColumn("dbo.User", "EmailBeforeDeletion", c => c.String()); + } + } +} diff --git a/Infrastructure.DataAccess/Migrations/202210051041189_RemovedEmailBeforeDeletion.designer.cs b/Infrastructure.DataAccess/Migrations/202210051041189_RemovedEmailBeforeDeletion.designer.cs new file mode 100644 index 0000000000..3b68cb14a3 --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/202210051041189_RemovedEmailBeforeDeletion.designer.cs @@ -0,0 +1,29 @@ +// +namespace Infrastructure.DataAccess.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.4.4")] + public sealed partial class RemovedEmailBeforeDeletion : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(RemovedEmailBeforeDeletion)); + + string IMigrationMetadata.Id + { + get { return "202210051041189_RemovedEmailBeforeDeletion"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/Infrastructure.DataAccess/Migrations/202210051041189_RemovedEmailBeforeDeletion.resx b/Infrastructure.DataAccess/Migrations/202210051041189_RemovedEmailBeforeDeletion.resx new file mode 100644 index 0000000000..99cd152d85 --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/202210051041189_RemovedEmailBeforeDeletion.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + H4sIAAAAAAAEAOy923LkOLIg+L5m+w9l9bg2m9XdZ7rnzLHTO6ZUKis1nZXSkZTd208yVgQkcTNEqkiGqnR+bR72k/YXlpe4gATgFxAXMorWZl2ZGX6Hw90BOIH/73/9v//+P3573nz3KooyzbO/fv/Hd3/4/juRrfJ1mj3+9ftt9fB//uv3/+P/+t//t3+/WD//9t3f93D/0sDVmFn51++fqurl3374oVw9ieekfPecroq8zB+qd6v8+Ydknf/wpz/84b//8Mc//iBqEt/XtL777t9vtlmVPov2L/Vfz/NsJV6qbbL5KV+LTbn79/qX25bqd1+SZ1G+JCvx1+8vs4ciKatiu6q2hXj3IamSs9VKlOX3351t0qQW6FZsHr7/LsmyvEqqWtx/+1qK26rIs8fbl/ofks3d24uo4R6STSl2avzbEZyq0R/+1Gj0wxFxT2q1Lav8mUnwj/+yM9EPQ3QrQ39/MGFtxIva2NVbo3VryL9+f7Z+TVe16kNW/3a+KRqwv35/nje2rX9Ls3ZI3nUou//8l++Gv/+Xg2/84V37vxpku2lG6K+Z2FZFUkNcb3/epKu/ibe7/JvI/pptNxtZzFrQ+rfeP9T/dF3kL6Ko3m7Ew074y/X33/3Qx/thiHhAk3A6xS6z6l/+9P13X2rmyc8bcfACyQi3Va3cjyITRVKJ9XVSVaLIGhqitaPCfcDrRmxaOgpPGK0B3SM0HvyupSPWx8HDKDRzZb3d1DO3R0f+Z5jAZXm2qtLXgxjv83wjkkxjLZhO8/8HEaqi5fxT8ttnkT1WT3/9vv7j9999TH8T6/2/7Kh+zdI68tRI9exGmZxtkuK5nv0HTs2f79Jn3ExV/mKFVw+/Dd77fP3m3Rq325//H7GqvPP5n/nPR7/2N7ZtlFFmhPzPTJe8as1z9Ws9qfFYAJP6XGef86ckexRr1RXsab1/q9MUX7gvyWv62MYbrQ0bp/3+u31IKp/Sl54t72Woj0X+fJNvDrjSj/e3+bZoMsZdboK4S4pHUdHlU1SHxNQAK9IqMCahVUCu7JI3QVL3wBR5pV9NksogXBlvxCoVL2k9NCUkYw9MkVH61SSjDKKT8d9/OGYwQlHSuaJtYdJgL8UJGlnNqYwZvzpyYyMqFJynFIt5oddF2N1PKHPY3c9KH2G3ZUAIvXo4Q8AwAPsJwS0zMAwPISCpsXBMDnWdGRlBrkFY4pr9kuOPf/gDqSy1CBmOOMOMrp/yTHzZPv/c+I3n4vui9q9NeFteJ2X5a164WFwwOd8mGxcLJwvfaWJLabOm/CA2op4mI1DHrvE/iIekjjVNYLqtkqK6LsSDKES28r/y/5SUZy/pftNvoAaKWkv7TXzKN2tRGEhwBzJffRPrq63V5sDHeq6J9Vkd7Z5fqnJcGXVZ/rjJf042Z+vnNBur1ddtevCRH9s//86Lumajuf6nxmNqt74Rj2lZZ9gG8CZ9fDIsshCk+2E9RYFXikISErdOvKzO86wms6oA9QZAijq63xXxtUB8cW/fynoSgcJKIBpRh79qBFVA/FTfLWmw7tZDKLWrAYy9VZM+iPO31Ubc1aP0rfaxi1fjtoIeVjE3AKbYHYLlDgC2bGiJGhYMw9/05h6zZ3NVPCZZ+p9YVFHAFPPqIRTLGsDYRpXI1JkcihhaUFD8PhSowgCUq8a+Ar0RpahuxC9bURq00EEqShiBFB3MkFwVbst8t2JKhV70GqJLg926SpFa97sisBZIJyt5RYzkMNZi+ccP1zdY5l0W01DtZ3MQMdx+rh3Fzb6gz93F0zz6oVUZWNkIFiBsZCVZ8inYbRFa6b5HpSvcYbC13KG53v2ksVUqHAaapaaWZ1k1Bys9O0S6gg0UW7MWiauS9bS0WjJyVTLONwcJ3WUuX9K4zy0cZGv7T342guWKfmzCbvb7tj9L/pMXh022drb9U5Rf8q/ZWqzStVhfvXQOinRqFUlWPojiLr/MSrGqXevuKS3W5/k2q40kxjNo5K3XAi91XEhrXe+Z+2cD9BvxnBTfvO/KXrVNpHXw6HQMxPVmv+vMtNFlefZYCPFcz6Sm+XSzXR9LuuO4XRaF2IjXJKtoA6fSPKvUQpFLI5Ap3ydlWn7Mi717My16GP8aWhSvyWZgzqT4Kc+qp/2vNIMqRAPZ4rI8cD7Pn196JybW01olGWpqnthW/Fkdx1dpkxP3O8fY9vS9uYQo9RvWEAawhQ2icXdzhjOSWS/eq/iUslFBY1SPKi63Lh7map7GQ2ySvn0kjrYDTBtdpURto2wPnaytXFww1ZVRufpe/NYUsE0Q3yVt9vjqKJC0VhE5imuwubrvS8VDlbjr2L7LG762M5xKlWQjGjGO3YgU/bQOA3JZbm2N2tUK0PMGMGdv+Fju9Tg7/mIr2MOlaSihsFSU8dg67ovApo7ixr8e8v11UgwaSHmYjEYCLTr7mLC/QmQHfxWfNswDNNZQD3H5XfjJuvumkbvZt0fciXux2/IhbfxpcTl9I3oC3AG/ObaE8UZaQiQN8QGeM7ZHJPag2jf8WB8scJt+BucR5ANkdbeMN3QaAqQhVPA4Q6kic4e06+z5WiaP/KK0j0vTVkJhKSrj2Rw5fMmr9CFd7Ve+hg4YGQpY0Q6bY4hoii9zcEd1GRzX6axDiCOa9Mfl6MHn0YPtvm6cIwtHn03nFSS7o53NgwMH+I73dvvysklFsWd5mz5mAb5gaE99Os4tx9HN7n1qNn3egS1wWTpS3FphaZ9o2KLHPVhweB64H0imCE0uqsN4cypz2yQi8fhmT+F6k2T/sU2K6ugHNiSaExVb/Mt6FNr989FnGnu/vhPPL811FUyzHNBrFK5F6zrgKSnFx7x45qK261euqEVts1WyqbMfX8n+ASP5U51tV/Q0Qz38NoSG2R652aFeZY+5dJWIbQRpjlBf81WDcZdzDXDx20vaSWMTgu5E8ZxmsptzMRvG9VJ4k2Zc7+xmT7NvnK2ZqB3ST3XlmLaxamQf5jbLhjfCNP50Kx6bSECb5e/fLrL1aCpXL2K/vfC8zXZ/fi8etxl3fK6Tt4btx0L8UteI7FjcYbc1OzuMpytRr0e2Vlf8nO457KFp4WLT/qchh57Joujac1kES1lNM1C5C+ojvd2HQXt19Z33PZh79RC714aPAas9+SgGdy9oqB6wO6I1smlfBAWmjeGovZDzp3SzrqsATBt1j135EeoGsNwpH1ZVmJQqvFbeIRhkZwWWbWGptCPL38LCstcgJLkbOLbMxxoPFVkG1Ut8hAAFlsBGNEuoXS0hG2IA/Sh9NI4bCCTucMMACAgp5aAhoCNxscqz/PmtXlWK5FmvTQ9kx3lfAOW901wYUolTCDj7E9zMSqEOjaLQEBJRSAH387Gu5BVgWwEEB7ma/7YBiZmhTUAPAUk9qg1AWjvpPyKVANo4r5/dAJj6GSkAO+ZzWNTghrYFAwho8rFtCa+p+BU5rz6yUxCM59RUHKCOQhD5H/oWpmsRmaUfMByD4pAuW29pa/j8uAcDTAEYUvMhMgjOt/NxoQ0p0gLgWujATCpoYdny91f7ehX6MJAWIKSqCAzO10XZwkYngA5FPxtUSHBqaMDZ80Ta/kUV6cHqNZBAQNFlOH4zENQPI3HR9r/ofodEHdHfYj67wSUHUA26GDFg7cxoDvt5hpfTqP07egj0lhvr/pyX3aYwPA5HOK3R9z9DFj7AcM2p2T3XiquBA8InDq3YnIDCtb9lD43ceAL0zEjWR3tk5JFy0xNj2IUd2yijJRu1e0Yn0b3aUqPvvDma3aYJx8h61MVvfZncXCKhk1R/06pOJf0cRkDV624RePtLzeKcTQA7xdRjDas5rh9Lu4mto7X0wtm3pP3xz15a0i7Lz/kq2Wzezl6TtEUcfZJfXtXjVc+rvHgbS+uDKFdFujs19t4LdZE1oo1uhqpXZHnRDviYYO31Ys3f831G2mQB315OwlBvBKehOb/RXMfWdLc5AkvTadzzE+ARjcOigaQKclBDzqT9U3ZmDpVOrAfdAEsC9RkxG1+SbD82at7lDokdXgtrTqseEnbDe8hMKm1LeebUmrbZht5a9HeprS8O+7ROM8PqmpH8tzANIze96Ymq12DmU5RSUIwaDSAxdYbgfr56HzAF6x8MFtPIf80zYGiodsxQmAbjKpxB5KZooEEy6qHAYtqoCOyt25w5WwYIRl16cJgefWD+Z45y7qAoMcQwatEHxNQYQI+qO3vF44iys/e3per08dXGuI8WgnwE2G4NdY4AfgVI/VwS5rZzKWgPzAmfVqvzZLPBdtzccNu/SnBb+9u2f+nj4LduuzXcV277ST6WzlmxekpfhcXHWbciK9Pmm9j2nh8+vu3nvzuJP2yPu3TddsPx33f79yQ6zWQsvc/GHbMmUzCN1PTSNv9wfCeX+A7SjqXl55A77Ga+ad2V5lWirCwp7P37vGkdyZt7pZgEmlq1vZOq5yTSv8LoXVLZXG+Ll7z0H63T8v22TDNRlvte8Z7YzRQ73IiDxazs213+IS3qojcv3r4W0DtvjlKNwtLReQjM9qXml2x3RrEzlkRih3GRrYq33laL7VGCSvu6FNt1076c1l7o4LtLlUP32lm7lM437sl/zh8zB3LfidVT1vh4HZuaps+mcviQr7bNTm7X4YN6kBvHpQgSYB9MFBJ/W1cekLGpS4ckYgwJIoN3/kVafjsry3oWPYtB7mAMxoFKQ8RmKOq5B0hyU//0Wbw2HbdI+VAD2o+omzCNyOB9ROvFomhk8F/kfbi+PLP1mAa3cY726xierzSosactIoN3/klW/trm1MbkY8dh3T6fajNts/b5Xpm/5ZsGeVnJF8u3Whz/kbjW2O9FMxcOS/cC/2ylv1oC36bsdjwVDPWZSi2gppsXgmZ/7t7hX9dzKV8bjvVlkPvBpqV0pG8GU3sAAVj2F+39ZS99KPTt1AAgbSisW6w1a2i6Mn0sRCEZmKZUD8NWMVOzqZ7j2/CzcQMQUYE3i0/Hj4eV3I+yPd4sSb80VH8jJfdbf/jh3c7IEqxpxA4gyHgd4bx9SC6zw74lh2ERXVxcMV/tUzqqyhHUpMD+b4jYBzBbYY97eAyxZSRMgSMsURUJwc8RfZ8t8tE4CIpoNP58/qckzZCWeZlhH9ykhgyFaNADdf/du8zK+Om7AQiR3Os9+ANWxm/ITVCY7EG+JJc4cj4mJ6MZ32+n4Lq96rxvXsPXnVoQZKScfONpbvYYMhuimMXvQ6JaDMCdfsC568owfr6p/m70nHGfbspnou0OHSXlabFMdtcAI6bXYbDvTh8e9nLVgut3BZSjklUtf5eU3+qZpR+e3Y/9lWj/S1UthPp1qh6M61Z7Ya9eqqutPknrOe0RMME7OKL4O2D+Z7U1Muv6PPs2TeTiPFNXJ+ML4braIkyBPaDJ77vfEWffAVk8BVCjsQxu1+mHGFvfFuj9Y2yDJjAk5ZNsTBv6F5vDLUCLjr93AyJLux/UdxfiJGT5KPP3+FHmlE4xHH9yOThRgL+2xIDVL/lQDOffWA44mj6vNIOhSnj8qNLRKRK4bjaeOY1Jc93hzqgk15FYUhzUlFslhaHhhBlnLjLDmyDcsJulv2zFbgQDvEfT8+TR3dEvL0X+Oj6D/f5OxAcFuJ9zZEMcBs+cvWTHHUdKbjSBIsoEy4s7fnBWVIEQ8bGMSM4m/Y1wRjKREXt/WfKJ/ZLJzWc210955n9hdrYuROm/CfCidiP//W7a722Y0f/8FXqk7I8uRvZj7XzpYwZzcjS8bet7PX/TB+lBnS6yDX4KvXBsTjeTVVWHwpL/HUz5QTwkdfTpBz5WQ9/vr/oY9F7VbrgvBhirKn5DGGlVpbSPUZV6LzZ59ljPHoom9x102TzIpYp//NUoswRi0Sr0kD5qxet+Mh5na35WBNTB2DQzHWak/v55mfwAXLp+3gil1EMAqLsnQRw8RW4aGi6u1VPkowbVYVMe3wi2ujtTOW+inEMTWL3wbXihm2AGw8PgTENUdZ6rfzxbv6bGh817BjfhGaa4Hhye6wYcm0kvNVEQdetjAFrJgLg+PWh+W6DxzQf+ixT44xowDutFilFz9UgYfdGI+2IIcOfsSJEP18yYZD7eQ2MWWg+jkdoAyBebVCFhPXWYtDooW1H1/WpWbXWkVkH2pKDjjjIBpTy36IWEC/NR4tP2CXsswG1CGBIOzeM3CQ+3mtzV0eNbnaQvXkVmCFh62PvuQ7tkI0umbYe0wVdG0ooIe4z1VvnHU02vd6lL2XUpfso3a4MjIPLK+CY/tyTBNZ2RDvutLGTjuUfcsO9sgoHnw8gG7eahEbzOap8jMY0VCKi+UAZCs/uVzR2zvWnRNbwSFFAhQQ004Ox+2qrsX5rU7lqbPiTRQ78ZdaPAq91tFCT+ky8/e1zKDamTvzMb4rE+NlOQY7+DA1TJ1ntyxlbovg8Nmp+VH+EwZtXg/PWyrs22G3HeHpHtSBm6J3WgxlmDQ6tdlDhKoL5Qo1IQIN4ViqrCvgTSrlFm/4flTBPgddjYtrySLEATy3UhXtN8WwbpWO1esWQaY39dmcXFfx/S0klbqMcLBG/EKn9+Ftm6dTjOdYIN9nmLW3kfOEeH86GPQ0P2IPs7FXZ5med5IZpIxr1t5vd3risdaro4+zR9d6M5HiVLKMVFRMgepE5OCQAQVYbiSnv+lG7WdQyFJdW9ktz7ybw5OnhD2dPdDcRrGzg3Nri5rOGwoX3x21P6s2k34cBTi6DRQwNnVkQH7PfSA9p9B4yrDgJ0Px638+E7AkjXA4S5GYB5gGEWdsxVAOA76+T4YZTN8oV12qf68Ff6hA/0R3ybz/r+GPz0GP/q2OYJXOJZDOOSGfgMRrmLxmr13M+pNitomcKyih6x+FievFy+rlw+kRlfVPXqe7CwgiGVJIaAuy6weuwMRZYJBpY9wNeWzMWauadWt6SzynTK8oSV7hTsJdWBG78r49vrjI8RbZG5eMChHJPSXVptoCTv6IuZoTMG2GD/evPZOw/jrt7v/N6B90UTLZpHQ27ES14YNkWOUJeZ4iH33a+Hv18V6WPaWwNboCth24aGu6Z17ik/vAfGQuSc8wN7avzOWOyoH9vnAwCh438nOuwXwn72KY0lhUPZqZcEjrwkF94IcKAPrbBWZzRYXRPAlTKVguO6zlZ5GoptEJCgirNPusEwyypr/yN5d3QbOIMsBS/A6+/JZiuuHs6fxOqbWId4v+M82UqvrPXz/+437v0lRZEXu+9UxHktCKtyOvhJUy9dPXyu/7+sWmHaycuvppBqSKlkplERKevuEVUV70ShKw0BO6h5okO5N/2s2oJNwlAh8umM2+QGmY4OmCbCS8T0sdZD4gLxIDzilNCHCPupxbPP4Wi7iUkjbDOkw7RLH93OJgMazkoq6Rl6J6XUgd4SEJYSasYl1PFjU1bphKCBJROGG6dUchv7rEokQ/y07KC3i3hSE/0S4ighLkRQ2xkb4PMnF/dUSUMOHj54aqnWMCeF2Obteu9D4Kpdf+lWX7rVf18NHsf3AvtPIpDeYtj/QUpmxvcYFFjsTQYVgX0ZGfsQz1O9BR3aUWs11h08+a/mD3DrH+979Uf/AG7ws/aYbQjDb51ve7yBB0qG7eAmiWFI6PoWHTj7UOooEnLxDCb8vSqE7soZVTPX3fFHDkiDPAAIqhCiTV66o8fUKa8FAQX33C8/4pIiUGqscZ68ZtlNfLv1yg55WatwC3y74mP/5JhFV5b3AvL3V2OB79Ht86nuAbrhb8pMVwBGfP7lqmAwyajLy26z154TmLmMQEbB/WesPSdDttL8bBTWWcfD0R9t4/3yecryecqktzKWz1OMpGaSWel5Af80xQylDbaBPkk5sAJyA/opihbI8WcorDrGtKmgFDpjT1d2q/zRhyw7OieYzmjfd4yl8/sLTVhl7WyPC1j9Q1tibpvGx9wKYWwbh66Q8LbvtbcZdfvLCE8ZmKCbYXum+J6YBpKijbO1x4Gy/QKkR+IEw/ayCllWIcsqZBqpnphj5IiEpBcYVI3FCLzzpNLjZ8onJiBEfK+fyludyEGPQMCHh+SMt7sOx/61yB2BJdP5DG1dOeI5HzQjWVsNTMkuWqZIKY6a/bGeoSp9Fc004zbkdJjNJYk8PKv7YpuYU4fM4Q33y9qXmxDBKxv3N3+pN671fzFeGWZ5XyP84g7zOrNhCjNfeGb1gTNNxj2oWdAOApV2BzZO5KuX6mqrb/HW89sjYOJ3cEQldsB+Dhj3LMHizQhk1MB/wbbnZCjVND8bhR3VBqMPsLDIJhyN+HpQsyoGeIf3S5KDnUlG4HJJq/fIO9u5eJO8obSUm1CCbTY4nLTqj9rAcXQBUpJJlvvLf/VTgDnsAF/2MdyWbUqUVEOaAQR/Qsqyotu9Ot4YgfqE1PGh8mESwWAJz0gNEPjqbMTjsRMfKAQVAxpQgaHRYoBP/ABo3IR5scqz/PmtDlYiMdTjPZB7KPvDkMqwIeD+n1Zs2ZCfV9RD4wPlv6ZUH4LDn8UbwuF6eO26dvREHq7EmNvL2yq1KQfhRaGDOtm04Mbqagd18ojsglrf+n72w/vRH/OC8TKyhAiNBg0DuhIOQvP0EGNDe/dmYjsxoQGS4dAaoAfMvwq+LXopfrUDBdyqhcC9qgNzti5r9XezMGtJLSszaG1gUzYPJ0wuXTurFJvtjxG/f+2Xotxl2O9u5TNcFvheS0DRBVx8+CtLO7bkutQATtAsbGUq5xWwNFUACaoEK05HvX9M0GNMfcrwLtyhiD5kdBv63fTyMpDZYrYvwPqL1CXjQtuH7d0618lb8+hkU04zr5nPRqGjJ7rYIfQv27RMu2k36iT4RezvzR5Fpno63rxhR+Jstcq39chlj/XMKKBmA0e3hmzXaXVb+9K27BVNd0Xy8JCuPnfVL1eJhmhTTnC7A4LcSfP7q6KGk5ywsaeimDb2hpDq7c8wOPtwO2Mro6KYlBlCIsoo4H7KwT5T+KZxGBTRJ8AN4/1dXsPt4iYgRHxXZZ9xreFs8xvRg3LwbX3K7HBH40BuqbEC7Gq46Xdbuub8tJHrN05Z50k2a3cIzy54+9trpukx2Jj2dSxG3oDQArN0seyZb/cqyZp04JgKzW9E2VtQL5sORx60GcGYBOM3IBS6rV2dZcua2pIsAV6fkvJGJOvuysqxX17VxP5RpJVwQ235IM/2a4XlgzwdgaWSIqaKJhHxCiktBp5C9GjeK5GGLbUQGcDSdPL46d7oYoTWgNCrW+y+XZc/R9gd3+0erbP4jr3FfGekGTfFy1Kp+V6Lo9uJZ5cJQ76jlpljP/Zy9mJhHQPa+3BNrxR2vyMvE+6AuA00pF0p614atP+333Jj0aDFtbWEukMxWX0IidhfAR8VS87z7CF9ZAWODuUES394Gt8+5b/uR6LWdzu+eu0o7o963dHsP1PrRspO7+tCPKS/udXbDc1awu1LcwN7Z8bmHx1cTNWRbEri5TAvVg3dhRu4ajbBKDWlEdB1ZbxjZKiF1V9Nknrt/9nzMDT9aH42iunsDvAmLDRRoU4ljTS8vHTEPMH0FOw+JjfxrJljQRhdP+WZ+LJ9/ll6K8bbN4q1O/l/7gls07XPIlNKGs5zxHHqo6kCAtUFOBDeQ+KQ+Jnzhx4IET9YN+n9IIzrF3B9KHARNwAdtebp18c34jEtq65prtmvb5MFK/H8+OH65l2D+o5AeUlM9onpT34eR3P5VUTnmJ3LjaX1U+0hhz3LJtic1W71mIk1+MW/mxTU5x3gicMew7u02kCO4OZWg25N2/y5PCvPy1fvOu62cerlZCCGUjzKi5CKbn+OxfqyPHsshGjaGOuUsdps18d6pk1T/xTll/yyKMRGvCZZdbU78YOp3hVJVtbOeZdfZqVY1bH57ikt1udNh3ORilLl8DVbi1VaM6cxUIU+q7g9x93bwlevTTZ5fLJqW36flGn5MS/2+nqfgwdp2wbU12QzsGRS/FQn/qf9rzRjtne9H7dJwynRiRfU2w+8z/Pnl42odN7O9MX9zlxAPXp1tf3C5f0b1tngZLwljrpZar0hhpbYhPrSuJvDxdU+8cAiYNMm1pU4TSA0vwFhEKKHfRRJ/czflob2TQkrQtxzKLmqtHaMPhGeY8i4Vo7RIzD61SiW0d2v5fR8lpWd565vF93nDY2PNYqjPMFt19JfWWadMIDrTqIGSkaEoEXcMZGiEquG09n6NS2bL6ZsG2C15JZJH/uc4fwVXqW4OmHw/wHrupBae5cjjOUgXBvR+/EHf3COgGKK1yiej6foVL7Au3QgMFGtcIciWv7GSxQN4PAxiQFn9HlJbztlTAaVCC25c8mdS+5ccmeg3ClFHsL73RCw/mlsEMPLe94SR+hdbz0YqkTYvChxhjOiDIjnwh70yK8u9vvizZb7ayp+tdthki53aveZALpLgpzhqb2jHgb0lLN9tmhs2/Te9QJ0FHQ7OipDUl7rIwcx8XmRVukq2ehcgoyJbTM6efuqf0mvxe1jKoEg1WfTXr9J2Y2Ke7QgR317l7ttGm/895fu2TVsuF4noQZxuwND8fxS53dreXfoQWS+ruP8U1I2122rD47TUcPIWuRNo0mzL37b7JaLR24g0lAILfn1JsmaLg5buRv8/9gmRaVcR0gmcVnHszRx0RjRP8Y4tOyE6fTovUEWnuOxdy0E766d/+rhrCzzVXp8DeSwkhhXo3XFE7nd0NEeRZ9piKbKAcvuxsJkc/iHAGXf2Wq1fd42AX4tXXJ6npfV2CE80L162d156pZqcwXqeIoH4W7E8zbb/fm9eNxmNv15uwsa27Ugu4Q+oobJArvLJAvxy7Z2NnbyGqAHkblrobS+9VW6g/YfT+kR39IZj9RuxMhVqUTrn2KzyX91Ru7HOguOvG34w7Z/Z7G/Rs02zTdhMFtzd1Yl1CCueCeK5zRr7fJBJOtNmnErbA2FIJI3zdWv+apxAP6zynuh7Rqgy+qidkzqV2cIerBe0o7pmVXIUZrcqYgXv72k3bQjsTU/bGEoipE3jJTNznszId2LRnR8ZaPbioiHx5YhOcwPMNOxWIqPfKgZ3fCHeJtalqk4LEW9tyhDzBV8mrIDNJa+Q1yuymjvMcTc1HNMxWFpivYYg2oO15dcTYf4RGX7aDx9B7ijmiUBRoaY6OvUy8BuOQwj70zJDbajn/kyUg5yChOwYzpKbWJ+e9GiwHE98Qd3nvmZ7j0myySnbsg6uN3qSOy4uQtMaDdrQ5ltmKPyHcfL8kNaurl0dxoxyckSgRN/DKsLV1HHwddbhLCzfLu1fLs1nVbPiYQSR8tSTjAxLWld1zD9RZKvIqbPZYkmYLPRxsnCpHFRh/XQXe6Q2ESmtaM9Cc60Nu1nWE5r+VLykV238m3nu+kMUV/m8Ax7b483OoX/tnvvTq5WGV3vRvOKarGuVbjL/55s0nVtpGtRpLl78p/TB3H+tnJwBXVrBjf9yUGeUd1F68qp93BYWjVDo/4GE9nFMv/nm82TP+dJoKq95TY0qvethRAbJ/0e7TFvTQOUgozR3mrvt2WaibK06HXWkQjT2rBj3D7lUn7KN2t2l4GORFC7/+3zxWWoCwglns0/hLpNrIkChybHD/lq+9wrxwMxDtHh2ecY5t5M+zumJcxgzTW/m2vlIjUGDbCbe1wtP/KSUS2/DdKRCDJ2PbUdfZx3K7KmW/pVNAd/n8Wr2ASKn2fF6qlhuz0+LNjuNUj/3vxriUb/Nr3VMu5D8FiL3KTlt3pYm6V6U7zuyVKOox19agcIECTcp9m3u/xDWtRhNC8C9UT3eYZRc7cW7VqMe044+K35xb6HoTxetxv6QmZNN0Wg6d3t+2yut8VLXvo/gP2Ul71u3nYUj//Ifqb1RWTr8iprrwR+SGpTBjTdZbbKn9uRa78R6Z+IBpTjals95jHkMG5R73JDtzllap/TbLj28KDLCPnY8EN6NBLcm1qBUEO3CeVCVaKB6KRo1mLQY5tOndl0kx1w2BYyYtIMYkbn6g/GFroluvc5pR/YFkEp0CyDk2FbaMfmLim/1WtehlF2GGxTGPBoBjAhj3k6la4ypb2ejKbpS6bjsr8lgJIbZyLUNMbNA5gAdRogVNiP0pK+QdAND/niXwt0mjFc34uurpDp5lCR2SbBSdDMQqDj/Mp4ZAabv9wgo3GDhrs74hmFnpcuAj2rpaUA2uyqksLwASRzhXiRrZ3QCdrEE3hlRJqZtMWVuwnq+l0+6mxdXu373X58xO3x8fK4WOxAE2e7gRSCLLYv3MUjdWnvJfyobJZoA27B7sw1+guoPaE4/YKxZ72PHTPSnMY33NxNYfMelJepbGa3TGlKH53zDxt/n1M7xBYwaarTd5LdTfnhrquXiT5kskxvgFfbcAi2KTg4Ed11GHrvhog9t12fZJDmMXYM4jJhG3bLPeVrA7dlPi/pOmC69n1QRUzWxOMuh9/yOfnmn/hl3/Ll//Llv1V8wK4CcPpJWLQo5Pd0mHYU6PExWO65q5cYBPBb4hChE74GPViut++uGnZ2VUCYdgTSPGS0NVjNxUML912RrL7V4fTiVTDvE9xjvtPTWmYTlM8aC3V989IUau1Xp7C9PSUo7pX3q9W2KJru7q/VysFxfqOT/Intj+2frciYtJZ/ZV/w34xJspFb3jQPLDAuGU82Z6vmxKv22/QhlV4dar/BGfxEIyh/bDrieUnKpdrmtj7IUNo4qZ/b9wihY5C0wVcipBURdssjMk425jHTIlvIRIJrJCMdrp2MD3waBBg+7QmAUXUyPudJTn+3Vdmfg/uwbfuusoHgkgShfLB7C4efWOz7tA3jZGzQpsArbktCGuW/MqUuZdo67pDS4rEAL2Tzg/pBF/cz8ubZuLzofwgsj9sRwMnE0Tdw95239TnDE8HNj/CzwC3EqHvJvl7WvrndiPPW7Q8TlzELvl6e59lD+rh7+OadluIyG6DK1uEVZJ3tw7cT2l+kEfZxduo8pr3FrvV1+EV2IoqSC6l43DL0Sz3m+kC15yTWXy8bqPuvqTZWHHWjYSghjYjG/tYMeXdeb1HD6/MoMHHAvL5Eb2BpKMlwaKpOzsqxoSeMSkRDYksOQvPG2OxTaxS+rLvInFxS+fvMYErsBZMXDq2EDAIKOw4igV1haYjpEByux5hIbsikIZMwqh+cu+0WG81LhHmVPqQr/jpDRnw3pLTE9smttuXh+UmU3bs7MYVQDkzUH0dQvxGr9CW1OXYd7lIUQn7h3TqTuFxVXlar3YVw95ZXhLaHslxk8ydTXEpQcrfP0AGyvfVGlNl2+qXDIKDeQ/jSGoKOpi4mGLj8J0v3NxjStJXhAe2OYLg2EuyoB1epCvRQQB3kGUlQQwbnakLcRhkyhXdQUGhcKxf7JprYT9POgApoqMXAtdSjuS63FbamLRQADtfF78aJws20ZwIBEpRwtlOyu9DgTpRVc28yu5reT+t3GkJLMe2/mMY+zm8vw968nb0maavJ2N2Ny/KqHp56dkjnX7a0PohyVaS7+wC8W8LR9s51keZFerwF2LJ7e2zv1u9zl0kTZOAcT0JQ4i0Ny3X+03E1pEAElKTQmER46Ooi3C12r00xhrZdHTB8X5gWY9RR9p4gt41DSYVL98aoFEj9OJWdwZac+PvLiae5OcPLmk2TDylbagGNSUUP7Ss7NtyQrDgAAQUPngUHjVpGIGLWG924ddxecvK0vYFc3DxYya+v/EBBGHzNzc6ilfG9lzHfgrsLHMi+prTneFaW+Spt8nv/ymHdu6kGYOC1VBOG7TXY5p3O/vTZ8y/Nc/EAgszEI5yTh113vaNpY2Ob4lOls9SgyzbMUnJqqSzbMFYFpRpj4LqSAm/8DBdEcl1lapgaik0YkqJNsNJTl1pMWU8jJ5z+NAhO8mD7fdy4FNiSWLIfFP8cXETi4kKUbiq4obKs/03RoJ0PtEhtADWGNRO8XXwmaLEHNIne/Y7IuwPylURkJsb8oQCRZLbMGvkGXhx1LDowk6jNvyEytiDOvmPu04Y9luCk4z9WPtBr7TQqQ9UUlgQF8PqUlM09K90ND2PXDDWxf9RrBuGG2nJ6sSwll9OLMdXL2fo1XYmG5iHq67f+Fbj7fgiWjgBgUGUtg8Fz9yGZBVnDglaPaSHNmU4P7q3Qadhhdc4ABpY9wNqYXOuY1r+acsiu30DxQVZR0aFrJslSWAC8OnONP53Z7/5rV8G0ox0LVOANGD4x7C5PN+m66RsWr6JQvp7p/8DdfBCrthlZS1X6ZcnFHUEkFwPp974dp9akpZpx5V8NSbYH4u4NaeOaVpPaMSpgHQEjq00GbAr236ZwbDDEQmonGZii4wDD9osVnkZ2tSBJG03t6Lg5R+UK9+gQ4CmqBejYUZmaGndASIo2WL1ILsawEMEozH78cH3zDqa3lGjL3s+y97Ps/fxe602rvR+fVRxhf4hYB7qtEhCmYMXAxVXyLZuA60oCEcBQVdCxuBp73J0COGv3qyjwileTkBx1FVsckmmaiZdiaSmWlmJpKZaWYol9UGa/3UM6LNNuELk+LusxQQ7MYFjNsROC4P7QrMfQeGxmgsI08Hp0duBkODxTfwc+/vBQbFg0jeqqjaVxdGkcPemMwg68lNZRBBgKXCHaR/vMdA2kOghUam9NpDo2UJ4gNJKaYR22klrkCExS1w2lfeqYJ5Oc111baftdhe71PuvXF9uTCIT8ku4AXl4eW3T2MavKHPjARwOMfOGjwxhVr/UIdv0ZNk3UCpnFhZddmGUXZtmFiVozK1EJrpoJ4OpzZgQc1+WoytNQkIKABFWCfRWryUKknNlKyciYLfyofLlX5WMhftnW6r3Z50wtqSVvLnlzyZtL3oyaN7WRCc6dRBQl6VDxXOdQPV9DHkWBiWp5zKe73tj9WVCb+w7MezUBBKjkUhja0UnBnXh+2TSThZ9KNQcGMrUlmy7ZdMmmSzadyMmNHJqoBzgwDrAVjiD6OyPpMUaPSkzQVM2CHLHfD1kb7lwcgkG3LSqwrrKpmyy6ZM8ley7Zc8meE8qenKzJzpbBsyQtOzKyYoRsqOzUakFIWXD0zux5PYnTOjbu/tU2BQ7ILDlwyYFLDlxyYNQcOIhJyHveGLD6TDSK4fw17wFH02PeZjBUiUCZ8MjVlAiPEGAelMBGpcGrNvRc/FaJbD0mDw7pLIlwSYRLIlwSYdREOAxKcCbEoZUsQkBxnQsVloZkCMHhenhMhwovGR6Q/wiGiy/Bjurrvk7enuuQ3hxhWjbvHBKkhtSSI5ccueTIJUdGzZGauASnSRKCEqJpWK6TpY6rIV8ioCSFPGZNHTt94oQhSXo4Tp9tanOQOw90lsS5JM4lcS6JcwqJ8xCUSFkTgDZFZgjFU748soSTpRYO18N/mjzyAnOkDgwX31l2LNKVuBGP206LUQlSJbXkyCVHLjlyyZFxc6Qal5A0SUFQQzQJy3my1HA15UsYlKSQz6ypYWdInCAkSQ936TNf1bmryc23zRWY4nHc/qye3JJGlzS6pNEljUZOo9rYhKVSIpImalMx3adUPWdjWkXBycqFaQDScDc0AmkgoYYgHfioxqDrGvcpKcXHvHgelVcHdJaEuiTUJaEuCTVuQh0EJSSTotBqlsFRnOfOIUtT0gTgcD0CpUmJrSk/SiBgYpThRmXEO1E8p1kr9QeRrDdpNuoKAgO5JT8u+XHJj0t+jJofDbEJTpNkJCXL0DFdJ00TZ0PuJICTlfOYSU0s9Xu6ODRZJ1d7u/1Xjt4nZVrW+fuuSLKyZnC1C3bjHnTUU13S75J+l/S7pN+o6ZcSqDgPB1IpII/pkcn4fUTQIAbpKUEc184GUZ4VvB8KQ3tdUEFjPDKo4o5aUvcZNX+7EeVLrX5aTy43aV5LdMnyS5ZfsvyS5SeU5bVxipPkiQSQ/Eal4jfF66UgZXgU1coAcfL7QBZieh9gcbL7ENVhcj/Pt1lVvLlJ6j1iSzJfkvmSzJdkPqFk3otPnCSOICK5C8P2m7T73EnJ2ojCUjROcr7MStG0XHWypKK83bZy3OXt0zG8JTmNGCeVEyk6zPAy+6vXJgE/PlUf2tuPx2V7I+El80ORuj8EIwPsgdqNeE6Kb97z5nVSz0r+68DGed7RY87xngnv9yQoE1qHicQ0FN3hidqBvptyfEBumZZLQb4U5EtBPqGCfBChOCU5iorEdRzfb1k+5E8qzAEkprpxivOBFCWxDB+icQpuBXfc5xdJWf6aF+sbUYq65vplK8qKlaZ1BJbEDPD6lJRP3rNPF0tHxlarcLqkDeKtLuq0wW52oWBorhUhobm/4UXD1njLCwxL02lMAuANE2lk6INhtD85iN+WeefD+wjEiN+3t1fvBvhL+AZ4Nbe/Flmy4RfUfO8bjIvieLrf1fezdUCj3O2sqpLVk1hbLOr7qIujoZnTTf7tvh/a1RyNZx3HlE+xHbrRcrVUFLnkf3ZYaUypsHBbR/QnFFxBYLBK6EARXFcNA4aGesEMhWmA1QjkEPhJbF7uxG+8pdIeaQl74MqlOm4aelsf1Rp75xFyt/H3Gfz2EwoOe2YoJVwAoK5D3YGVIcjpfjfL6yyw/U1k6/yqeEyy9D9bkZPNeZ49pI/bbvuJFfBaYh36O4zwEhSRU9HXVPyq1ku9H5jTdWdeB8GJW6pJbuBzg+l0Ix82m+CIyMdWIo8FCdcRFBXBEFk5eHy9x2xDyXQtVe5R4Ogs/WahtIzN1frvadsEfJ5vts+Z/gQGFWBIg6F5H5Wv+wB/fPbtKI3OugqRJcNCp+yNIUppu8VfY0C2Fr+Ny3mYT7o7zMDLwbizdXhuajvb7Wbr54uvL+va3T7VnpMXb5eVeObN1M8X73RElplKr1rtOw1/n4Wjxt2QYpGEoeZNGprzolDH1lQIIrA0nZwtvdvOubPHQrS3a15s2v90CztGTGmp7FpD3hlJLhFmKht3LpfCTk5mLsuzVZW+jm7c/H3GV+OMg4MsA02JShxc1+HWzNsQc0kIDBW9LrcBtoZ1Ng2Dox+2smaml2L1VM/t5s/sdaUms/SpLUllSSpLUvGWVPqTjZJPMAxDHELR/GSRAVswgZhhaToFSBtDjmDGAICJCnnJE3eirNzmCpniki+WfLHkC8/5Qp5w9JwBY4EhCUH1mTt6rAn5wwRP1y9YHulzJeQSIwJDOT85xcGO1pHSkkOWHLLkEN85hLh/BUHDYSfkbpXEkpIjaHtTBmC/OQHfiTIAEpRwG/vfb8s0E2XpIPjLpJbov0T/Jfr7iv7yTCOEfxhcH3IQHC8JoMcTygAmQIIq/nNAnx2UBIyQFD3cpoHzIq3S+r+Hb89GZYIBtSUZLMlgSQa+ksFgshHyAYqhjz84mpesMGQLJQYAlqaT//SgcIQyBARMVMhtnnD+LpOaPJZHmpaMsmSUmBll/OtDI8jow9pE3iGiywJlqdEvEtlR8ZPPaGJASY5NYYw9fKZD+xcOsCy4PHewJL8l+UVIfox7/PnYlDgW+kZ/VAR6YqPf7c9CDpHGBtzp2cuMaKG0z1w1/qk9LGct7+4tuWvJXRFzl8WDcvZUKOEt1tNyZFHouY3/yJwVkRC5ziAFPefhBEYYw2cOHPMIBpb9lhcxlry35L0oeY/11IMNPiWchX/0gSAEPb9xnn9goofIaQp/ejaDUK1U95nB5PcnGomcprAh8SWHLTlsyWFhcthw7rGTGE6AEswIVAKkMUUKeh6DUK0MEDqTqQLQUxmIa6e9+2TmoN1wT2ZJUEuCWhKUzwRFbDA0g5qjTsiWwgM/LJHQmgi1kP6SA942qIXCZHcb2ms/FMVDsnLxVWmP1hLklyC/BHlfQb431QiRHoHXxxwMyUvM7zOFAr8RkqKN/xQw4AflATMoSRXHGaE6z7M6Gq8qBztVfWJLTlhywpITvOWE3lyjJAUEwRB8MCw/aaHPFcwLRlCSQgEyw4AhmBrMsDRtfCWHO/H8smnmh4N1g5bokiyWZLEkC//JQp5zrKQBI2LRCcH2nER63GnJxITCUjRkcukzpiUZIw5PS29Jx2myWZLMkmSWJBMmybCTi11SiZNMGEmEmzyCJw1OsmAnCS/J4fatrMTzeT0zHvMiFeXoBDEkuCSJJUksScJfkhjON1KiwJFM0YiA6SlhKJzhpAGBk5ULkTxUpnACAeHpmvlJJE5OPY6kluSxJI8lefhOHuQTDwgcjjxhTzsknpQkQT3pMED7TQyUUw4DJEUPt2mgm9oXv1UiWzvYbhqSW9LBkg6WdOArHQxnGyEl4Cj6GETA85IaFL5QeoCAiWr5TxMqSyhVgNBUnRynDIlcHYNc9E3pSC6pY0kdS+rwljo0M46SPkhohrhEw/WTRnS8wVSCIDBUDJBStGzBtIJhcPRzm16uk7fmNeOPhfhFZCsX9/5rKC7JZUkuS3LxlVw0E46QW0hY+rhEQ/WSWXSsocSCwNP1859WtFyhrIIhMJTzklPaQO8uoRzILdlkySZLNvGcTQ6zjZ5KABQwFEF4PpPIkS8hg2iBiWoFyx0SS0Li0ENTdXKcMop0JW7E47bTz0XWUCkuiWNJHEvi8JY41AlHyR0ULENMIqH6ySAa1mASgeHp+gVIJTquYDZBEBjKuc4p+aqO5E3eum3urxKPTra39FSX3LLkliW3+Mst2klHyi9ETFOYoqJ7yjN69nCuQXF4uobIOQbOcN7BkZiKOs4/NeunpBQf8+LZReIZkFsyzpJxlozjLeMMZhsl1aAohnCE4/lJLkO+YFYBgIlqBcgjCkswgUDQVJ3cpozurl1ROEgXMqklVSypYkkVvlKFPNMIaQIG18cdBMdLeujxhFKDCZCgiv+U0GcHpQMjJEUP12mgU6Y5pN86asvS0lwSw5IYlsTgLzFophwpQ5DwTHGJhuwpZ+iYw8kDweBoGSKdaPnCeQVDYanoNtPciqxMm2nu6BUOhd6SYZYMs2QYXxlGmW6E7ELA0QckCqKXrKIyhjIKCE3VzH8m0fCEsggMTlbLU/a4riN6nlm+5bT/4P4dTHPJJEsmWTKJ90wynHacjILjIoGKQMBvhlEEIGUaCIurccDMo/ImZSAQja2u24x0J4rnNGupfRDJepNmLu6QN1BdMtKSkZaM5CsjGSYdIR+RMfXBio7uJReZ2EOZiIDD09V/FjJyhnIQBYmpqLP8cy2ydftcbrJuc8HXl3U931iZ532y+vZY5Nts/T/zn8t3eopL1gF4dWM/NnqfF6LhflaNjpy7G0XfDimw8X/9uHaiHxFATmSvtO4o2a/Kv5bJo3i3dJMQHbD5f+/1zmXZxrTN29lrkraajK0zLsurenjqcC75qi2tkJXfZXmRNaKtxwp9XaR50Y7vmMDxdZseJPmx/fNS7xHqPXoHDbN5JnDfDKVlhtwt46xRpg6eohDZqnm8ABNahjXIfASBRZbgRtVVjjeZl/3lJa0taW1JawHSmuWe+pjt9Jg76exNdLv9cz9b50iSNDPVZ0wKPEMzV7n0TvxWsdJmg7AkRoDX35PN1n9mhOKnfRAMEFAxgiMjbOOecDDVQyhTzwDmOkS2bAzRcPibXkYsxplDwfa5ty3UvKe5PsJ+/91l+XGTPJaHkWJEidunpBDrdwpRd5Gjni5rUWze6ukl+1d/WH4Szz+LYqdhengY7vvv2kn61+//oAzkAEPa8Tog/RFGWtchuvmeWJRlu6XXLICK3eb1jsJ/VUeoGwtgfG5XT2K93bTRZMTAnK1f05V4d6QWc0Qun5/FOm33xGkD8qmeANRx+JC8HUDVQq4H+g8hvh1g/wWG/an2oSfTSA6B/ymSo7x/hmH/Y5sUlTiC/wUGvxXPaT3i22RzwPhvFm7V+cPo+b5zqyO1WbnVjXgRSWVyLJId/ynKL3kj6Spdi/XVblE4PoLq6Ma07T+bqpZm1S85daoe9DNNWPoQXBaF2IjXJKscj8GQcMxB+HJFHYN/XtxSB+Hy5ubi88Xfz77cUcPm1y8fLs4vP1x8MMVO4rAlRRtUa7VF8bpvtHEzcFrSMYfuU7J5uH+r5dq8kcewD40M48WrKN7uS7HKs3XLiDqaV9WTlH2QLKjOWJuaptHsVjw21644GPTjw7/vFMIxh/wiW189nCcbka2TolcRIAPfIg7LAmz4G5x+jWITSz+nD+L8bbURt7XZt+Xo+qB/dqyhHnOAVGdGM1t1mX0tyUuC66ekWQtcZuS5+CK6JYNU3SEzcsfjaluNmpJnxeqp+T5g263XynFV4YDYrAb5PXV0/0bOl9m3LP81G5Utm02I83ybVU6m47v9fmL57kA45iC9v/h89Y+7iy/UMapB764+Xn68+yd1sFrgu6tPde1yIxUuyMjtwK8/f70lZ0ilOLKZjs347BqPXQ+4RPrkatkPV1/u/vbl6h9hK9mbtPz2WbyKjeuhOhCOOVCfJXMiI/XT5YcPny+og/Xp8sdPYQfqU17umvncjtOebtQ8p1gIGayrL9c3Fz9d3pLH6+L/vru4+XL2eVSBebZqNkhr26QPaVPdjqkyeqSiTpGmWYFq947lqE0nqb66qRd8z8/NEqOxltPSTUP6d17Ifcn7NhkVjN4XjTU+p9m382Rbjltm/Ufy7ngw/G5AOeqWbPaabNL114I8PT5k5ec8/7Z9+ZikG2mwseBUFHlxI8qXuqwR1PE8r8dym6Wr1rwtBWqVd7cp+/A2RZ78xUH3mOsIF5CJvRtSjjpvS0He+WgD6dn6Oc2o4y5rWiu23Yg+OuIBXSrXISInPPstJx0qcuDz4yb/eajlf4NRbtLHp6r8lG9q23dp74D5rxaOd1ckDw/p6nNDdZTTyYRi+tg/nlLOqQ85qvxTbDb5r1Rn+rEQYlxO6N3T4G5J0e2+/fjh+uadyiHuIvDLBbluuri5varLzw9nd2fU8bu9+HJ7eXf594seEjKMny9+HHCxGcp6aqy+ifVhy/PiVWTV6P3Ulmpt33dG8jGH84PYiMpcoHHs5qgfZWivaXSk7Ocl1fUvbfpRLqv29OshWZHroUu1Uwapgz74aXqRs/rxOzgf1dGeekx36J/AYXssTcGavtRVdWU8GyTZ+Ete1Qvn1WFxN8q+MrF3Q8oxbdt1poyKSPWaL60TZeGqWUamF9M05+fUuHBzcX558feLm3G7pLXaL6mLJCjZ8UAwpiFvrj6Tq5ivt5IZbaato8Q4kUR4d/vP27uLn77env1o3IekZYwXJ3HsSCamWQ5lq03Ne3Px42Vt05u7f16DZS/NrHWcek3Fr+MNKxGaQunVL6XQ+kupi2x8lPa1/wgjk26N6POLulzAi0dss9BI4b637YS2DBvJKKU6kioBUv37TMbW1/fvkzItP+ZFvbLJygdh3IpkkGx+2u2hpu03l7QNLUjn18aXHp8OfV60JmdwQJS5iGye6af8vzKQVC/47xzsvity1no9n/mapVL8QVd/JjJHEuhqUCbxflsPRT0eXSbYk0Dct0/iLim/3YiHIzbiqX1sNQQjbtlHJwSbP3Ic6V63vv4j6lWKFn8m557766QQmYSJusABsxl/nRf9mbwhcH9epFW9ptscis89CdQFelIoXvhn1AkO+Mc/9iVA/UBHQTy/NN8o9SkhYUkeC+VJvz0N1ImONEzP0u5Jkb2pH2L+jEanAx5hVvyF7qD6SPsXup8qcfYvdAftMszFb1Vd9fTM+Be6hxovjdyTIm1mnZVlvkpbKmg+a092NB8u9uW9yNbfdZ/+sSkdPx58O1w7hRD5/ruf6oIvfalLvHq2//X7/0Ox3xh59t8qSvJ03ttnqjrN7oS7SpNNPWANmzSreiDfNd+lplm7PTZWvgHh72ifJDcucRBh+MsH8VL7Zq3B2LGkyKb9IlcV9iBT39Y/YMb+9x8kL4ed/+yxEG2Qu9i0/2kGnuHxNHSdm+swOb5N5BzWoXlCBfBi3vicgOvKX22zXEf7Sbdnd9V9JR7RUTXixHJRzWhQRBlcwDAdt5SuH2F5iO4aEp5Tqg5DZ6nxyWM9pkMu8Snhzl1V28TyVtVkFEm0pKK5rVRo738Ua/0Ym9yJTkLnzPLye+jCQ4NcZV03w3fN9d151lzgWq6StXpxSb0EWDsQdzITgW/iAHOCb0iSUNLKM9ak6Ba8+xtiJO0OrmpyLhRTNwX6SJzyAmcHuvCQ1R/evXNUaJAFC+Cn5DEhRW8FO17F0X0W0PTntooxlm8Yprbq6COxqmCUH7EMduegZJFCFBfU4ZjZQm2gFmmNZsbx7JMWizJ/3hhpSYYbfy6rsf6x0NBNzKUhgKUvXnub63Tvgzlp/A/xdHeuSJIsSHVJGAtSxu6jxg6H16JI8/XgWAYJUjocIBx24BbBUMtHW0ECbu902TYmmkLahIum0NjR1kMS4kScl11pmvA8OnH0MwGaNMEd8bSKy51SjNJSxfDohBF3+jE5gjveCVST9+/FJs8ey7scLSGPoFDdaFMySpQ1LtXv5/FdJKqyBKwMVRNTmB+QonmT3LXHSKUwms7L+u2BdE9DOIUNZDRhArgdzf7zyqI9nShJ1ITgzf3iZVBMjNAudxL5U3YJPNHJ6jvPojJxjWdB3usjkWrECZpLNbYmpVMJL14YO1yuc9k2mxZZsjkczt93vx7+flWkj6l5D9CCljb4QWRY0dBCHo07ozIoH08xra8wKG/ES15U96afkRFg0zOPgolUoIYDW310QWmEVzFGFHgJy6Qk5RWsfrMztywgvJUVrn05ejWK23telaj2NTLUFZAKdJSbxas8IRFCutaMK872q8n81/uDB0DDLQOa3OimuXKK50U9shoPMnmnu+rSJEUgJ9LZlcJ6jxPde+TPCbGRlmAd+5BMWXsYJ33z6C0eGQQJ6EkaA5O4H9Gi+xOvnNJiOPatKdRSoBwBHeyEKqlGHWohNYB17GBxqyiDBAGdasY1lBQ5L357Sn9OK1JChNH0+3hDDFJJRGbJTZoOdwEsNwUp6gTZHaQMpb0gcZyYnoUpyHYODW9RE7iGjaUckeL45Ykkb41mlDwOowVx0XiJniZMHLecc/rf68LcCUbwtM4oo7D8EOEV2BFp0oTwRNoYzCw29pQihUUThkcnjBgHMTmCO96co59U57LWPEdoJO1a5luJvm5dAzmxy7YFQJ6wmVa1N4l/9D1BWQWrFQl7KWLrcNHTKkWWwE53KilVUom5zmAsMGwdbxJLivhriVNJo73WdNL4Swi+XExmwWyn9+FrGnFCO5vG6CRvk/Am0Qh4VMm+ARChgTX+Wbknh/+o42DXLX4Hvo3sI9v7+rTm3do30AVp66P6DGP01LZResFJwNWNzqiWVwrP4Fc0MIQKELEZwzKvilRVjFKXglgB/DPq5SEkcaL45KwL192HEYzGdQCH8/kKetht5mLT+O/sijpU+SCVLGockhR7MvH9Tz1UIjigBonjgd5uXgTEg0tZ8hnlON8F7BbSeQH7cLw3vvNyNjZNKM6//Iu/n4kJEtLXTqRuPOhD28ZUgZ27WczdS7MIIV3rFMo/4qalBtq9Q01hrxKQJahrzXmX8qDF7vEodOQ7OOcOtSMLXPAW4MP3vhAhfahvVQrnDiO+3xzXcugYHxfjrr3nSNlm1enBkxSBQjqTYmcK8wNSNJfaPf93uJ7QvLZUIHUOdXhNkO5PKl1GPLLfEx+yba9XpGvfgXsywY449+JN18a4eqmutubsBCF5NcyORXjz0FezRgzHhom9lEXlCBCCUVvPayG7V4eyjtXAOnaweItYQIKATjXjJay81OneLvwgHpJ6qOof2gdnTWOPIepcTMHhOBvKEFnsds/n+qovqdIF8ErqyFBE6WNOyEvpWZaAG8BXY+dghkRRXPRE8rKqGCVDg1gBnDNe/ibJEsUhTyqnk/anYbQQbjhq63po6dDf49P0iePLc94HV9VhpvtAGZ6X1KfnrdFLAG7Wn0yib4vqZvgemxf/SDuFNHTMa8lLGjbjcNtmF6s8y5/fbqtCJPuGrOvkrXkV9GMO9HKCaNpmThmD1cgJs4r0diZNqgATmTYSFEGGuPHai3sqtV1WfJ8conn0SYXVJHzSJFVwnzSNBEmQbJI+yfg0A8bz6JWxtzyI0gR3xxPZ6ugrRfr+woTh0QnjbW2gcgR3vBlvaQwUGdbARF8Y1r4e3W7IKurhBE228P5oGA/u1sRkjiZaJexOJvSoNgtA6q6FgWO8/V9YoMBbEvB4zCtTK3pxzySGSN7dchoHEiZRYrjijHO3qgv3NELB8u+AJ3MUYVQnihefykFEqw3SmG+A9+675ob9OO0wGqFi+N7sGvmHGoxpfAHwKf446ngM4h03uU+rEYYwRvOuO+XGCqbXdkgBXXXH0CKITi/96zSK5tv9kaTXsJP0Yt4Sit3a5dyfp7CimkqbFzgic11bNWqOKRG06CQ3rTFHeamec2RXBYWK4a/g+My8Omh0swqrA8Rg7jqhmGoQJ5aLnlJEbVNE6y+8jNsaIlyCb9kRylWd50+1ZJV1ilYdyONIEaKBn5j3WmwTBN4ZmG/zrF6HaN467ybar2WaPdI3VFtwm/1UVodsxwXriN19IkfpjnW2qdrTP8aeas803I38qMf2h09362KjroTJHSUInusPqw1cZrktRVQqgB8TB5Hk0HoS0f0aOZvqgzn2WvMBlIGou3MnvQgBXWp2p0w1/kP6yNgzMiHonKiD5fiQkXrYBTYmRgCPwuw8r92enTaU/R0V1Klrxdu1MQsQzp1mvDOz14DSPaSBpTsR8gmdjvbsWoQAJQI6o2U7UEwXrJJVdS2KspaYlTMhPINrHlGYYQ7kFfzlCaJAYdyOMgyzy6ySUsQEq8fw6IdR3z5BRQnuezNOw72g3fcOypZaH0XnC6DHtU7hMHmShER2GHHHZZj3Q1Il9cCvRNnsrd2Ix7QZrQbgRiTrn/K12NBKIC4hnZYEGpyQwBYpzv3ltmIGiCK2g8rdm40WXQAFawPU8Olj1nyKfVQX2emyJcicDnpajiYHLKhmkljM2/hLkrEGiDv9SM40g/1ASoTptLmo+VVvo/KPTGgi+acnEmtqRcxGOqEnko10Q0wRTcaLPRkq0UbAs/VrWuYFY91PxAdcv49q4ewo77B7oEypwjkxdYzmtTmgV46ySYBiBnTaeFv2ZHmiOeqp7CRotaNdoGfAtVq2+99aMAhrLjW4s2l0bxFizwCuzjDYrFa2N6J8qcmkP7O+0kAxTaFYQuIGYZhf+CBMkidQECaNxfzqBFktaoVgwPHskHHrAUSSCE54SjWApBcj+8tYE877PTENGZ81R9zkep31YmR5nXlmk9+PF6xevYriNRW/HjdB+hslZ4+FEM02IfRGO5+Y/u1GI51gz7lbaALeX6vQMZDx9gy8/dAEmFRj7D2D7WlIPeIrjXQS85tRlMchjdicG959zB698SPPGb1FZz5TSA0EVAIjZwn8jDBRhFgPnfPEi+zKs24MgBTrH77aRf4BjfmF/qECtNhv27fgfL4Y7B95yhiMOvPwTzq/pxKIFP6xc3rzexfxO124ekWeBLM+wgcVayu7G7FpEezyxoDG/PLGUAHemqGPHSFvGOwfe8rojTqLvCFfarBT7KxYPaWv4loUab4mt17ySelnD5kKL7ewhUOvgAg6uy1nkq3WQSaUrb/MdV5RGuhsJhmdLnnGOW7FHCv2qc5FvgliTUy+j811lrZvwD0kKzFuUhrJkOegSmH0lDMLdaozDNU41oRC/WOu8+dr2fS3SD+Mm0coOfJ8MlMaPa9wIU91fpE1jzXPyP4z1/m2u4to3CwzECHPrSH+6BllEuhU5xGib6zZg/jFXOcM+2yUTIM8Y9xNlYkdkrIljOXbJ3NUqs169SrNYQ0GU2OUYAZCDiowRMRTTRxUxePVXzTfmW0qsbuowIIWPbWMv57ARrxTnWGTuY9ghM/MdXbdiqxMq/RVNPuPn8Wr2IybYTg98iwDSI2eaQQxT3W20VWPNePoPjTXWcfuHSLTiLo8wpuIgI7oMOujaP1A7BGkSDWJlqDe4s7usTT+I2m2b6RE//qWJkwAl6TZnyLIdL67/Zw+iPO31UbcFcnqW70uunhtssXVSwOTbGSVd1yHKkpuY0NM57Z6OhwHtpKEuT3l7nrQMdIG8Psxw0ras4IITXVmtK8dlZ/yzVoUpB1bS3pR5odRmKlOEUzg+LMEG1/ORDHRmtpcAasZACeoz8e5k5wgTDyfne0bbuznWznPtloX0NN4pnUCz7PO+Z6Q26rsh1rRrT1JuZ+CrHM/Ax7HE0mso70eYjvPG0FpE7yB9DazW+KI8VpRA0xvWZbQ81o2MoV3Ax9tJn+9/ClfbzfifFtW+TN/G4aIr3M6LSrH+6i8g9czTMECOChzmOa1bbNXSqy/Xn7J15zL/HBU7SssAyzWQyw4x/AvspBlCuCq9CGZuZeSHgcCkLx7ZtxXggjSxPDGGVftii5fU10GJvuHFt27V+q56vyTUl/EP2XnKRjD5cFxpgjUoU+sxqWEXxQzYF0bNRqTRYpWy844LhsUouyl4KghPXQSuyiOXTzO+Ql9XElOPoVjkSZAfcmr9CFddQoAb/cY/Y5OQ+v3A3SWyzNYj3qoyGHQ5oscwrX5Y0iRCqAyHZeXrsEi+9kRx7tLS6xYd3h5dFlVpBguqo4BSYpqtceakgvKTZQM15DQAjiizI3bCurVHTWCxfFIzXjQnFJGnI5fMo4cUFTv/hm7C5QuUAzfPJENW0Uv+S83orZNCn3fQkP37qp6rmR3jb4qY+kTw9vBYaUIpCUwHa8n7ZMBSN49PF5HEUWUGC45570wRRfSNhiE5d8B573vRVEnihfPeberX2bvrs283b7UAw/EURAL/TbP+lM8hVO0znaSWAGckTQQFDkGqNH8cSfHnSirzzl7yUXC1vmnBpHjpTS+wU/DWGIF8FbW8MxrEaZTjVKRIniBfDXqmS1RoEj+OeMaVZscem7Dyro9s3jP8T1uGp8kzALP6V4nYayUrxsbRtqX0aOH0KYtnZ/ytVhQ+NR0+FPCpp5P2PU8SZaA8RK0/TzzeKMSJ38P4D05XrwtJESKwM52ckkZ+jLKiBEgCRs+lQJc2XfSDfvBFGp7TpKN+f1UX5F9lwD0eJUWnu1yqi/gPMCejjDPzYLKB/c7xTQkCWQSE/G7i98qUTR3IewvCqE6oIrI9sQ2MDncxGaIqnFoBSqIK5vNGNynzWZiO3e87pCBGLu/EX16/zePafzAAmhNmt5JD6xDcE8djhPHP6N75nlSice8SOvpRV9TU5Ahrz3i2bguyDX47iRHqoCuSRmaea28NZpRFuAwWhAvjbp7TpMnjmeezDJd4zK8BCwZxX+2l5gBed/s/r6W8Gb5ouV0dVw42f2IPRE/5ad4A55HL429eU6UJrhLnlga75T6qSaEfkpkRrFb5FM9scfJftNJ5WltLk7Bo2B4nLPxzh1QOYLP05MpavhPlvFeKBvhbrNuVMV1Ce+zp9OietwwpfnSAd6jvx552Oz0+iq3FamCu51ie4oEB6TJOFz5UhNMf94I+FtUGM1vKaNwQ5/1KR6/Zmnlr6Bpr7u2WJAY8CDztSg2s9fEK06Jg0gTcPYiYzDPBUmnVFeGEb2wA/boejsG/DeEplLj6NQI7qj9YaIX45NySdqiT8Hw7pwxF31GOSK52CwXfeYLZxpFGRmaS0jnmjANjq+ypQnrwrbiBfBs23GcV9pHtKQEXTqJqK4eL07zBYvv3jOO5Gfr13QlmvG8EZtuLwdxMpNHsSlp+9kVIqy2drYIrNvqdHPM4SdrtsIH8H/rsaXIBlOKWFDvT2qYNQ2GqC+vZRxefY1wC11m08QJUm3TxmFeNchAK9pCz4Ti1RVjrvUwQcK734xrBEkT9gYsgok4IH+zAeMXzREnsBFLHIvZxkPaZqwO3LMbQluypntlp7AfC2kRwWNnuCerU4CcrGn7so69NHK+jro7i1p+rhkbXLjrgD27mmntDdee0wuJgZfh0EhR2E9lPd0KzyocA9SKvPJwap4YuZjk1o9x7+NQd7MGgYexwThY5oXY0xywZMdRr3uWeuHi7FHqx4YkSw9zWp66O0Nm++kRL5CXSgyBbpQIHqoKFss/1TGheecRb0q+ybhhi4AcxEtj7xBxRIrjpCeyT6TRjHQXF4gWxEUjXtBFEiaOW856dS6FfYtuZsapojnFknr2pnGiSBEmyJqHYv95RcWeTqymUdJJogP3m0DHaMwzRNjas4t4lN3IIajHdmSbtckU9n5MOoR0yTnuQMqiM74c8vyx0Nx2Hk2yB/e+We069j+uuxVZmVbpq2i63z6LV7GhXv+iwbS4QdOhF3EExb5KUnGQacUYgB5t5o3gBFzdIChonCBB4Rm2ImJIFCAWMMZkXkW5qhilMgexAjhnvEKdJEsUhzyBkl0Tyxk3i6sm8XdjgspL44ao0/u6OcEoXcCqCRkTiiQK8kQctA4vddgmemUH7PHe8R2DMRcmeLmrua94cM/rm4XEXsaPl5C7Ncd+6/ljkT/LbmLMkSCaNiX3MFj5GOY1v9sAaAqFyOqkUaQIMkCdijszVkEIoleXjr74IYoT3iVPZdnT14q05jGieHXFiEsdVJDw7jfjRc5Ak/0fLrNKFA8JcB8chujV/VRu2vR+1MLbEocqWHinNI4I6ZRiiDwVB73LLerOHpJXx+xz4tecPnxSK1N4f9QOAkWMHmI0P9zr8bEQv2xFtnpj7p8T8XXeqUXlOCmVd9hMzpQqgMcyx2hexaVeOUqNiWIGdNp4hSdZnmiOejplaBvqD8pR03wfy2ueH7DSeCLJ/73VoXr5wid9/ZBQ5OhjTuCbvfv9j2It1SNQzwKCCX/NF6xhAZNyAu+GEg0ZZDefaC7a1v7BjPHd+048v9STlvtQPJUA7Owyrt0XrAj3WF/z08QK6ri0cZpXbWvQjnfbhAk1qOtO4QoKTKB47jrjClfKHEPVKCXEEIdXPNAcUWUC5n7I8132kKDihc37ppGgSDHEnYA32ud7mzxvHyQnltcnlM9PM49b5G9e3h7nipPI05PIzyeYl+HuTi2833xsaOWEvdlvDg7dvwlanZV7Y7Zsnhdpla6STT1AzMSLYuo8cIDEcUOcX9iwR5YngDeSx2Je2XeoFiX9AjieHTJeBiZIEsEJTyQHH7UipeAjuJ8MLNHXOBnizn4ysCpS4ASs2pyUf49oU3A085sLpCMdAN2LI0L8WE94uPuaVJJOeY2VZEMVi2e6dnr5PhXTCGnzHK37szCz9cKGA7OBaGdgqz2hKUQFm40w7iaYZQSwLsC9ZKFp7H2dSuUtacTb86Lvd1l6nUWV7cXfYm9zzbm8vnpp/tLE6WzN3HXAUXVeN8Ti+B6BY9jVHl2gAA5JH495BUBFL0oYhJC8u2W87QeKKDFc8ZQiJGEhA+DYOJ82a9K4sV7VcbQQIWgfwwftFiEymUnUgMVjkqX/2a3XKUWaBO+nCpQZaNytJ7DvY0+tNIGLQY3BSY4m4U3B0a6ThibFxTpIL861I82KYl7WGH1BwnpU374U3h1GNC+6Tt6ea0pNh77F13AkbJ23aRA5bkfjG7aeY8kUwCtZYzOvZYZONcpKA8EL5KjxlhxEaSI554wXHjp1CGsPGM3SHZEVCMIzxiKEZoZIXmm3FBlQiu2YP+VrsbHL7QAq4KAHLItgCXGMEi8JAoVzTsJ4zDKZH/ViZHItkne3jJ7AQVFiuOL8U/dRF3re1uHYOB8tY2u5RUzXkPYxfHBUom7JxPPBIl2JG/G47T635yZqCrbWL1VEVlwk8Q0cIDkyhfBSztjMLG9rVCOlbhgvkKNGzOE0aSI555wzuUYdSjIH0SzdEUvpMM8oWZ1khkheaZnb+5QiOma+2haiqTNum/Zd8cjeZ6dS0LurFpkXQan8Q8dSplxB/Jc5VnNL+3r1aKkfxQ3swDHLALJEEZ12xuWAfCqrakc6LFfR/Jyca/honJE4DfycqZtFDOCdtDGhlQQKerxIWkv9lJTiY148c+sBFFUbRwdYrACKcwwcP8kChQif5PGYWbIf6kXK8gCSd7eMmNAJosRwxRNJ4ZJapNwtwftJ2jIDXbZGvNpPmtYIFTg/a+xOSswS3hT87fgFKMEXDsBePO1I3eaLVS9+pogU1skUe1PYH5Cm4V7lS00t/Xkj5Gbi5hE9msMZ0T25oJkf0kfeqhTGJ1EZQ3spOkg0vzWSmYIn325f6nGlfeW6h/XiowfizA8bvDjjUJiwnje0M4X7HieaT92J4jnN2n/5IJL1Js24l1iTKej8z4DMcUY6/7ArE7ZcAbyVPVbzWjib1KOsnwm4gR043qKaIVFEp53xEtukEuHgHEcd4abIATqBd4xDdLpJInqr3WG6hlo0p+1fi/U+KdPyY17cFUlW1jy6z4AZdYMdOZ1zUyhxArKlZGFj9DghA0yEceM7r8KDpCulCuESmsx0iFes2Io3lSkw4zLGfFHi/VBZoseDNHBnZ9zVaC0EemEkbca52wCxED6475PGlSLVEHeKvi/9lBfmSp5MIYrfD0Rgbu/ZX4zaF6n5m7wVO67IJFLD7a0lZG94qlwxEytTxuARhjm2c64v9aryy0uUzkQmwlRqS7J0E3H+06wsB7rapleJRLT8KsuAlpWkqRakqjSIHreoNIwpRagh6hS9nnFJPIvKON/3d4k8T4mIl8pbWTvuVBl36TxAeCIT5zzfZlXxNnKxgFDBJ06PgH3WwOSIWRERZQvu7sSxm/MioK8iv/g34kdy7KkU+ahUkZ35NIv6y6wUzSdCna6pKG+3rcB3eYM0ZhOZRjnKEoAoGroy4MxHN8Nlm1NhIlEGYQIvw9hIF7eCPMmM2tOQn1BN6FG8OurLMzy54nryaaZT0h34RPw4/hv/znymdJHdeM536pv1unoVRZk+PlU1iMAu3OeR4bl1j4IbH9cKNeo1SqdbcY7nDKRt1KkD+QZFsMgvCfQVOygzcu8LpYPPngEJ+zmDyxJzu4AsXXAnJ4/hnGv2oZL8sh2gENHJp7IbRpArumOfaAnf19LquG9II04pPxQCrXF4s8qNufGbByjIUQw8lZsKOCLGXS3N9CYDQKPb7c/ju04VIlHcWZUiUu9pX6q3shLPX8vk0a7zQsaPY1ZZAO1XehJECJPeNBF+l7wtLCqj8wzaYrqxak+Ik12767SMGsB1Y08v+SYYv2WFbM8cFBqTmBXxlzAkySbjzie2jOlUawxg7dENVGRXbkVghfdW49mFeFnPCcwIeeRJFXoNP9k5YNklcUSOPAd4O61T9/TJtFKo40sRJ+oObCss/WRBD67zZp0rQS5roBy83wGWI4B7wSae1/5+KzmlEh4COvOoqL0zJglCedGMq9DrpCx/zYv1jShFdSN+2YqyYr28SkHXvzSoYvKeuiRxDv3oJUeoAO7JG595BT2tbrQXWWHEYO4a83VWmjixXPTUIio/iAaNm/Nap6AqxPLaWa1Ibsu849+Qq95gF9UB67xzAMdxTC2L4D7JMODZ+jVdidum9Y1eMEFIOoMe4Tm2BLkEL88p0gSYshTTz6sCkjSi1D16cC9eF3U5CMsR1tNmXMh0WtxLvgAPvARp9imv1QQkkcYLOV4+whE1dgnmgxoLUHh3WLE9j5tVORmVH9eiby5gYoRzqpNKn4zUSUubFq4VbyPALEA4d5p/jrwRq1S8pDVNc5+bCjqVLCmLZEyTjQ/eiA2xu26ML2osFM4XNbaYQ8KsqmT1JNbsL5gwRK2L9nBY0Q7jFn6pQJQohAMSh2JmObavFSnXGlG8emPcJSsqS3gPnHFa/iQ2L3fiN87GnBlF53V7aI6/ARyC+xsuSwB/w00+r1h30IcS5XTAzj0takyDpAjpXTOOY3+rGeTyZzstyYf0ccu+U4pPSueNGBWOl1pIFNyH7WUM4OH2QzqvuIrqSYm3HCLRPT9q3LaRbgrefspxnnQ3FYtKfB8fdVuVw/0wT5MkznVXVj5AmiZTuPQK1e7vaXsb/Xm+2T4D1z8w6biYK562cLmaaCZaS6L7nTnb/cwcve2nMHf0tqRIhpGON6M+X3x9WSeV+JSWVV68XVbimbOqIKFr548Gk5VfaJzDV08suUJ4NWuIZrYy0OlGWg0giME8Nm6lT5QolpfOuKL/nK+SzdljIcRzTfBi0/6nfdOaHlwZNHT+akTnOC1HhuD+ayFcAFe2GLZ5RV2zgpTQS8KO4M9RIzFLrKg+fJIxmbS9QkOP4bmz3knh6RXX9+e8d9KpVaye0lfR/Jl5fkRDN3t/H5Pv+CjnSDGbKlcwx6UO0RxrjoFu9HLDjBjMYydQX+ASxfLS2VcVQ33oBQWAGc43T6CCIKgUzbtPpW64E2U1snaASWAeL2Pbej0iQdTYTJMtsB/Thmy+9URPP25NYUIO7smTqS8wqWJ674nUGX2duLWGETu8z55M3YGqFdXrT6b+sDlAgVBRj7fapAM5xo3N0zgcoQzJjOsJ3lGIHsm7Z06nXoh9zAEPwCzrA+ahhgHLvw+eTv6PfmCBjOG88v37bZlmoixtEj6Ma/RpGY3t1AjPOPGVJlQoB6UNywyzfk8xcto3YQXwz/iZHxMnik/OPff3lSEnfyNaCE+cf/5H9Ynjy7OvAM6LtErr/9ZjbVMEoOhG7x5gsh0c5xwn5pLlCuWw5CGaYU0w1I1cFgCIwTw2fn1AkCiWl869SlD0IRcKEGY435x/xUBRKZp3z75u6L8a9T4p0/JjXtwVSVbWjNgXpI2gaZwTFHLsiWIpY5z4Pk7YUJNj3LDPsGohKUwuZbjUJjhf4ldCtmJOao7MvWaiKUkupNjkpjgz5l+HWes5rbl1YhXbeb7NquLNRaGGkCLOqh6VkZMJk2gKOYYoY5xJQBzS2ddefT0tSy4jkeieP7W6CpVuCt5+WlXUQDfL4slMJb6Pn1qFhKs3iVlyYvVQ87cbUb7UlJu7p1zURUSSxBmkpTZyJlElnELuYMoaZ44wh3z29ZNeX8s6CiU2uZkytfqKLOWUZsdp1VsGHS3rLpza9ObEqdVjdDUnNatOrD67ehVFmT4+VS4qM5QYcVYN6IycT7hUU8gxZCnjzAby0M6+9hpqall1AWQmMQumVmMR5JuG559WXaVoZ1lRQXSm4e+nVj9RFJzIjDmxmulGPKYNzQaqMcK4ogmnRpw/Q0IjJxBBrinkDbqYcSYDfXhnXzkpqlqWThCdicyFqVVPFAEn4v+nVT+p6lkWUCChqXj9qdVQJA2nMm9Oooqy+RjOjAfOC6sPNgBe8eL8ND54w4dhphUM7xM3HYZHP5xGpRH7MzbI6LOrHpgfrmlRfHrcaWT56B+ngeM2r8x9mVWieEhWVjfYIchGT+7hsd0Z4xonlhKlCuWixKGZYV7va0ZO7ka0IF4aP9ej8sTxzLln/YE25NRvxgvjj/OvBHCFInn0/GuCqiZTU1lVNmcgGLbZv3uIfAfH+EaKu0SxgjkrcXjmWBn0VaOXBka8QL46geoAFSiSf86+PhioQy8QzIihvPIEagRco1h+fUJVwp14ftkkld0WApEKwedlAiN8H5EjdnymiRfeq2nDN+uqoqeiRXVhwo/k21OqOjDBIvvz6VQhfbUsqhEjgVhefEpVCqpZ7HlwSlXLuGrFukoZ6fsTrUqmVo2ccBViW31YVB0OfHVSVcZ0qosTqyqsqwmbKsKFV55U1TChauFUqoTbt7ISz+d14fOYF6ko+ZUCTgHw9SGyhb8T+MeKx3TRwnkwfbhmWT0o6jEqCAg3sA9PoZqgCBXRb+dfVagqMSoLEDm0t55ClUHSKqa/n0y1YddtAeGi/m55TgjyjBuXp9JlQRmWGVcS3A4LPVYA/5xOxRC/swIehFlWCeyuCgNaCE88nWpgAt0UyDjOqwLortO4+K2qudmcS+D4Rv8eorJ9nMA7TtylCxbKa+nDNMPKQFGOXB1AmAH9Nn6lQBEpmq/OvWJQFSJXDSBqSA+dfwVB0imej8+/kpAk+ZqlVl9w0GiY/V6Dzvd9mgyR4jRLuGDezBq2OVYYOgXpVQaCHcGfJ1BxEMWK6sOzrzy0StGrDww9hueeQCVC1Suu78++IrlO3p5rch8L8YvIVm822xskEsZZoMFmTwKaBHFiOEu2UM7MGrIZ1iI6/cilCIIc3JPj1yFEqWJ679yrEK1O5CIEww7vs/OvQKhqRfX6U6k/fsrXYjOi+ADwMd8/oNo6PsQ7arwmCBbYeQnDNN9q46gct9TQYgb028lUGKBI0Xz1RGoLSSFuYaFHDemhJ1NPwDrF8/H5VxJFuhI34nG7aX+yKiYoJMxer2LzHZ8kQaQYzZEtmCNzhmyOtYVGP3p5ASMH9+QJ1Bk0qWJ67+yrDZ1O9IIDwQ7vsydQeRDViur1J1B/5KttIZqy6rZ5P0Q82p2mUMkAM0FLwWI2UCWJFcuZ8oXzb+YQzrIu0evIqE1QAtE8fAp1Clmy2F49/3rFoBejZsEpxPPlU6hf6KpFnw3zr2NqmZ+SUnzMi2erAgbFN8+FASp/EuC8I8VzsmDBHJg8THOsTobK0csSADOg306gAiGIFM1XZ19zKArRiw0INaSHnkBdQdEpno/PvpLonlIVhU0VAeMa/VxGY/s4wjNOHKYJFcpLacMyw4qhpxi5WjBhBfDP+BUCJk4Un5x7ZdBXhlwVGNFCeOL8KwFUnzi+fAIVQHfE0zStbm2/LyESATxdg2/h8jQpYsVilnTh3Jk1dLOsG3QaMgoIBD2KV0+htiDKFdeT519taLVilB0Yfhz/PYWKhKpY5Bkw+xrlVmRlWqWv4vBuPLM+IRAwzgIFlz0DKNzjxHCGZKF8mDFUM6xFVO3IdQiIGtR749ceJJnieezcaw6NRuR6A8YN66fzrzFoSkX09NOpLa5FUeZZshldY+CE8FkwpGE/GwjSRI7hdAmD+zl9KOdciyha8msSiERUb59QrUKRLb6Hn0ztomrGr2FAGnH9+oRqG5JyE5gZs6917kTxnGbtP38QyXqTZlZPzpPJGGeIgQJ7ftAliRP72fKF8nL2EM6wvjHpSK5uCASieXj8uoYhWWyvnntNY9SLXNFQKMTz5fnXMhzVos+GOdcxlg2r/F5V2+arqXWoTqY59RT7UtktqZxuVCceGLVOmED76al0nvb02NFdiZLmaEd4rp9pfQHnovG0/YNjX8vkEXNnhl1cbN+P3Ll3st0z6f36aW7Vn/wu/bgNeuu9ec/+HDUjTW0z/iT34c1KERIXBXmU1yIpjcQfyG/uUtud+K1iZDE9uM5UDSRnLhsoEyevo5kLCxFgqsL2nVdmaXWhJJEhoDN3ssgCLh0pTrQ3WXOagf2ixqneapyqxhDFTo6/pVVeNv/YjvpqW1b5c5JledXi/1s9cOebdj1Q/vX7qtgKxbUaorei2pE7W7+mTTr4rvtBcoHuF40f6QjUUbsy0uh+ROg0HqcTo/NEBLnJEc11M6Is0+yxWxUVrUFu0senSkcXQRnBkscNZXRZNaNdJCutGsdfGYTOHgvR3stzsWn/07oLSNyAgfkGkY8ODiW+ez9713KvI9uHINhHWiHrzdFbQmPKF6unuoxptoI79qraQwgaxbowSvO11o4yAEpO3k/WUetv+xONB9kNJfJ+W8+OeoqY/ET+HSXWvIpaZM1HGYeaV6WoAOEyFvk3kX1Os2+XGYkFiEBkpzK6ES95oY0IMAZLv8s6yxQPCa7XAZDgJyBR6WdSBL7JfzWF2/onEgmTsx3XL3SVLn57Sn9ODYF6CIUT3iMY47MMgJK7S8pvtTvoCO1+YoWM5oU/LGw0MCyixnStAOHzf5Vn+fNbc/WcNiodfxcJHpqUtw0pgh4A+eTrepVEPd9QHFTKWzWFBpGW5GRglE1dKzykjzqa3S8UAlVda3QLfwOdI8CYolAk6/ZdB2ZhuEcbw7oesLreTx+zptCxFURPhCpWJdqT+aY4L3Nt0a0FpAVkUb7Ug5f+rPffAQijZr16FcVrKn4FTQaAj2HVH4lDtcqUwEBljGCEkpWGayME3ZPJyGNsga8HyMjMiErzTAjDjmGv3Odz16PbiWIZa21p2Ql5KJf4MqmoliLI/8gX42vZbF3qSNiJs6v7+IIMEe3Yf20GeKRBDBQspzAnptHx7YTpfe33WbyKDV8ggAYq1Of0QZy/rTbirg6Z32o7X7wakp4eEt/BKfN+T1uzS1ql2kR2W5Ua2DdWYW1aRg1h8L3Ky9qC2404b3dfgS0ULSBeB++gxfpr+qUeKm0pfIS5bGBI+6tf8ip9SFdmcQcw1B2pO1FW+D5XH4pI2bRjePyZUTMwyiVuddRBnze3nOeF3oV1QES6xtVmD4BOzrC6lH8nbvw3LgPVXCrUyMUTf6XEcBCzYWQIDkHzwPVAeBlCjepoQlBR8PA8/NpcG5fVewMQstpLcnSkDdcfkW1/J55fagrm3TMtJIcBTphC8LyoDbhKNjsi2mjfB8Gz3ktjuGYPOFsbs94ABiWqeV1bR1f7XjqN9OGtTYCu9GIqRlR9Q0tLV/cqGkpa+7SFnrzh8RKMxeCyay1t5cpybAtY/0mCdkvY9NEJK3q/T8q0rMWrC8OsfBBF53R4DNfjMZkPNpuovLVoTNbn+baOAG9Ulj3wEQmyKfvLJp/UIMxM2UNlinDApeo7QCDEh7L8NS/W9bCIellVp4NSm1V1cJRlSNcMBC0/ejD4suOsqpLVk1ibDdKHQAl+EpuXpn1FR2r/G0rkb3Wo7y252paUh/Rxa+5cwHBoTM/zzfY5ozHTwOJMPl98fVnXnvupdui8eLs0HEXr4PCFcPM1F7WXwQhMZIN2DejBGLSR1ZoZlMMDtA5j8dYiYH0BChCNLKHw0sHRiNvmQTKyjRhoWsJwbJiS0zAV10YIQorCsWwYU9avBDQ6a9CVyau0FhptQFChiITRFbcGjEsaW/8B4GxWRBYM0oQNJSMkhwMyAIwNoRaDsvLUAhLJE/skjMA0NsSlrgmWxQRc9GoBieRpy18TLJUJeSEMwROZEZbEWkAaefljSiPp/seaNLLE/S7ozm8KI9J+nemyTxaD4ac5OCP1oyAKQ8Z2BXxRBra8rGNQm3N3R2PdEkG7wNRCEvY8YddieRVrGOxHwLTa1K40pU8YyF35mm+rvpPo0Pr0sQ+0vpO/fGHTOnxuczAO5VsD5duQMRLsP86RJNh9KjEYgh/6Y0AYH90qlTYoREyzHWgEdOYnfYlgwyu0oeXPv6gmNn4yhius+4jMvVl1n5WFMqjchU+0p+l7WFxRzcew7q2p+eJVYsL9Oodv5iOH+/3vYm1gplqcgW22C52Ibhx6304B1mdwiTIQ/fZEScbjx1+q/XEks0FQXJ21lQ5MwOI4A9DQToJIfw+VmPlQJGCOY7jaUALv9DIZ+IzJA+ZYfgPA6RpiWW2E8QKlsl6Xxr0isC6sQghQjAPw9MGz3y0Fxk+ItsZ62PmFtft13cz3g/Yto/tpwVEf0WEB7nf4YBP3Pi1lbSSExma0+Tih0IhCVZYTBvmmjBEDd6xpEVADTNWNFv34Ngsc+u7fi02ePZZ3ORTvJCg8EB2BochGC2oSLY0xBl9RjzaKfIxJm4cIhllBGFFnuMFBLGA8hLZHr+pxRqagEZaoGDIBLc0VfPr1Ts6hGSgDUiaOrJWDeSiT0xgGNLeNJ0Ff7t93vx7+flWkj6m2YLMhA3gKn5rWNZFrDCBftZBAM1o4V+shM11+cG/62TxsfFKY4dgUzcMHXAuBjh9fDN2MY3mRxXgCt4kazgrYWZBw2ehg9x8P54TLQz0EdO31lJCZaBkPvLfS3jSBstzuKpD747mX3iA9GFh8GdRkiO5iEsQOPUIaGxgtOsIOvRtWzKaQwXAlJOjRBpFpaVe+8gUyzsxCji96YFwtcnQhGyp4bGmYEkLLEAzXhBBYyFYJVjwPr/PBZhaCAdW/EKK+rtbcSARW2CAH/7NQIwBpQpLwWHqTpqkD+wadvBr+yDxGMFiqIrPbgTFDzXm50ZXooAgKoCaMqbXkoF0XMiJCPZgVMT80AlN1w7zP1mbh88w9Nb3cM7PKPTWZkCfmPZw8QJuPNBI3b9gmDHamoBsvVm5gJAV+NmCkAbqlIkzC/q2oiJGM78OZNdI9CDfaTLoH3nyeYeiuBrXbMMXQaduUCBVsg5Rocg5H/zU1aZvvwLGR2n4bdEBm5N5jn1qU7c+BCMjWp9NxU7fUSSmNgmY2CgFbNw7MkwMKF49hXGWPJDwYgaMnkvxG2zH0kSHtCAUCJ5z30Y5CmIeItIMNL4cZBxm0S17AfDp4gqoaNAcG1FGFs5lpWT/GhMQy3whNUJRY4LOMF7i033FF63oNHEEZtKJnmSZ0CMMLeR0gRRG0hOfZJXDxfmB8nTTP1oCm2YEQtOggHZhjRwjoiXRqBOmlBsAORyiCBsesPd4aR1qhktju5td7SVDVMCqQWRcFVmeW49sFgFVUSp69ZMhw342LG2QHSdelQ3Bmmh25EJ3FetZXL9XVVhtcQHiuhh2aY7PtiIY0HqncMQPjGpKKHZbNgpY6e6ZIpaMDwzVB6hyWVQJVOcpzKfcfxEOy3VS7Fz10xkFxzNphqDqz6Z59AQyIskBKo91zNR4sS5qbFDSO8qT5OtrEQeewyh6ZzTACR09kho+2Y7RZjy1yEAyWjsiyZ7wRAy+EVAnok5s9n71N4ZCzto3DH8RGPDZf8mI1MRGTpqyZAGZVbWKw4ROiHuw9Wrbby9xfQJXr97BhDGCTGUTU7mL3X1yDNrBh2t4//e7zbzcqWWZUMKiqDhFdmlGhHdiMtGMqBIWqLO14ytKSYU+leqyxEykjMFU37CTK0mSBKpwBU+WpSdRiQwyyfsMc4NJ2Q9oRljItX/ZKxoDFSKXsdYxFuo62imm5MxYxCjxDScYSxsKEERYwHV/G+kVF4CjIWL3Y2C/i2qUVwHyYYwJlaGc+3BlpNvNhT4h4aLm9A6HSdbfc5pHfJmZYOvJ2z1GELtDQTbyD52raoXk15o5FVN9l5h7bTTQtbgDjBs9HjUiWAUGPydBbS4Bk5HyD9JMReYU2NNd7hzhMhbm+a2fWWJ7bTptGAnogaKG5M7NV0ufUbxkQoqp2fJxZklcIWOV+7+k++FKofa2XVIN2kIxKsUXwUIF2dLGt3d0ZpPNj/yZM1NGXss+BoRCOpvWY44+8DXQDVUZ7McwroAEErpF5vcMyjHl1YyJjoX73jhataDHCmnUxoeiM08HCtjHS8xindjyRckMDhaqBlBQMgwQqG/bckG0XHRiuArLFwrFG4O2U5tAkWVXdGwrkuQSigDpCmAbTHVFQC4LU/TqXxBqfbgZgqm745LOzWYQK/r4nAVZBDaBp1U4fSacYw2AAYaREc3VXjeGRjf27LWiEY9MwG4NLivnoyJ4Gfj0OS4gAURV+8a5GSR+z5iz7KKG5hrOmZWUykCRz/PS0rEcTFs1wyRjXtTxNys5wnWy2k7JHY9x8kElFm5Q9IVjD53DUqjrh1f9+tn5Ny7xgPdyEoqLmwSgAQ9NHJQ0Gys3zJWuqCIQr12Akrs6E69ic2DZGIWUSHqmoDGjECkiPzS6F2AzM4QIZPNsLAo8v9TIuVASRYJ8CcY1XCR6RcK+FOfi+cFFiTrl40QBO15ByEaOt9WLN9r7AhHneQ2BMQBnP8dzukTbMamhgRr391TyC/ZqKX481Sb/mODx6ZbjEwIKO2TQ25OCXwRQ62Ke3FgKAnbgKHbN5vY4q/hUrA9vOgPjXrl7GjfJVrBHbeY8/JCm2bUHGtTMUtk3hZXRCb0tAsvSX1+xJMkS3M8iASrCBGPKlzRPi/objgcK2Esi4dqbCtg68jA+2VeD24w9QkuFLkMwBGKBbmqNPJdwwDPjy0gnyiObYFwb3/HoPflE2WC2oQObjEkMfKISp0K5TYYiDdoSg/uRqJCmbiMxhZZBkGpVOmTzgo3dhxwo6HVc43LhmPfJmCkz7GQmRx1WlYDGMZjGmM2pfy2Y/SfrBevRwSkzzoQTpo1npqFiMKC7SdEZ218ZlPZ4mfKbJDGTIYzfEtxg1kwjTGSvOGpuOzjQTZ6XNspI164AXDg6meZ123cREhBA7/sD0yINlJGQVFBGhJjTP2K0dNmS4zs9u6OCQsZmN7DaOSMN5K7Iyrep1UlMwfxavYmM9pARSTCviFMlDC5CyGF6CYNMZYs6mGh3dOj3hW2veMiO+web4KKCXitnfHVp/b8j/zpBxnhn0FP1z+iDO31YbcVckq291krx4bSbX1UsDlmx612VBN/1a0TEbxIacbgj0dODBsOIdoAxE5Oq+cvuUb9aiwCp0W1LWRjNRDDRmRvbxhs0UnyBwtv6myOTQxCG/keR88GzxoTPnA2dGPA/U13NblTLby7Xo0jAWC0h4ZlUp6Dpj3pa5Bi9FeqZI3AJfH3NvejVbBSJ6jOndbEsHNL2eLQO5emnw62VdCW434nxbVvkzqzKjopq1JlLQmVaLCtuYys3nB2M71mL99fJLXYETv7zDscxa48jab8mOWGmDhXxOhvMIaVTsQzwInqEk9jneOBOG+j52yPdrqpklJDPqMRkqawl4MK2ej87IpCDjLOoifosjcWMf4sHOYmwgXzYwR+opAhZbX6SWcmfYwGVUM1Jf8ip9SFcdT3NXgdbUDHTAFHQqWuMP0BG7M5gF/5hNEe7YhkUyvwTOsMARy4N5JeLeG/40zKXtTqIFZQyWnhKiFzvK9ENs7Soi0BYROBZDa9rSYZxlg9a2Cnf5Lzdilb6khhMpIiZDcS0BDwbW8wlpZKwQg+AZimLl1zgzhiq6FL5YvQUicBTEqqyR9ovZNXK/a9a93b68bFL4lVM9AvFMcIiHHkAyzhsV2gGsuGN5J8rqc85JRDREs+YkfJ11NYigiWmMPM54nQBIxMRQeNoicdOFQQO/3dubLn3BifO+h8Scnz3NPcz/Hn2NNQkDNsJNm810VgTQI+D+o8WDHFS3hc+gHGCKN4yJU3sIStOKOJVZloo6dw1HS2Zg7lwyHDWNnqOGMydoBEYbTVrMYyY7glIVO2A4NdeRKrg94eEbalkK3UPYmAU1OFSlVVSnNtWQD/X4d1+Q/d9wYx4gqToeHjh3abgD0UCPx58nlXjMi7QeIFJGJeHhykLokD2PeCSbgmwCJBKJP5JzEQyWqkgGHm/LKOlYJzZ1Tks43Ikoqe1jnkvkgRlvHqrRZmXNehMKVWvWXGfbNMoU71j/lKQZdE4DQFO1k5Gcmq1HOGYJRAyRKjBVU2JgZFswSjxkfQJo9cUf7wM/lsGibsSCXfQmUKpqYC+8tcHALvcAZbR0cZvxJBXBoKvaR3RsxwHx0K+m7Ikz3u3DUHDdGe/09VBolo3wLl+ftfk9Pi0cVSPz+3vWRjK/t+cttZIe2TMD8zRDU6ulxbynVviyctZl0nQaZhtwSfGvc8fvRWXxjzc0tJunKdjW5qDdRe1jIALNjuYK5pVoqO3v/AJ65hrBtKcKbCLA2QCXlvYkQiGCHEiwmfJeMtA5w6g77+ihC8WBwjWMCl9ph88AlL7XMqPHG02iRmiyemgatTZcsDXqgSunwsWQSGpyqtweEtmQMSrdPnOo1tVC0vWC6t0R5oJqXj93fRJLXjM4VznKfLU1XPAZa8rfWji6NqYsPMpEpiyLxEkHVqKGMmb08hKwvLeWqIVRfwCI5eAAiVWJDbKdn3JvwCSI42nF2K2QOaaVUJg6HzG9mVViAeyNeDQprZuMgsfSnNZbNt7CYTvNVP5YwxmMwVIVaz8bb8zApz2cVRyIQdhyY6zggCnJoR3KgNQNUM7KTY/i0FyhPQ2p/xQo6iauufaz3BUOlSn6XGkHNKwzGefHMGHbHtQ7AglNOTok6vmdBtfp+aCOPnZaozXC+LuEZKr0jncKmtkYBGztRUJDNOQGIQIXn7c0KeyR5AAjcPRE0sRoO0ZpRFHEYIYAVs+8qrO36W/qn8dHabRJv7YXyON23MFR1evAnVpsRzJ0G8Uu5e1L8o9F/ixx005iGAOYZSCidhr3MJA5DFMP0SkwEIGWZjAcssa0BGNv0bCppc8byytmaLJ6WEaxN1yoOxP7XPd/ODyKQjCcikNWUkF1bESVvnZGH372YNG7nBcZ+/BkTXtojq3Ypx0iJu5ZfyzEL1uRrd7oFTgV1aw9kYLOyFpU2NZUbh5jgF4EJHriSFydkVjqzLZxIms7Nw6CEALBAIE8W/t4jkPBgLjGfLRhGnUEeL//Xaz7cQc6DzQhUc7xDLjwSSH1kNBEPPSnIHvSd+L5pR5Cxmf+ZFyKOWASsMllXKr5EX5BTv57MpAbJ4xYbLXJbRSjDRy8qeJ+KAYSJRRw0hQeYjmKDApZMCaAgzPOP21CwYgQYDP1OR4Zc6rzprjV1OZNaa7hIk5h4+amHpQ3x4ybmfbT1rCDiRjf5s7pIq3SVbKpOdDnKo5k1hbF1V4y3UeC7Ylz8HmH94A5dv85AE7XELv9fIz1IkzaowTYnJUgafPriOBqxkoUNebBTD/OUuCNxqDlIEyS3gABR5aFOAS/3VmSi3rfD4RAMgD1ph+2ZaPe8XOQglkVWlaE3GqQbMRIVSC9AmRXf/TKj2ykQMmje6qscdhsTa9iCFhmJXFk7SNEAyzYkAQeIY2KPSAGwTOUxB4SG2fCWB4JZwsInKEcnClGWg7OFr4+CSLclqIHpcUn9J4UfsgLfkPKgTX0JPIQiKQL9Iwx2zDQ08Mufec6eWuetW5OEXjnfzREs64kfJ0xNYiwVWmcPIY3nQBIesBQeNoiScKJRQOlCh1rOFsgGDwt4ZzhxJAhM8eOf/ukNnvqQ1ioygAyYNkDFsmsEA//LnrkTpvreniGkrRZbmvCsPP7yJc0ubXgDOVI09rWckEndJGuxI143HbNAYw5TUIEtKbga42rIiL2JXHy6aIaAbApjqDwtMUmuguLhpruGtbIjIcxeFoi896FIcPO/ny1LUQTfm6b7VzxyCnoyciQAYg09ObWImMmp3L06sV6IdCogKPxNUejg0Mrhz/u0kiCLeE1GLQluIroanGvoawxH3WobDy2VuMpKcXHvHhmhAgcC/AhFFnrrgMsxE9xHj7DwJA7Nv8heIaS2IwfZ8IIc1wSAZvcMiht7kkYrqazTFI3j7EBGGcu5J5nDRxJK+SGZ7aVYtztLDE/XIgsbyk3H+uhVjNjEvU2EnBmWTMHZE+9gXFsavjhRxWMpCL8yCPbYiHfdbwTxXOatf/4QSTrTZoxWr7pyGa9yTR0xjUgw5amc/SYUExCIEmZgsbXHEnRTq0cKGGb2MPLdwIWX2N4Ge/UuCGX8/0mrfdJmZZ1CXFXJFlZC9EdOdvc2U2mZDaPHUH82mg9JXioLGUJdpe3QSLWjd4EGiMNxLrd29swRb8H/34oGO+2dRWdahCQCu++dc44wGzRzlGiI7gdIumnvNBmGTqylZ36NAINzoBpgMq1L0zzN3mlYZ1+qISoViLSw4dJS4gzXlRJgkU2vUCszIOTGGcdVt7xNELxs85ALouYJmNbxxeJSMCoJnNFMw7NBdyODu0jBh4BK2vRPnLwMEwRP4LoS3Web+sF1pt99sEIUM2D0MHHpUeAMzAY52ARrC8IK6uYUe2swMoijiwfP2tcZqVoTgg7uVJR3m5bme7y9s4+uxUMkahVGKHRDhTTiMKgGQl2J7cjPvKFNkevs419mc16yCbyIpv9a2yjX2Kzf4XN2ujx4xz2VQsV1U595KsXHxYP/FWMWZSr13pwmxu3PzTXopg/mWFSsLGKjhBvPHoUbAdHK0bwL6z71A8y2ZfFOAmqsVBK+KANSHCGCuceLIQNRWElDQjZ1has1OFwDCaQQBRleElkiG4X1QdUQiWTIVs0WGFD73ZswPYlEp6VWcD2Jg/DEL79CRCmXumMOkRR8a1sopAJNBYq36hF1j12uyYV1c4YyE2bPuyP3r/p+NZNsyzYc6NETBszYM+RIpi21seeKw1ZuJrksnnnnPG8KYNKpIGJWCzBz2OR8Oy1b6CCm7xlGuURc0wy/g4f6XEuCnrwUfC9OGvpk1bGBkizanoEnQW1ylBo+TYMEncVGEQBJIISzRDsm/Oy/DUv1jeiFNVNc516SbxwjYhpVpNGQP9RuoqJfZhO4hXa0OjtCAgOU2H0lgQnZo3puSxntfFPzy7p2wtvy7whdbkWLW2jvbRwZl104NpXIXpwKfb4nY6q91eNb5tNbcZj0QZ4s1oQmvk949v29AGwFkg2jNVIb0ArkCSVSG8+c2wUKEp1HO9l+UyGkYEwFSRYszng2aUS0pjBbFd7WzDmlsW84swpkoEiTCbaRGJNItoEIhkk7My5EatUvKS1B2q3BzVQqAIS8EhTyJSMs6cxiPEhJBvDVFWyehJrzoEnigOoiqBqTdjDQUyJ0ffpY33e2LQzQ5PVw6ahveECTctPYvNyJ34jlkgAtFkxM5LOZHto2FgAzRDGQjxLC0dQBvEmpmkCedDfRLbO5ROmZHOeZw/p45bT6GdBxWwCPjGduTEq8DBYyBBzkBCPZuGPMAoyAzwPyVRmDNYkyCMwxiBIw6Dv8QjcPIgK9Pe0/VLnPN9sn/WtN1wSI6zTpxRheAYCaAaoJdH9DjO2GazPF19f1kklPqVllRdvl5V4JuYaGiZgGRIB7YhoMJFRoPHyGa50EmD5AsP5/9l7t+bIcWRN8K+U1dPu2mxnZ50dW5u26gelUqrUVGZJRwpVn36SMSOgEC0ZZBQvytSszX9fgmREEHcHCJAgAy9VqSDc4XB8fsFds8GquGBHrSP5/8/ZOkoutjlq7sO7Spr/wS/S0SEXK0CDC0/jQnK52nVqnaQHFLiGEZq0X4Fw6/qeHOuqJAdIadR2RVpjX9kjJzKtJPn6JX5F+N/wcRiQUqUEFQOx1klKgL6VVTlHNyUByIVIaDQbDHIcQ7U6qreg6wY5ChmRbmNB7mGwSif0CStUlOZ+QUEN04OciUrtfWqw6hVVjoRrQgoNXyGkM2i8hs8YrukJfAdZv4b/EBOaNFzDj1hQ85T+RHPwIqUCtl1zqHKigiRx0jrGAjF4PCIor9FIHYegr8IpPAB8iCEi0GmgjqUb6G8K0/5QFXGKikLTthVkilbLqYWq7ZMBdKuoxTVEieohBi4k0GknxMSH6HFMIycrhli5mEKrjRA7H6TEKSydeqtew9jVlIrGKxkItUxRAhStrss1bGkJILYvo9FsMMQDDFfrmH6AqRviCqREuo2FOAQLOp3CLZCnnIbc2T2EnUJTZlyFXQVhB+g/Q6lcmwtILIhT0mZkQ18Q9zVm/43p6GACQbyfPicruoL4yVE7b3qPanD/pwEXLWUZ3ASq4qLdYRPeCaqURt83mtwOqsNmgi6Zzu9Rcui7OwmDIQrRd25W+2N6V4b/MrxQfwA3LZ0BmQL7j8tNux+hMo1rZXyp9F2fmo8FZem7QpddN51rFMij7yIBjGwoSt9lOu236V2o0cWXRny09GV0Baaaj3a/TXoZJkAeffdodi2mHqOJOmc6N8hIou8ApSyGqUXf6VnvmekdHX35lLGnAzDS0pWaH7DTlNdrWZBkXLNiBNJ3d1IWw7Sj7/Ds99B0Lo8VRd/nyXkM1Iy+13PQPVP5Pc0FVQkJQAGaS6gHEqB6J1o0PVYN9Tm6y6Q8Gqs6G9s3wJdC+aXB7YJatrbCprDWm7RE+XO01t3MqKJTNFpBLtQrQQdQrqoe18Ak64fYsphCq6kQqx6mzDHtm6oZYuQSEr1mQsx9oCYnMfzjS+eawxEloartCnqxkglCiJZVNTmHLSkAyPzFJHqtBTmAgRod1QVQVYN8gIRGs6UgLzBUndP6gRXa7ZOo1M4EoAzAypDzAai/z0CrGxQ1j4dxQhA9vyEkNdOCnh+xo/lp/Aopgp5/EdMaakDP31hS+8T+x9jvDPU3xn5GW92T+xUDf2LuRwz8h5FGJ/IXJn5igH8w8Qtm6pzGD7RPBl3W3mib4dd8tXwBgFipBDUPicppYojWARW6hzMjBMw9SMn0Ww5zE1aUPK63YKuHeQw5nUGrYZ7DjoandCDa0xlSMmDjtacyTmQaKp5sGqNXvY530J/C4NM50eMUbkBn6kJEodVGHaM3UuIUlt7u6sBPbqYbzUEDgFTRfDUHoaJpUoCyAbW5xi4jAsQDSIl02wzxBDZ0O6ZHYCuHeAU5lXZ7Id7BimIn8RI9po9prLvMASRXqQLERax8DjmkA2C1Osc4TwyQ91ARmrQf5EUs6ntUb8IVAORRlJRGbQd5FpvKnsLD3EVv+K7L6xz9hdK17i0SMGqFMkBMhD3AoQZ0AKxO15DnSQHxLSo6g8ZDPIs9VY/pV7j1Q9yKktCk4RCnYlHPE7qUL9kGJWb+REYK04KEg0rtR1K4zmW1jQTvkwgaDoRPpNtmDdcxSLcTOI1e5RoeQ0Cl3V4NXzFMsZN4iTxeo3u0rdr32HQdBYhapQgIE7HmWWqI8kF1Ooc3RwqQ31DQGTQe5D2sqXpUH8KrH+RGVIQmDQc5E3t6nsalZOsqb+7uf8BHSNBWezwD5qDUCZCRpC+4HED9Aa3bvQXwJYG5GjWtoSJgLse2+sd1PQIZYO4HQGyqBJgbsq77SdxR3bqXqEDXWb7T9UNqUpUmlBzE6qdIIXpX1+Yc8rQIICcjI9JtM8itWNDtqI6EqRzkQaRU2u0F+Qwbip3CS7QHXlGu6SEUZIqmy6mFSu6TARSsqMU1donqId5ASKDTTogXGKLHMa2frBhi+WIKrTZCLH6QEqex9HaAhGdoK4PFFii9UhEgNhK9c+hBHQCr1z2oeXLA/IOK0kgFMI9hU+nj+hCuBDBnoiQ1az7MvVjV+BQO5wGlRVzGr8jgOgsIrUITABZC7TO0AM1D6nONdlYGiGORU2k3G+JQ7Ch4TEfCqR3iRBRk+k2GOA9L2p3UadzVfYdfDh/iPAA8oFpRs1L3Bs1Dp1cA9Y9mAYwsWk5GSm2sDi2nY7UjJnFCrBRazkhObq4KLedktxemcFYrlO/itPnyEUWbJE51T/7DOSg0A2Yk7BcBB0CvwOt2bR8iSSAOCkJrqAiIc7Kv/jEdk1AGiFsCEZsqAeKSHOh+ZHekP41rPIOrP3kLnyqbbspWZ7bWYKJWZ47WUF0jmTtR5z16RjlK11hOhZ56RYENOlFY1FKPKUdJh4N5j0W0ZbkaaGvgcMbOSGbgIMYwYfNk6GI8ahk6YDEeq1jX90ieQSyA3E2A6EzaLXcg1tUMcy02NL1CP0qYAxGUFDePT8DTHy4pV5WAl0MINjUq7Jopo2iAwlqBarBsg7++a4nxpTNRnXTmx2+/vntYv6Bd1P3w67u6yBrtyypKmi3XxeHDl2i/j9NtcaLsfvnpYR+ta7kv/++Hn3/6sUvS4p8/v5Tl/h/v3hUN6+Jvu3idZ0X2XP5tne3eRZvs3S9///v/ePf+/btdy+PdmjDZXylpjzWVWV5HWuprXXUt6XWcFyU2rq9RUav8crNjiv0el1mB/641THbjr0fdHqpqAXKxeY357gQXx2Z8KI//3dLcpM95DeK8WpdVjv6GRbpY4/vC/9Zyo5mdNHldNw5vBmvaiXrdLSKsSR/qUUWU3+XZHuXlWyf2zaZWQJZUu/T0N404MfVhTYjm0v8dzg0rhuTT/gLngAG6qeqx0pbk0/8dzu2muFhjf0xp6PgrnBP+L8ml/QXO4aL+aVcDhGLT+1lDS2W2Z1mdftXgVEOQw+n4K5zTh2zzRnJpf9GQpWocISXK4Uc4n/+ZfaXh3P2k0VuNFbJ47v8O59bz8LRk1Cc4z17wJDkSH4z4tcGYlpRbgOX/6zvKw9H+9B3jUKnIRvtnDe+NgWvVgfMYgp04n9iNIz/VyPEx1DddrrRkp1+DCXhkAm2iaAf9vKEAAPd8MjeIHx6ScXeyXE6/wjndvWQp+qPafcXjij4z4gOc39UuihOSU/eThkxRUXzPckrHp181AnOU0FG5+UVP09hrFKxzoj7BeX5ECSrRhuVIfNDmx+Wlx+c5qpISm8JDGeXlXX4Y/NOsxeXgtX2Kiot93FotyZ/8osWxlucb+pQlG5QLOHNKaKAhW39Dm9uKE6qoT3Ce17V1oM1FWaLdvqTkpb/pDCB+S7KvUXKx2cUpPYogPsF5PlYxBbL2lxBLPYqlkqe/8MuHtsKsohqDCKzN0U1w5vW4uJOFsxNZwiSfh990zYVvKSGJnY3hubc5q+Y2mqUNDifDE+n+lgXGMKhveolI9bWn4SznJCJsCY35yjxKizrpWmU3aYHw+dzVS5xvLrMqLdvrmYm5TGVpjSSRfDL8idYa77sx93u0i/Jv0goORTT6nHwFmFeHoIjO7HSXEbPT070PWvPB2xw1h7Dx0kdSbWinyy+hMWHCUF9QQyd+iSE18FQvLqUxoxsVcXGd5Qfc053A+26An+a1ttcoEWDn9HkAbyk66UI6eDoyucx2e874kV/CoCVHamlTmFIht/Eotzk9BGIrlzlxNMhdZMS+5iq2I8Lw3Ie3wmiwvpjRMyHtLxq+6NibTB8RX3TW4/b7JEb5gfoh3qb0/KaojGaW1zJpiDecFI/8rN+ClpKzzsn5Ducu04u5Pm4KnhpOv2q0XtRqo9b2kkX6jmDWFqVFpx5XHHqd5tj/XWOanb3Yh2YsKGJUx10Spf9ZRXnJrDQIyhjX8m8UyatoCxjxv6mhEEdMtsQvoW+Rh3f36I7gfTfgXgdmIefum4ZWene9MMChvuks/uRYicziz+FXjVbndUfUH+qsgWk0+UlLk7zBl9GI62PVzrdgNFIDduqTPs8vda++CJgevulzvU23GbPBifmoETHyHL1m66h2t6uMChvkJ40FyB/7uBWIjR/0N435lu5IDN3x/d/1ufUO2NAIFRTRiEC9xzaYCER909EupvlSJWXcRBxav/RXjShdpSmDreOPGmP/t6t0wzA6/aqjQdStP6BdlXb//oC2VUprU1xOx+8RV42zDpD5rM272SorYHz8phMViTtK2dyB+RzG9F6O6Y9TbldJ87/2vIDtcT6oFq3BP5Cjcj6yR85MZwsLmYxvGe7UJ2+w4RIRPN4mGxVBbHzdwHVTNCdtk7eL1yhOcJZDj5rZ71qzu1+TeBvVKnuj+fa/6GwNKtZ5vG9PPJN7gXofdCS8SnGrmMmC489acSir8/k3Jvx0v4YNLouKW90rk90xD1teieRq4I9UDHydl77Os13vfDAtDuezxjgnk3BmPurM6HU5JV7/eo54c+qcAtN5u3v+Psp7k22TjbqOF+GxO5XorxrrAd25PLQRzcfzSwTv6JF3pA7720rie0yNUnYpvRvXaHOqzs2k0vCls/b+qEa3DEzJT3Cef+IVedrxHX/UlO2yzmHZbJn6pMEzfkaXb+sEPZRRWVHzm8zHqZdrDrBnR30m/XKRr1/iV8Sbw6c+aSwo0fcjMitLvALTLXp3Df1Y0dk+8UGbHza7gsuw+6LNEYdgLsP2g44G23teSuZAJ/lFW0LRWiLnszZvbN88U+J81sc/KkoFf7qIvsVe4qXODG+NFNkuWUJve3mz75LdYd79DOf1G8KzzfjNhX1WUOigv8G5xsWHqojTOu4fVslIzrzvOh48/bbKPsZ5ne1l+dtjntBOnP0+hDsn+AjKwGvZ16RR1d1y1mdNfDDi167MFFfpOn/jjD/kJYfUeFegapOl2S6ukcgsn0DKD6m9zTObQUWWqKqmCg+p93O2ZRedJMV0lvjWLyk2jtqRovw1xtnTx2xd4fy43VPCwyacyq4k+lLo+rweK9bzER+N+bKpObeAOX9l94EIrNWvVbdOvXlcfKuH+rWRYQ5kNfQ3A6477lF/zmcty5YJzfmskYHVlFooABFYq1+rbp160zr1xeyoGNf7WWNC7e7mgppJa37R44BRcZ3lLKPjBz1+Wr0KIrBWv1bdOvVGafG9Cdh4QMd2C+ezXps2zbFzztF26psGDps7CFhR+79rbNrN6uydOdpy+tVgpHeYIBeM906fw0LUoqZaqdGsreVxOVfIyriKQ1gUD4viwRct0Rfd1bE721jbqdNnau6IRPRu3FBzIw3visHjzxrLPinnEMrxRw0TSuO/KtSpg1mypT/qT1dy19eZjxqpzX6fZ6+0ZZ1+DabvkemTry7YsXzZIxUAw5eT+5p+NDeeUfGy/UnDcjY5c+nU4TcNv2PhEjXeap7+At7lK3088FVrmF2PylG8TRk2/d81tNug80u2iZ+Zswf0tzETnOb25nV511yezjtgRXzUSQi7q9bIF2fI5JBbJHhojzz06ZZ8u9txBuzEGcsrf0BJlm6LVUazIT5MtaXiLkevcVYVbOwgv+ictLF1evGwyMrz4/Q3jSFrXHBGmKdfF7e1A5NdZjt2TYD3fcxsY3jUsT394Ca6utladZkj9jDm8ccQ/TyKfn1nZSsC9nkaREE5ua/jkzA9GqZHgw8y8kH4YHqe4ovSJG9vmTgihrGBNwLwcOOSbsq1+GDqWn4wFTQlyWFLf9XnLGRqcNXkHfcCVO6dlpKiGpMycUl77e4nnbMIFFxoabkFNBza/WfKn+EfQmq2QLf4Ic++oRRviL1JnblIaSUmyZsePzeu888oqdDt8+ULwrf+Mxt2OJ81DCiq6N3c3U8aTiLPs7y7zQzhh+coF8F+Nhj542Ww2+fP9X+LEvdHC3TBbICosGfGwJrBPdpnubV7L+W1GJsDnKEbe9B1+h44vOPZYBeO7sh8oIOT8AmOLTg24PKDdaj3WBotQowOa3a7vB50bR2K7TWdHcYY3lYg5mjGb/ixZHurDGGePcyzh8EcyM0372Jk320+NlOzM3xZhkvpahbLvksVHYc3OwWPqVg+wXy8Mx+bS1QHfoYGFJamwtJUWJrS5DdHv9OLUVc/XuKvscUnVmjOw8ZqQiau4rrNrV4BySxSbSP5ABSr9wf3mZrgV04fAmoIqCGgLsoNraLi2z16tuWAOnYGrkdI6WiKczA4V8wdYyvNu8Vwk39HlKUdf5xyyq3szuLT022n33W50S+WnH6dYrs49hu1NaoeuJIUC07MIydGd5CLg32Y78DDfXwWbvxbk/AwvXj4cczk7CqivFLzwyRW72TSP6Q5M/MQ9/gFXRcuomE80EcIeDhKgjj9KO464UaAjB5vtb9MbZino5682M5+DQbrkcFerfF1mW/4HU1rJ0FPPFFkchxUQe/GRtu9aocHzTKmG3nfNXdDSLjzvpvZNTe/HpRYX6z/qmJ83zY97CE+aEi7716jo4Q8/azBq3yhNyt0P2ntfMB3HNeIrDFITz0xHzX4Vpu45F0JT3zQ5Mfe/NL7eczdNME397+PMtxyllAdmVsYeM00saK5HH7TNQi+LYS0x3fTqrvbmWXhLN2CYXHZuLGrT1Fxj6JN2yCSEfVJi+e/8rhEAqbEt7CoJeYYFrVgHIIX7X93tEukd3C2G+G7e+KrX8HQ577kvFSbP2zfbGhn/DYRCC6z9Dne2urxlptB94oI3QTIh5fs+6HDv2Sbig4avO+63A+vGYr50yX0aiDPj7P86e9m2rnL0XP8Q6ydw3dT7Yj50yW0NnlVe3xQsVUs/pFj7bwiBnX8Vsc1OuWgvoWg55e/O92caNHtnZiaeT8ZvRsnODz3xj3Ncjn9qpF54jtR/2geX6CSz/4HjelgC5edulluCSbe/+7s1MUd92YVPPStPT5KbB7IUFRleFZDm6uvTsKNGT1kVb7udEZzpb/BuX6J4vR4Bhvj+qLugW2KNnQV0oKm9dHHidmvhpw5NwTxvmtov8n98L+Li+KyeKX0z3zV5YwnC8Sc+1/1Dsx1RpXlItGFhTRaUH0FVSUrpzP9c7HNEcJuRPA2Nb+ExvbLPEqLGiir7CYt0Lp2gKuXON80D4vip0qpfZnK0horZozc9BNL/BI6gQ5fsHD7is/cb184q3PcAnD+H6IiLq6z/KAVkjn7VcOrHkRqlp5f6fdUOZ/1LKW77iJm5lOZjwYyty9gigxDUkxr4vbA5jLb7fEbYYxd8ErAaziMT0XN4H03TMGk6ZdxqvjhjZ+7U5+NeNOGSn2aQ6qYJagN6liaMRNHfsV200hoHW6SSjsrtnZWjzHFdZUIHl49fXG5E3da8Jf1oLPGxMXmNa7TEMsAJ5mbg1jFx9fRz9C3Tpb1fkyYUpnxlEov67N6H0wvmTRzD1IOwTGIeQTHEBwD/V17D8FhnINHU68x+m49VZZUYbSPQIObG+cxpxnR4Y7upmgPsTKzUt2v+iNuunX933XTdBFP9qspZ1aDvO8aWsjjMq4/cLqZ+mTEkxWX+agx0DtFZsH5In6JITWwDRCV0ZnT3e+TmPXN/d/1ubGSkl/0LeMBr0HQeQX1TZ8r79I6+psZVw7YmK8GnNFun0SlWObed3PuEtmJEhp+o3bSL1GBrrOcuaCI/mbGleOLmK8620UzPMGPwyw+gFaiLeORBEUG1cFphKiQUT13SZT+G0X0RgReAWP+/1lFecnsdRCUMarlpnZzMXvNKr+E0SpanWUd11+kK2lsQa19VqdtmWwtnM+mvE9ri4paqIIauVSzjeX2+aIosnWj+ZbVPUq6h5bJREtdXOeUHM62ZCvC/BLGNTCr2bzvxtyV79VAyuvUvq52Ffbpm96pycusoNcjJeWMarvdd6cqpXVRpcxqwucu5bWcSmiMdQ6i3aNdlXb//oC2VcoutqrK6mTgzUncZlTHZvbkNzOuvKye/qrN+TpHf1U1Otkwyvluzl0oO1VCdx1dcMKV+aiBz9NR23+9xNyjs8RXI873dIykvxlx/TdKkuy7kPHhsxHv3+pgSh/mZr5qxPSKd6D79KuOtWMK7GxTZssU/c2MK4td9qvG3haU7+K0aeZHFG2SOGWft+cXGVQH2whhIY1sJs/Ra7bGh77oW8SoT/qyswv65Be96c6rGqqy2U76uzl3VtH8EiY1XHBdHf1Va3zJ275ltGfr6sc+bq2XlZH+NoepZNFgwv0Ms6BmuxPP4ErczEeL94nQfOUlbdTIWqyq7AI3ZkigQg5F3eOfqM8u6hWs3WDd1RlQgvQ0QyDh3y9kWA9rLJzP+rxvCv5bS7zv52F9bvcCgiu0Y39h75+7vX829kLM2VAOaKJnKp3HKbJCu4FKxduRoXT1sSumiUHGha+jlkQ+zmeNUWIm4cx8XKQh9O+mcLcPRlbL4Cs1wm4YANfjyTaKY+93/XxLnm2Z5Frt6ge+/DDf1AhYZX9GSbypm3uH8jjjLpVICg+o93P8jC7f1vy1Jn453d7g7S4iv2is0A2+V7HzTqUIKbzvptwFntHoKSOSlo9IURl4LbZevG2u9LqMeJkb9UmTJ1+x1CeD0Zp4KKg5/iP3MkmvHVIUtVInq39lYX3tfaiKOK0jIG8fkqjMsFrEA2u2lH5N7UWgn7Jkww5iRGWG1SJuD1tKv6bfP1/dcI9rcwsY8cc/KGroF9G0+tOz69m62nFyTnEp05qY7RGcz6a8OZs7uAWm3UjfI2ThyXw03FB/Bidn/V9PEnHFd1CI9l/T38y4ivbtisoMq4UFhbiUoZa4e+n5JTTyaJTijUqvCA82P6PXesjKu69CWEpjfJCvXzCHir5jlPigc7YAR656BHFwyfQhA+azRtYTF9/qPsOjYpyeHlgIVqnUpe3UzMQNZWENLxSn31bZxzivXW+W83wcr4AxfzYEcr7rcO+GkLw7+5mPNtYqi9OtI6r9r1IyW+umigttJBRwCX5DeGNeclfl+6yg4EF/g3P9lBWcPSanXzU0hPYo3RS36fGN1kKoGnlRDS+UrrNdo91mnyS5RCvMXKFEGhlVVW4zXTnARH7PtnYBpJ2yGmfqlV+lrXlYKHc3k7K1m8w5+5t6P2skj+mGkzUefjyX5YARLyU0rd8WdD26vvBctja5vwZu3tZ3DPHjGBtbnS3bgnB2tHPqUDPDpv/BgB9ncpL8dDYg7f84DlAfCzxdxavWFmB1apjxlj/xDLvRVrx5A7l7pH4cCNOV2QKumq8buDaLJSSD7ictHiwgjz+eCwwfcVY1gUsV1GrPo4IrCA51GUh2vgEZXqe1fWZhG3LYhuzOYtjVqnGsRlKvLcvRqsLR9GAnQi3nUQj+aiFZYoHoO64srfJo/a3+/eoV2TuZyOdugCQoIzd4aSrD7aV80ulnjVWO9brKc7wu9FiuqbUM8pPOFDVWFLtLr/+7LjdOc3u/655+j5L+bjrhtSfKwvr1tkis3Uv8HDOPtQvK6NfS34cm3REOKO8qfk/kYR6KjGwhwuVia6c/H8qCw//NwMmAOTnyMt0lPxw7Jr5407N9ZWHWLp6wbtyNfleqWbjpQzYH1s19L/H9b8xzzadfven9x5v28cnLqiizXadrWxDgMjfAAZCPGzC4ORrEe5BV/wnWcLd0/7sTAzlgDm0e4z/q4Y211zpPfG8wX5MHO5Us3FhEi1NmO+vxV40pYkR5yOYHnSSXc0LI4M35YEf9724CDb7nKCvr3HxtN8ZQfE3Ci5KFr2lGX+ovtTbwHSb0yUG2gBl/dijJfjXjfI/W8T7mzLQIC2kkYjli7589/jh1FnBTrrst80/sEgbxyXABg8OW/mpjVxFTjaJo8MweeeZuk+cKFSU+ocXzgIa+GcAZ4J5BXHz10DdFc+otebt4jeIkYl6y5H3X4X77NYm3UckMNckvOlvXi3Ue7zk3cfY/6EjIzdF6P2tMx+dxlsf0qZ3TrxpTbszkjO70avBL/e9O/ZLFOakeywGOaFYzUcEBBQcUHJDhmv7xQKvbCy/t3W9pep2l8AmqG8Pnp4Zuz5p4G0c3U29vfUvNWGMnhoxJiEMhDoU4tLA41L8mx7JDapgO8EUCejduyM5WRzvbLlt08zEf5rh8NaHM3rvRfZ5DDIhL7sZ+PkUF3qbZNoBkRH3S4vmvOuwgAVPiW0g4xBxDwgHjELxl/7ubmbfNa7xGWCzbl2eznE3m4QBM3PjPtmaax+lXnfHxYVzNy0bYr/ojbz5f8puNtT9ePerS4x4jwYvH6BXl7Bo2+UWLY7MazeXY+xL8mkd+TQ5LWz5OXouBv9NlGHLHkDuG3DH42IkXTeyOtftcBy2RBJ8ZfGbwmcFn+ukz7U7xE2yHec0wzR+m+WdgSP23Ldm7wl1cusBWM/SOBQhHN4Zn70qFqY4p91Vnc+cgw9jkZLKaR9i9EZK7kNwtKiYd1iiuc/RXhdL1m023xGVu4JqAfIJ7Cu4puKdFuafTEG+Fdnv8/IJN/8TnPmgkKmcUPFTwUMFDLdVDufFMgz1S8ETBEwVPpMdvjp7osu7VuG5Xx9naVUAkW5ObgFQcgjMKzig4o0U5o/YSUnypZLqxem8jxdfk3kYli+CPgj8K/mhR/uguesOV4Rlk27PcHNYGXgnEJTim4JiCY1qiY2repnDglY58zV2ShEXwR8EfBX+0LH+Ux/jl1G2VWL9zn8PaxCtBuATHFBxTcEwLc0zZunYouMIHfMAQbe2O4vjsjRwUkFNwUsFJBSe1LCdV5euXqEDXWb6z6p0oviZuScki+KPgj4I/WpQ/WqF8F6fNQOkjijZJnFrdQClgb+CdwJyCkwpOKjipRTkp8gaZD1ERF3WSssqjtHhGebtc7+b6G35dgy/BgbINviz4suDLFuzL8F/3qNjX/iuugePSlXGrGuzJgFyDIwuOLDiyBTuyy6xKy/zNpQMjqhjsuBTcgsMKDis4rAU7rP49pLevKC/wDVF1kRHuUSWqs3qhqoKzG6dGVkpCl/xkwPMe7aL8m4Dr4aOGyUc5Yh/qPf3qKViPLXYZX6lKBgNTyS/E2BBjQ4xdVIy9i4rie5Zv7lGBavf8V4UKa/dB8ngbbVqGsHHjmz5FxQtJ3/4C57CKae/W/qJhR1Zupwy21P/uxJYeiqyVCeHv9t5yJPm+mdwEqOLgxnrwicw8jRI2EpBfvOnBi7KM1i9oYzdrI7maPECjYOBomGD5Jlr26ZL+7xrcGi0wch1/1eXEkav3e/CwHtnnJ5TsV+iHtQzlwM/AJsWkbqxxFZf0sKb7Cc7jd0Sl9c0P041bgsX0vzuxmN9Ruslu822Uxv+rmXGKksssfY63VW71oTVVPQYWps/S3XTZa4y+c+IE8QXO8U88z0Lb0PFHDcl6ymEMiPoWrNI3q2zFdWeNHP6mVghi5cb67rBZFOwM8OlnjXmydIN+UMK0P+nEULlXogWFlPcHl5+vHvebqESfat1m+dtNiXbWMMnhbYJHEBs3WLTmt4OHZZBqGcnNhP/FNkfNqb2rpPmfzY3ywgoMMK3Byw2wrSf2bhITawP/m+JijR/GoNdLDr8GU/bOlPP1S901+N+87GOQEctZg+1XxSaYbjDdMzbdFSpKh+YrY69pwnJWwYyDGZ+zGVvPoU98h9ptyJiDvQZ77YziQ1XEaW1l1g22z9jUYuU8gskGkz1Hk3X03gOPt6nhTvTyQ7DdYLt+2+6YVx6AKzS1cp8uPwimH0x/Tqbv5GCtqh47hj7JEdtg38G+52TfTm8AgdZnx94nvQsk2H2w+znZvaMjveqa7Nj6RId7g5UHK5+TlfcvZ7jPErtzcPKq7Ni5mmsw9GDo52ro1qfVD0yHGG+YSA9mGsz0YKY3aYny52htf6cJwdnUYBVMgtUGqz1Lqy0vs7ROO9el9ayZZG1stwouwXCD4Z634a7Qbp9EpYO4y61iuCHLuQWDDgZ95gbt0JDtGHAw3GC4wXCPdvHwVpRod4kfGM1ye/fHAbnD7VfNKdhwsOFztmEHg+AT46GGGwbAwWSDyR5Mtu1lfCFpurGeMdPMTU1XzSeYbzDfszTfHmoe09j+9DOvAmMzBvEKphxM+RxN+S56wzVe5+gvlK7tH4Hk8Dc1ZBCrYMfBjs/Yjr9kG5S4MuIj84EWLOETzDeY71mabx6v0T3aVkkDHPsWzPI3NmIIq2DHwY7P046zdW1/uNYHfCAAbR2k1Pw6zO0ZyC7YdLDps7TpKl+/RAW6zvKdfWOmmBtbsZJPMN9gvudovu3hPJRbN90+Y1OzlfMIJhtM9jxNth1b4qneysm0NLcGcyMGMQvWHKz5HK35AaVFjDvHyWFghrupFQMYBQsOFnzWFnyH8iJLHR3rF9Yy2KLVDINlB8s+R8teoXwXpw1oPqJok8Sp/aOIgjpMrRrMLth0sOkzs+k7lG6a+6iiTbPJon2105Y187kb2DGUkRsLfsiqfI1oHqdf4Zwuc1TLvbkoSVa9nzV4tSe7qMfiT796gzEX86kDp1KnmEXF/yXp2190PGsTz5K3i9coTqKvCeNj2e863G+/JvE2KhlMkV+mi3w3xVWKW0V3w+lnOK+7PM7yGg4kq9OvcE6PVUwJ1P4S4pxHPsj5gNTmWHTyYWhwVcFVBVc1kataoR+lLa+EeRk4ID6ZG1/zZ5RUlHPofgqonAKVF0WRreNmBoGB5oc8+4bSz3H67aY55pqneC3zGeUoXaOn9uvx79s83sa104Tg1IgxjVopE45BbageMhDiaRXlW8QzMZCl8Hny+h332lFeN01px7OmTdET+td3XJjpIpFpWnGP9llePok+66DRgLkbRGoLMrAr76KaTdnVYQ2M+q0YZluTALLt6uPts7ZcopKhDHhHYk0XqKh0Dq5P1YTlubxji7ECbLo7mrFdxGlVPkf3RrVgVq5tFRXf6mY9HW4mAsKKQ8aMM9oihxIAuDBMB4LhyG84DljRBvZyx0dTNuvd/VhEW2jmJKJVdHxTzKD3W/b+QqCTzw4OGmZ+gOF2X95W5RBIHDhAgPHeGBltLb7jo5Nyxiihb8x5+ogStMVLmvouBMqLRo6uL4HVMxA7TCUWQAQUfMwUo/52maWbGIv0003xR5Uk//z5OUoKpK0Oq1h8wncYR+uyXUfRxx9NT2OuX1YTciTrgb1F8rKMMUrSMcdMUFyp2j8YVA9lQW6tQg0InggAwNYJQZyYFUE+FQBzkPoGoo9gZQF8IJFnNXQng/OXKE4Pl6vDQCOjZ+Pg4ZtuRBTXMlTbA3ITXUk1oXxSFiNz/wtnGUbAryeYVA1uHKFK05aR3HuWugWZAZpZHtLMrnYCOHMwwzRd10Bc99g5hjgjuC7Mh8BSuOpKZXOq5NcN5DU6wTL6ifNfn9ErSoBDHAAbqQ2wFNqWwKnUbyfPE3hWs6ingPIkfgsYDCAYL3FuICYDQQlS/WA8HSuxAiaQyMMQJeY89oSMRJLepywH4k2DHQ05Manm4Bksw0DcWevEga2YbEzmEnw3aYHw3WGXWVVbY4yKh6rZn7XKmi2ueZQWzygfDEpoNXCwkl9avm/t6ahh2IWJOldMA1tn0+0SfeMR9G9fUV7E25eylWy452UZmsKZ4jQM0LRYc4Uu0w6bIKWYewTT2kAtZwgcjmZJAmQdUEeOuSKTbcgicwX9pUMwMzj+dOdQgSLMFnoL2dbwUGTtDvtuaQH/AVy/4VIy6zVkKcg6DYfvQA03LGysx/BEm9X6S/+475PubnAh8dAdCALGgyele1wt9L5ISh/3FyjaPtxtiA5maoMKxkmEMIg/AVQwEGniKmw4HYj8PmJQRytqQB5OazU7HOIU5XSR43Gw7pfj38XhBwyi2iE192YUJ7qH9QvaRY1qin20bnZRbNB1nBfN5PDXqEBtkZ9/qvXxGm9QXjeugV8D5L89/JVcJnEdE04FvtR55DMq6uH9N5T+8+df/v7+l59/ukjiqMB6SZ5//unHLkmLf6yrosx2UZpmZdP0f/78Upb7f7x7VzQ1Fn/bxes8K7Ln8m/rbPcu2mTval7/8e79+3dos3tHk3dsQVz+/j8OXIpiQ6yb9I5YdoC52LzGtXn8RNf3j5t0g3788+f/76f/TWLv198RA5oDmGrY/iTC3a/vaMJfOdjFkv3z5zg9LPr/hmo84H1fd1GJN5/jUl2+8ROGJz5ofIToOyn7w4WkVDUnLrUPUzJpTqibk2O0baqkhu4AJqdrhloWX+NSWxn4vwf69DXC16Tn/8cu+vF/6gpzUfug3Ud8UU3HDV9aU8Y79As2GbSOiwb7/6+2psps74JtDR4HbD9kmzcr6uzmDq3w+p/Z1xPWh3Vy4yQk2Adhjjqm3GMkdj6Y8h8/3fzXE0H83366zWtX/I+f/l57J10xiLPNYBTosj4db9ZrJ4eFRmv7B6MBbh9bw0K8+6lBmuatwV2/Nw90gwDr3m4gPmAxZsM2Fmw17UTI8lMlXnag7oZ2Lgb/9oR/OOn/v9Vjicc0/quqC13j+nGHfIl+fEbptnz558/v//53I8zYFfO9ppgQo7l7yVL0R7X7eph6GxiIr3ZRnAxqcsPh2OZf+m1e1QJY6Jm7qCi+Z7k68wBxe4gSdTYERgz2x4WD/A8fT6ktzx3nIbn+R/QcVUmJQfBQRnlZi3O4nsEGJj9FxcU+bud8BGIC2dTSfUOfsqSGppQdrLuz9Te0ua1cpPvXtQ3hqyxLtNuXxZCc+Kb4Lcm+RsnFZne4NMGsue0lVy191Rh03Hj/51gesjoH8V/tjDfmwvfbB+cQcpeZ5i7iFa97vEh/DmmNWfdoD8I4U09ZYjB4aKksDB1MLc/7cUsY7w+3/qXY9tD4J9kRYD0qGg5c/qsZsLR1r7LbfMsfu7RC9TDWDnPkg5tfDDJ9+iZ+DeRL2sJRcN8vEHVyW6XZCpx48jeEma0QdBs+V9lhY+jqJc43x92hA1hjGXtHgZ70vQ3LYUhaRXG7R7so/2ZlTEHtHbTI+biyahCPT6RDtHZTXGxz1DwtfZml66TaoM0AULDMLkrLwx22Cosd8iEq4uI6yw92o98vLIch3XOEXnOd1WuUDOgbhpdFvd0UR+6X2W5PzBIMEfXIzKY5h1GgJ6PA0xmxkPe1acjxzJz1LG/6ULOQPNPCdoesZBRh5nWJKxOsLPjv90mN1QPbh3ibWlosaBLblnvDddAkMsnJwZyqAwXcFBba7aq9vcSZd4mArr+QMBuUDS1iiHcAr75iT5RDtIgHlvVAEKfQD3hSAW3f9EXhMrEk1V0Spf9ZRXl5sjyDHJJi+G8UWeJ2U+M4jugEV09nRx4KQOn4qhWqc+Wap35nshyG9OSRWy3DAFka6kGIqrCzLlA9GNsZAJygHiRHc/2xgQQd3aC+yGucraOkTmYNuqJPPBAR5MyCreXoqp0TxbY9aCqr4/Olxt6LDUa36Tbrbas1CfU3eY5eszWmWGWW9Xb1Yx8fjyXbTiUOj79a723Oq7L6mOYyGZSTNHOC+DLydGMwnUBQD5Gj5fGlSsq4yRGG7AO4r9J02K7wD29XzfuhQ+aA9qhbEUa7Ku3+/QFtq9Qyru6iNxySr3P0Vz3INcmFaAbDokXDrDk8YixKRz0sH4vX6L5WN/ecAijboRgMsrIwZ+fdnN1xIv4qaf6HCxXWd27wauEfd+PMEMputFJPFgqr1tx2zWczaBsB1TI9gQhiJ/v5OS0+hy09/BnO/g7W/64/38h7uHNAWkk81zlkG2fvlU4rs2PHdzrNhTq90Gme+wyewu8umJnh5sWwgQnq4NpTuYcznOfg2uRmocnsOs921BW4et3MMBgE6VU2SBiKfNjezMOx4MPrVSaz7wyLQdtqLDv6e6vb/Rud44FXZTZ0o+mHaOpwswDasKty4FyRw8PvcVMIGvCRU/+2mjOIGa6mfZ1OX1pbnG+y9rbH2dV5AC7J27qa43IES/iJxl/0jwr+ifdfsR7fTOyOmfERTLC2L+thktkuE6G2DyzdCh8/o8u3dYIeaumqQs9/8SQn+SlkH20NnrOaPmgKhDYu+PwHa0MGAlzU2IpfkdkyJ0E8JMIT1/SbycJhMUSi6Xeadcr9WAmnAjS44IBQWIkIHUOcbg4Q63DlWvl2ugDF4IRrJ4z5ZhSGgYUewy7XzLEwDCxIs0JFOVgiksmgrfqd27rEu20yfHrD3PX1eQyRCWfLzWGSAYBuM87krsr3WWEn94qLD1URp6goDnsYBsiHH5BeZR/jOqnEs6aPOXPngVl+yLC1mLpweWvkMP9dO4fZ13VFFRZwyAaKHpfuFvCrdJ2/EdMPJjPDLN+7AlWbLM12cQ3hgXs1WO7tjQHNGD5L7LL+nG3TgfKu0PolxVZRO2+UvzZDpY/ZusJrNe1WTT4YjXAOqczSXBDKe3UMQCHFycEok67BlfIV9VipI4+LbxdFUeN9hwYFgiOjnZt78Wpbsibrfc1IswPNXDmgIqd+XVG/FQTV+kC4Hjtp9se7m4she/hqcgy+6yy3jD/MeQyjV9RjpY4oLb43cROPGS1ofNPcLOTA6NPmviuJhLBj2Vltl72zrObDydPS1YDB2+BFatLThLXq+S07yGfmjm+9m0/PdSyGzQRRt8PrzgYR5A42s1GzBgtZd7EWSMLWI4+2HnnngsOOWS0nc1enS9nmHNZ9m3sdXVx8fJXqnn2F2V1ja103WTpJzbzxbTZPa2NP0cV+n2evw9xbSOj82UdCPON7Bu5Edy7Fzj3Jdlb8Nnnv4lj7ly2bTcgaLRLL14Vh+4FemZsUdPpRt53XNQzjbcqp1awvmyn9L9mmy8c01FcPuElq8I6Mkbas99+jfHy8+Wh1MqB5SWld3jWvMw167+am6G6PJl1gL6xBbp27ur54/Lx6ur3/ze7GmBAix5/zILBlMMVA0zs5MHeY7lt+qP6AkizdFqvM4N68E6mNTRKW0vjaXl7jrCqsTalMeRnEYU+EWQJAUg86UhAXg+dbFrbJDHO5zHb9RclBMDNbf3R615rJ6x2DM5vWGTw9VrZXOGxPQvqbXS7j0q3LHDm4kiTkfBPkfPL3Xg23PnN4OcgF+zH0HPJBfhgKB+KXsyoVDsQv2fmCHRu+fSpP8ZXih9O9y3BgN+V6yD0ra/U9K9qLSUaCkPQ2ZBkghoWHHu74b6OYvUEhZDZEylVcJkzsM5v5p23L0tzG4/1nK3z0U2tP3HvYwADMWvPsG0rxmZKbdKmO/s8oqdDt8+ULwg812tolexlVpxNNJsnXVZ5neXefNrrMNiJmWucy8R6K2+fP9X+LEvdqiyDb8G5Rc6z0No+3sYmHFvEZlLS106n3aJ/lJpGdIneRUbXNZsytaCtdiNVZCR1Gfux4O85CNBn8V/BfXvmvm/JkYmcw02XL4swvXvmv0z0rqutg9Md8nPvItJeVLtJNJyFvQcDF4+8DblGzdHuatduEbKyZDloUlPfeTJcHe8C2Pz8ZlgjhS4RydIXFwjBfbf8F6vvs+zlkJtzgDZ+yBQRCmDc0vp7Kzq1UmIsVNxzM2C8zDmvpYS09rKWHtfTFOLVezL368RIrzjVM5d4gycPML/gMRuGRURxMIoT7EO5DuA/hfjGebRUV32pPdA4+bbA9dLoiDYIz96wtWRtVLPgeLGGtZaNp9o5WbulEBNCeBBF72qH3BF6sy+52M8vTpi1j62/gTnkQD/vO2qfQt20ZuGIRo5D3LiQ60F17DmGiyVENF5o7WnlwGHY9CC8zN9vYG/UuL9ga7IiZ1IcNWvOju8lGUmv1Gozm9kPrV2EEz+qnZ72Pty9n4VrNesTCoc377DTXYDKU9ubZodMNNGYpG00fXvdbhju5WuPHJN4eyhxFZ3HXS7s1/S56w5dWXGcGPcNyGHQwLR0qD8vBVoJkOLoDD+tg4+i/qhgfdhc+jQFzxHuUR4OZlC/UDjZNBhfrNX51KE63tSHmzHSL2f66ahOXnBf4dEXDbHx+mDJEDX+iBm3iIREdIxE1uDOqobIwq2ZqcWFKb7k23wyNlm/yn6LiHkWbdiP6kKXZmtG/8rhEwzmFRfawyB4W2c/A5xI3oHRzL82/7Tte+uL/d2oa3lBR23n78+DAmCNf4GWhzQHkuKYYepWOhJWDmzcus/Q53vqYHLjf/vnwkn0/qPhLtqmGhdGW22V3H5MdfuTdQcOla9tae+Tn+Ie9tg7nV0tW7fFR8VZt+EfhNe56DH+rY26Y1FhasCUuVV/I4MXaoj/uA2vMmpdK/mheuLSzI8HaIyOS9TrfDDtcAwY/bHfHvSoPD+vr2ICSBRu7uiMA+unedMbl4Y82/2JwM4I3y+UPWZWvUYslg+uZCepBgnyJ4tMlPNhGLupu2qZoY+k2RZK/pdtgCKbcGyVtwpKtTeNlcf19dG26i/9dXBSXxasVjXVDsjqvtMi0p8Isty1w9dUl+5viYpsjhFe067RsnVQbpG2FH+/un47EVt9MWuVRWtSAW2U3aYHWVY5WL3G+ucRru3mMChNJVTytNoBV7umNcEvrvu09Z7ev+HqU7YuLleUPUREX11l+0Jy+j8Gqv797ohk5dR9HjTTbNl6jxAQsDBOr6GhuGTlNGJnptZaS4jOOWttpcevu6Mj/MtvtE1SauSMeH6tdd5g9sdx+IlPXzIfggZyqxapiCN6uE2WmMqfQ79XG9eJO2nVRKtrk4iZUiaRZgtrMeNfcEHkY2Hk4BW171GdnZ4iVBz2tbI6xJcl1TWJm6J1QBwbGxqtxJar9wzAW7KxEa1z5xeY1rjP8c7AlazOcI78ZvPCnn8eYFvJjUjes1mhdhdgfpATvFLxT8E7BO3nhnU77GPCA/zVG35e22BSWauwsv3WvuTfPrQ1aYANOqzfXkhDbanQkbMntDtYOzC2taLUDI5ap3sDqkvcEnoV5KJK7MWQoIZ0D5zKPy3gdJUY21iPGhLZV2mNvboKUiJrjfv17h3qpq/GZbB4Pq5plK7CWguKddElsEsFPlFbbemBrDKE+A6fzvQerf8D7AOxsoDqwxKxMNmH36a2bd4+3cedQIjo372NtaLdP6oRrkFI7Hk6V29VhQ8F9cZ0r+q7CMhboOssNbtztU7tQb5+/eaynhXSv1DzDGxDwUsoDXmBBW4Ooz2HiRMVsNeaaFog8psLvkij9N4r0HsohZT+wcKVnzP8/qygvNZ/zYaXsuLgS9KbOWOLIYK2ex8P6FovTSuZxO469DQv9Qz6OuJ72rNni324Jv32+KIps3Si9reMeJU1PaW+sUjK0O5JtR8fynY+Gb2gRjG3t06TYunqx+2K9rnYVzgk2vdtcLrOi1O1PMSfbHXms53bfXRwzUF6Cjztp8Q01QyU98LD82tpBAfdoV6Xdvz+gbZUK9gZCphGlPA13qMCmcZrblpoJXZMpphO1k5yox3/AFBMlpPssqLvCKkc113RtknOeOGAGDnV7FHKofglZnau43ZUru+sJtIZCMHFoZr27rf71Ep/kNb7gquV1T2WE5pz+jZIEv8dnhdlvdRY46H6yjxV5x5nejt2O2O023WZ3Lk400o3BqlGP2oVt9/kb2zUjpHOjXqF8F6eNPB9RtEni1GC+icPEhYo51RhrWiSyc4Xf5Dl6zdaYgHvBP2S+rM/CoQc96Mhwb3BPywP2/EJ3MV/VrnDY0j7JwfoO8j57Y9jyGDnfIN5WeDEo6pNcHGKBOfKlJyn00NcQEa9+7OM2XpprlORhTVgbm1QE81PnsMtOfMhg2O0hYr4WFl2ecM89fdzn7rcC+LhhXYJkYs7yHPAru1FrCKvTdK8VrLbsJNfX8eBqkKr1m2DN0Drhndva8UXQ4mNcYLJh1xbOw3LDUS7TnQItODEXnWGbw7NdtGiYixPRBh324krpPCu3twF9JnZ9sGRyCe4s7Lprq8kWvwOlXZvBDx4OuniTYWBXvlU2SDqK3K5sfppb/6LYcOTgTI4cnO4iMgh8UsgYXfllcv75IAY3wbXSBroGF3s+8MMu+aYe16+yP6Mk3tRde4fyOHPQHEWFjlv3OX5Gl29r6hZaNw071mW3Ta0oJgdhIK3oc7crt7WXdLpAVDr3Hse7gZsKnWfUZLsGXd9JslIMviEM/8TX/hitzEIU3XF3u4qAX4e4jIzHWZB2EHW4bw0NFBetOdQxyjyR4eycji27nrAjzxwNupAf0ixBdU4PUhGNcmhNglqd29ZBuA9VEaeoKExOFelAkqzHasfxqhghYNLVud3N0FXaPOJWfMqSjf5Un1bjUJKl22KVOeqrfjvG6KtDc0azq98/X93YvCe2xxf/YPPeQBwBj9vJP2brakdMnVhkbmtPPMnV8PJieHow4sXFA+4HgTRHcIOIjW15J84O7ZmqZawrG7Xv04Rhy++rNPXbMGaXmO6Uc3Q9Ztgf5fo0B75B3vTCEAiSSf5WjbHP2vROBd0mOLqBgVeFQ/ciqs6plyGQwLuMR3cuE6X4DNwrwrvLPqNXlFjM3i5qUsy6ol66tDPbe2JudxTQZP5xuj1kmw4WFOgq7M7z3sfFtxqQuG7szw6VDNkqCJotUFTr9jocSeXWMvs4/bbKPsZ1oMCv0rrMXNia3J7qIuuzp7Bu/aU9nuQgSyUrcHjCvr/dtjg9euHiqRXO5l6LPrldTk/uqnyfFa7wS1bidOb6U1YQZ1PsgevA2a5z/oj2KN0Ut2nz8sZzVPe45R6+SdfZrgFRcxqbvHPBcl23VbnNnNQ1bOdKlxy0K9pntQW09oS58SEduCqf4nax+lCby9HqVboZrUFdXS6bM5vtX5CHD8/AosDneeyjUVa15bBk+3CRxbbqpb8mz0YqX4tbwn5qToccc5CzMuhjq23YL6vCDs+9Wuya6pGxRctUt2LQzNay4uJjgRcUeh/Oy3okxwPNsFfyVHnAH1mbZUuycLZvWIuCVR2VtoqKbzXwz8qWmo0YlkBH66+bxWiq0Jk81E12uk0fzlvhfBJ0NpbyiBPkEH4shR+hNuccgbQaFYLQaQ44nB3XPF8angFVCTXOM6Dc0+CwXTKYcoxzNf6bP7sb4qxcwKH5Ne1RAcMDrESphyNvTInlH7g+Ll2v8mj9rY7WV69ncj9W01DMX7c7joRPt+t1led4cfbppNjTdyl6yBPdKqZHVu/lrPpnBrT4/qLB15KsWLyLNZ5or40wfo41OPOk1T+Gf6zisVwb7uzUhgJAJy66TIfvfziAgkLWAVDgSTt4oRfX0j+DWDX848bVYOlk4BgOzFMr3bsmQMe4wI0O3//HAR4Vsg7AI09afdfU3L0cJf3jjpzXLBSwsNWxivBl3LHu4oO9S7SjhBTB4LYW00bw1GPaiH4fGV0/4wQAOsAas+vtjPxV9YJz9IeyIPusy3gXkod3r/WYxttW/4/4mM2JER8Oq7oPTLxxT/lPwy5senIziutX0eQNy4AGb76L2bMJO2mGH8HLcvL8hx3dP97Unr1K0GWDhK4TzmEAPeAas0f6GrMnrhaf2t+sGnPLUn+G0lDk9zyRB24TG3AA+r9Ex5sHHZ/lDJ4HDcCIE7PmjyhQLBxE5kPXo83jzR/ZZil+t8WwvtIPdIPuAqzbbsfnX6WDb5oOluaLpTUPjGQ4G1yfTYC1l/70NfelHos2TwjYZsxMWA3gdV9jeh/rrJboO5rLHPXf1LVlUt7c7npTrg/XgZvceN4jHuK8iLU4I0FI+iGyiPf2GwgmZTZESvdBRzc0zDvqDBncdUdFVqgo8TVHTeQ5o+ACu6iguQAqebt4jeKGbkjGdVPcfk3ibVT2BusmfD6iYp3H+zZVsNJKC+nkXR5neVxqzEJw5ial02Qhv51pfntwNE0OdZ6prWzjNNB3BE/kjSeCzKc1SpE8nWU6Xx8SKG8SqNP7OY4fsCv7F5+9gxBQG/i1PWRpetVa/6WmwWO8Qe/LCA8VDBVl1IGe9mbbbjUoRsWCw2lI5iVyzSKEehf2QjKv52eaDSznkM672DAz4mkh4xzT1M6sVB4SXD8S3M7Ws+QsRu6fogKfm2n3NA6JnzWjf9XxEw3nFCYTlp4JhcmE4Gtr2ovNa7xGmP85vbrbtlq/Uw50A0f1h5mKoY96y5MurYdxDCXpU7tZRjaTTMVviKz2XufGWzLQK8qHbvOo+TQ7O4byCY7ZH8csR/A5OOmQFoe0OKTFwftOu8YWvG3wtjJuwdsGbxu8rTVvG5Z3wvJOWN5ZuLX3dqWwF4QtxMCVN655uhdoSM8SnRn23YYsNWSpIUtdTNw6LJBd56ju0nT9Fjxc8HDBwwUPtxgPdxqHr9Buj999DC4uuLjg4oKLW6KLC64tuLbg2oJrW4pru6xRFtdGebzoOvi24NuCbwu+bQG+re1jfB1xugnOLTi34NyCc1uMc7uL3vCbhHhdISwrBP8W/Fvwb0v0b827gMG5BecWnFtwbstxbnm8RvdoWyW9G7uDfwv+Lfi34N8W4d+ydZUjnMA94APIaBsGqMHHBR8XfNyCfFyFkV6g6yzfBecWnFtwbsG5Lca5rVC+i9NGiI8o2iRxGnb1Bh8XfFzwccvxceRlWR+iIi7qXG6VR2nxjPLb/bncaxgcXnB4weGdncPDf92jYp+lRVyzDv4u+Lvg74K/W6y/u8yqtMzfgp8Lfi74ueDnFuvn+rc+376ivMC349VFzmLyjmqwXUQcmd+jXZR/s+Jp7qK8bqo+tA507vF0bHWInCFyhsgZIueCIuddVBTfs3xzjwpUe/W6W4uzuEj2U1S8WDH3VbyzHmYnu+U2WKY/lvlQZC3zDuHLsDt8FjlPo2RwcOozshqdsNINLortyJw8NlaW0foFbc4n/TS69PqRc+n1L31AXOOqjb1iu/vDRB5Mc5ToP6xI1CDBQD8d3VGa9/akMdLPkZJvwsN6LDxAPf0D1J9Qsl+hH+VCHNMqLk+j1kF5Y90QK3xsD1+D6fhiOr+jdJPd5tsojf9XI0mUXGbpc7yt2qnNhZgUnl17jdF37fih0s9Tn7Pd+PInnhAEGBxMAb0mGJgcQe356C+YvobpX2ZJtUuXaPJ32HyKXn4/bMIVd9KQiVKVI9FHiZqji3Hi75+vHvfYVj7Vys3yt5sS7RaCGMrhWlvPCh7PE4/XrAxdbHPUHJm9Spr/NSnBMgBsPU33JmngTUVoL+VdrPH7R0NWzIIp+2XKNbTrHsX/XlDiEqw4WPEZWvEKFWWw5GDJwZJnb8khow4WHCx4jhb8oSriFBVFMOFgwsGEZ2nC9FMzwYqDFQcrnpsVg27NCKYdTDuY9rxNmzwvHSw6WHSw6HlbNP/Gl2DZwbKDZc/bsukz2sGmg00Hm563Tffv8bjPkjBfFow6GPU8jTpMdwfzDeY7S/O9SWuDeY7WYe9IsOFgwzO14fIyS+tMel2GPDoYcTDimRvxCu32Sa2DEJGDMQdjnrsxByMORhyMeJ5G/PBWlGh3id/3zfIYFcGQgyEHQ56tIYfRcTDhYMKzNOEWFvhW2HQTUupgxsGM52nGPYQ9pnGYrw6mHEx5nqZ8F73hS7yuc/QXStfhxGOw5GDJs7bkL9kGJcGMgxkHM56nGefxGt2jbZU0wgRLDpYcLHmmlpytq7y5I/cBH5BA25BeB2sO1jxTa64wtgt0neW7YMbBjIMZz9KM2+OKKA8mHEw4mPBMTbgdGuM56ypMWgdbDrY8W1t+QGkR4z4N54+DHQc7nr8d36G8wC+pBXsO9hzsebb2vEL5Lk4bQT6iaJPEaTjHGKw5WPPsrPkOpZvmlq5o0+wMad8eXYgdP2RVvkb6qj/Q2X1v+jJHuFkXJQdsAKGO5AqpBuG2OwT3pquxA90QjYExu8A5WvxfK6Hmpmjic/J28RrFDd0QP31T3H5N4m1U9iBhwsd2QL0prlJcejNEqLs8zvKms8yD4WMVH2WoGrTHDQSeY5SHqDjbqLj04WpwN8HdBHfjjbtZoR9Scf73QtzOn1FS2fE77rGri7B5g3dIOr6Kim817A7H702w2rF4YjHLh3ZXFae8GuP9uvT0eaIcBBpCej0JeqQj9ORjEW2NMh7D7mzqm3efnppg1rEH+rF6933o3qV07+kyMvEF/EZ5xJEvtMPF9Rv1PiWAruZ7xIMwoGiVnlhSZi7QIa6wv7xggg+t3uZy6EtghBAvu0a+DGQgGEU+LkosP6o3HDQSgZaMIVWzh8hJc5sSYRaegrKNMUqk80EZr+FDJGX5TRfxjBLgEPLOIeQNHgYPh8nwodNMcOLhAOuiKLJ13FSo1OU99mbsfBsFmqt08xO+CuufPzcfuyY+oOT5b+0PX6qkjPdJvK7F+efP7xmlnRgoRCF4K8uS1f5fTLU1HlGOp3yjpB5MYeK6W1jwxuk63kdJv4lUIeA8Ne6TIzv6y0e0RymegAZqAiICd66VlelYNWWDKv38+q6HJTnELrY5ak6EXyXN/3A3jokrXv0EQ36BWSOI26QFwKa3zBEA4wVgqFUrf6DS8V8zd59b7mgZkk4zdTxOBVGXsqwTfBn3+0C8qVoLEYHb7ZOBsDcre/iINoDGceEiQAaLPbqlt+lHlKAS/YQ3NONV2suoWEcbNlmtM8TNfGHbU8lMwKpachgDot1d8t1Z4h5M+cocgsy//+1vMsdISkLwpD8tAD9Uk0C+jemb6aJrvn6JXxHeFNfAxnLqrkAKVTsZnulv807BqNbMLF2nUGItUw/4GIAPH7Jzch5L2go7/apADDkHSoYz4oubhNugFwenL8JJX0GFlJBTO5U7lMfZ5kk2eT24ex2l0kQLeCA+fHGU5uj2vB0f1TUKlhf3RPQEaGNOTk6Kj5FDlwYsvEtsOmiMMwEZQOF9NvP0ASVZui1WmRAHxC60fi+SH4ySF25gcwQI8W46N8Dg77oX1HXshskQ8aEq4hQVxdjrWv16CUbkh1n7CKIp84obBCxGCRsBEN7HDKH0Q7vRw7Ch3VWjho2ecNO5iDz7htLPcfrtpnkgMk/xTZ/dsuVT+/X4920eb2PxfAlDT3Q156uGX5GJSSJUXtIJzNh6xnBD0oaCAMjr3emWhlpxmKYU92if5eWT6LPYiUn5cUAjLjrKPI3fGFeoaBaAv4twszs8TYbzw6UXY29sZIL56cdZ52P8S0QEdfmTnB9hMEpiHgDgUTKOBb7Pvj8Jrr8x7DVF/t1VyrBqfnPS/1r9YgEDuCWQqg5yTd7/N+VNWsex54iOX8Sw6VSGHDn1ftfzA+OiQNjI6YHQE21yLIycDIyLgTEjAbTz/coEMARGSwRC5/uQBfS8z9WPl/hrXLoLCE4GrGwDRAIdPwMyljkEGU7TzGudBmojxpvBOJmZIzJEhz8BiQOXUWJTAMp8gtdB8LFnsoiKSXiQX+aNDKItM/MeBDTGcRwBFP56ipOTewJkt2Y9qVx71s6Zbc1+aPeZvZgCq27yGZA+QKbJSkfGxATpxdxCSA8SY2eeAQxehg7JfYoDt7v6iYvxd7xq4oN6fGvy3UsnqOjtWrK8wMIVSbh7w3n6Me68GL9pkIrnuBfp2ELc4GXuQ5oewX7tO9IDtR/7jdhtneMenx+4LXRmeZbZzjR/Um8WLWMdow84mUtW3h0l0NiLq7X5fxY40drqPwlWJM+5jI0UdqHDElR8XdmeIchM17Q7EacH2ahzh+OfZRpvokgDc/7kLUcYjDRfGADgX0Iy1RxhOA/v39TgERTtIHyUzPRAhnmMiYZx04ReG+GTINPjQJA82xtYeHj+eZKDqVpoPEo2GUCOb9l1YhdPD1mVS2DSERD9ePwNHjbo9z057Byj4yD0CJiQPmYqqFL6HuI0yFhF+RZZiiV+Y2PMkGICjuknN2h0NLfHTeQ82IsG+QUW5kbgdwp650s6tAAdivZFkvNAzuh3QxrjR/Vi1KQout2Xt1U5oed5rwTQ+2X6Hmb6eU7Op4ONHy5oOgh54YRgQPLMC4044a7hvGY226rjwfyZbT9AYJTJ9tD5vsy092d228cZP6LnqO6B+sNjSq8YCibdm4Kiiff2o9bEGiOUkLnLhxmZRowAH7ZtkErJLvMISyPGEz8wM5abMcOJP9GGhcoocSeAZK5RyeVCMN1CKxuO/IDa2KvKhpDzYXmZxZyNgLVgbPntxrwJbzgle8KdvsUP7/WnaybJrad9qGqKnFp/Oojpvun27q+zNNu9PZQ5ig7bs++iN/xK6HUmdk62X9YkxCD3UJBfFvCuJtkiSIV0t3iClmbzb0CLb2ihu8UTtIw4VJ8WH6MdB9JGhj/DcxIaowzNAyj4FfowHKfgIM3hRkpjp4XLFGmsAXQoKf0ZDk00L6wNwpl5FyNY+hN1GJiMPiccAOJpBGKhMef54KlgNuVsMBxuvk0GN3hTnDkaazUckzNnkSZAzxTr4ce2Q+qd+IwSLfeky+FHAaSoWdpSwalN886C+svjbvzPSBFvWgj64L10F+G9xODI6XhwXBCk+JWd4zZNGuzqX+WQaQosCzG4STOPdBg20ziZABhxvV56mCYgsU2w3cdnmRqBkTFZ0MP0nmFxFpvFpsea/wmVVyGxhlWcbl0N+4C7xLpzBYodY2SpxYzhxG3UncycdAnueLyrDuN13jfOGq4jjzb+6bEpgKd1kozfq5OjTTFrrtGRijnyjoqZGncLi/HPqs9l/rumf463Y84BtDUSLA4/zTqR6Roxr5F91/2jjOVDx3sxQj90+dzW5cHwsfe08djL8BpImhI+ZbQu71BeZOnIz1kQddNI6H+Zuz/ptWV28aSHjrGerwi44FfoQ7jp+9AnSROGd2cDEuczc+AwaAld+r1ucUIOVB9p85MB7WNURrVwa1Tgmbh7tI0xO1zgHkWbL9kGJRPdUg6QjKgHVH4R+w4hLdWdvfMRgHVj6/LxNsVHyU5wVMy6jIAbRw5TWxXQdoionViDLXS6MxKBOmYw7wTx1u2tmld1feWbgZEAMbVMTy5p74z8eh8BU0O1RI1DvNi8xkWWjzljyhWAhzO6xKyHO/w2zWs4zIfOKLOtATR6oPFurMxtCuwqGvCoxd2Q2S/4TTSuMYGhLyOZe1Tsazbx13F3CFNVM4ghvs3eVfVbM7/I1ofIaDEtgENUpZcRrNeIWcWuaWE2RbzShpsPkep0h9TtK8pfY/T9NH1ADkIvtjlCeJpE9vyxkJngvi1OuZEeSRZKIGg1tAFCcsdXgLGaHAH2BnqYwdSazCbIZ0iWbQmyCzShRGeGev0bOD3G+jSLfQ5MZ6ZJxVCYe59gkMsvC/WmgPU6Daoz8afzXZeT4R20Hqd9R+34icHEfnjce2+HGocXS3BSVDYZyz1KGoKFeuGDBGRjoXLTVGfihQXNn4UX7p9l7Npzka9f4ld0h/I424A3EXFZiZAvLzoS+MFNVwsvonP/muVENgDXwVytALJx6BxMQncrkjmTczIWWxuXfLSc5j2D52iNzstQ2GarBefRnJMZcNo/V9Q/FnitvPfhvNAvbr66ATLac7IGiR7mahXdLQXnZQt0o9VisxTnhHum9XNF+/RrQo6sZ7YrQ4Px7sniEDda1COHM843BK2HpBtC0nPyumI1zNb9mh1/XIQ9wNZPdQjPyRZmvZDKac8DSou4jF8Rnmf6jF5Rcl7WIGm/ugVS4nOyCpki5moZ2rsMjB7HnnOSrr83b/os3YvNA8SZhIkeOxj71pgpbm+e2Qmmz/EzunxbJ2iVR+tvdc599Vozfrrd4zJR0m9ZV+sadoe93gkWMX74AhLcRUUWMUsgaBxodkDWib4irrn5vPiUJRuUu5unCqBzDTpRP/qGO+fXNfqGpbGC4gAMefOmwfjP+4QUyaNzvA9lQbou1OTw87s1WNAQQixhmUVENFHrdFdZprvZkZAC9xsIeU1BEfraj/NwVIzcPjotLNhkAHm8+ZJtqgRdVkWZ7RwN9RXJDlcGkim/xKyDG79N85oIOMiONo83f2Qb69fdqC6vpqonLzxmPs4aLkxzZo6U0S44DxiR1+lDzsyg4zFWOkf7AcTV6xs+INA42EwByVZWz3KisRxWyIb0AOqD/xIgZm4jfr+gN/ZofwAEfZiqxpb6R1bGz/G6hR/0HmuXN4KrfB0lM+M7yY8LvO6baSSkTrHI0800MfAT3dUw5MKLGcBp3CsqjOBzU647Eb2Ci3CPzvDNS7PAzch7lAyh05PSI/SMuDfJB7CMlpWbYMSfSScGJv0/7lGtgli2bxgIFTepeECZvE5uV/qDtFH2AASQKOr0Ym6AgcbspgU8gNnokwFGcPNhHoBM0borjB6qfd0jEl/kYkOkYbI+U8ToJ/BU30yGmE6OFSrKz5mbhFqBFI4EBEvu91mHM16L5pVc81Az1hpJwMucMiBuRBK3xG4/ex2jTHt1qlDVF3Ryx1N31ZjzPr1quRjkbIucqY+BbpT0LxZhSIwy8g5gmE+gke16NujHWQSUkfY6mweSKfc8kzA5LNfJrj93cGL+UC3kqZ1xXtYZ/Yw8v3mgqvsUnuDo6keJcnyG8XBY1jqg3D3bx8hOCMX5ugwIsg3TBt90a6CUGN1fSsxx4TbFxTajx0a+itwgy9ylTY6ny6hE2yyPUTHyJCArABci/c+zzrA5DZrXqIuDmLEmAANWZjooUzXEZh97PVIz7NHJ4tJJTk+QNOLU37RIGdvHwLHhXyhqofGlZgTYfOxiK2kY2Nsb2PsythplRjn4GH6F/qUws9u/FfbhKCDm37YtwYyUvSk7r3Njw3m5sXFzFM8b0BT7mmH8NUFTnKIhL73Nt49pXCpqIEstJf0RNRCGqWMfepYLNXczTjHqairmYqj7soiMqG3LPEddLTTaTM3+KqrTnGgacE3mlOAoa3vTK2iNNAIL/sa/EZjkcdm6VWNGJbkkwGsS2qKzxpGicfMKZAp4jeJ+ArCsAcsHj3WxeY3XCCvtHiXt6Qidlo0BDNUhC6YF5BZJzueRL2gBA2LoXli2qZBa5YJPmFod5ufHjp1kzYI1kQW4MKox84qFFDxGSr0DMAQ1+hDLemKPPwlEVC2CxiIGZmRrZus1YJNBmjd/OZsGmhpe494XZgKyyWeCeMgaLyAFtzOLmCQdQhnnF2fgdsYaRJkAzZdxUoMwG4nOQtHks7Oa9mAyOwskszwbLmsmszrjOyDDWRxSUL+Q1C3lyHHUK8Rd1JozhkQK8AxBJzF9ws+Yl2d4gpjRbk8wQ4o/43kOXMa5WCMAZT4jsJNbm2RfmE5EmxkstCObP56DgMW4G3cCIDz1EJAZGoM+XPTewPHmZXQ3hE08K9PHlMdzMmEzoXezMeSO+geUFnEZvyK8T+MzekWJgyugnIKrqZNthlg+XtllbXAWNVNnnD7xgQtC+rFvuWQqJ597Z7/O2n+x7ZlXrs1CZZSEO4BkXvk3J95Jb8Uc2L9eny01683Rz5YyYnoCotroaqc37lWZ4VipVA3aqc104aodLBwmlK/zbCfUorfJN9kI0jNSn5aBPKpVkBqpnvUFcGPm0ROjZLTkSB8cHqXPJDzGyZ0DMEQ1+pAyU5A4/OMmLVH+HEnuY7kpT2XIENX7XStPnhopfcn9BAzTO77AZpU5zWt8xoz/yQnROZMh5iDydY7+qlC6fht7po8rAMFRUGLWYYnfpnmlLXzojJK9BNDogcbDlKZxe8eWCKFiqac9z3HMe3b8uEV2nAfHIp4OH9GmF1Fli6i+Hfrz547eaQ4BmlzQe6SdHoArtNvXBjT6U4B8CQT4IYvMOg4KGjWv7EkAn5GPlQbgzCiD6oU8uh2AYDewq8EXzgODqvWQpd2l1sAEqo0W0wMUTRivJBhclJuZdVyaIh4FYMwj7sj27Rh3p/8xxvPYMuUGncs8LuN1lNSaHzuwUFUTvJhvs/YgdGvmFVtoiIwSXAI4ZFX6Fl9OTRAiYkCHehpgTDpu5AhzktAHmIivNC2eHrIql26Q0J79hQBGLJGgGhnBoiZ3JQ3Vm+md8u0REPJWUb5F4ssGgRCBA2MpyByKEE+QKib3ArnMa1YWV8iauEq3z8oi2cD3xWbpOw3fHSvXPjnKsR9tnyZzG3/maGZDvh4ixnuUPWDBsxHe7R7/gf1auhl7coium3wGlfk4a2gwzZmXs2BgMsoEUQCIok4vPQggjR3UsZ4GGaMOHDng9ET0Iu9w+FC2hwAZ/Z1rPXD48cj1ERx3EeZpeSQMQQXmM9Uy5ri4aFoKqbHti8lQcRe97WpOeGvzFAdhONUT/LjfZ52M8Fo0r4SVB5lRctYAljklrzyYAPJXC53saRZr2pnj5iqUlFPD50u2QclEUelYNw+AvY9LcDGn5swyGJ1gMmYkCgAR1elRADpBAx59zDrW77ij14GTBJ1GxOnwksdrdI+2VXsudPSgw1ZPoo/3fd6ehdOimUUfDmTGCUABLHOKRByYQILR8E72NSQZdubIUYmUckL4ZOsqRzhCPuDNVWg7/jwdXwQKjoIyM/c7/FbNLVDxITRSsArg0QePD4Grv2bENkUSuKx1uLcBzLxjxw5ijKTTeaEqX79EBbrO8t3oEYyqmwQj83HeboduzsyCFQ2TcaJUAIi8Tt8CUq8N4kg0pFN9jT0mnTdy0OmJ6ANWBIcK7B258BQqhocqRsXKUTY/gFLsa27x1wT1N23hBx9Au+iagqKddO3HWQBH3nhPcCPsKh+Q9FDt606RJCxGmy9nABcPoXLoi8lwsUL5Lk6bXz6iaJPE6ej3JgpEIHgKy8w62RW1al6DIhGERhkbBfCYgMeHAZMINoDlJ4ud7mnYGtK540YwjqSTQYo88v8hKuKiHuet8igt6jragzBjRjaIPJLLJkQEs3ZboCbOKwCCYDdKNAyAcwg4H4Km5FITumXAi28cgUQRV61fvuPk7psBYLEKWu27b2jBfcRr71OWK+8JG/W2JjEX4dQIlGSBNzYBmw6RxMc7m+AQVlw4Zv1M89xgOvZcnEVg9gl8gSL+qz/VPPHwhiuOBHyC8gvKNfktnPPYhg+5CYY2AWz2wOb5uIZqGDBDdAKQRQxqzIEy7ZiGktuXKExgVeNST+tgWfqln9MOcsz2q/g/nrnMqrTM36ZOHgkxJAZAlVtQ/CZbNuckkYTUBMlhAJM+mDxPAm/SAuHDAm3DYlQ8VI3AqwwTHaY5ZzKJaIZWMIcFRl8zTSwjQpvYgdbTB1bc5blagj7iZmIKZBT30RbGvdLe18H9NAmGdgDwNVklEDXWlfgBS4Ow5HmuOs0Fx75iyp9Fv/lciCxZuHxFeRFvX/DjSEh1W7KD4Y6T+UVgc6EL2STNWY2GyLZDRJn4kmeyKUfxp56OpASRII8puaDATLdtznkeDa0JpiUDqExB5XvCRzZpLnsZTdGpweOsgu9wnM9sMpLBvda0ozV3eM7oN0HZbAyAjtk+2sDU93f4Ouyf5H6PgZFh+vs+JEB7qL5S283nkWX0J1TeG+xFf39mWQTZ9gVmDSyQ/Tw34RNY/ZlE1Yenj0cnSEC+FSXaPRbRFs3Fqd6UPaGBNVM0Z+VUybYv0an2Mazwp2LwSCGyLKTqI8IjcBIUPuLxHo/aujnWBS9PNc0ECtuVPSu327YZPsPrOZJHXS3wEWfT7w/RRZSvawYtrHBrDdxjQwZEQ1M0uEmIRmcCbMzJW0TbWKQ/U3TOyblOurCPKx958y8mYV6I5/GZGRaO7YLU5c/WjgYBY23WDX3vSTZ1FxXF9yzf3KMClfforwoV5bhvL7P1U6+w8grMGiTcJs3LWXBhM9JbzAEwYMB462G8TWkDvDTgNakLeiiytn7MrnzzF1KUoIQYzLdZA4luDRRD0822X2xe4zV6qJmNPPg5VUxw6v88ayj0GjKvzKaHiLEGQwEL3iUtrchPIsmZzuN03EjRZSrwdI30Dz5t8amRM+IQGozAWbqNWYaPcYbCoeN9ihX3aB2jfVzzFN9P6EewwP14jxJ2Vwjv8yKCB9GkOQSRsozWL2jj5siuKh0lKicBQn2at5shGzOzOEMiZLShSsCGqEYfQtEnlOxX6MfYkxmHagk+px9njYRjM+blH45IGMszBAx45Ad+ryvI+mdEGpbP8baa5Jo3lTgEf3XhWWNJ2bx5+Rkl0sbyPwFjljE2Cz/m8lo4JyPwOcB07IORduDqwx1zSrz+GTfvbFxmSbVLxfNETlHiEtltwxSycgs5QbIVZNlAN6/JkLpVDZgO6Z+vHvebqESf4qLM8rebEu3Gzio5IpBg4xaYd2TnNWlmGSMPOaNliQEzcMz4kAF+ztZRcrHNEdrVDK+S5n+4v0Z2NkI5CMaSUrOGkLhd8/I9YjSN5YACjsxx5Lc/mt1Q1E8ojj34HAhJH0adbRPy9Uv8ivC/J5jh5YnAgRFdYAHOjGrSHOMhhZxxQ2HAzMxiH42WeYY9P2A3TbAzgZ9vcW6FitKDWNcXQwgistBi/BfRrPnGPQJJU8S+gKEZx0ESPXOOhb7AcMqYqA9H7+LiVFOjp+rF4FnKBFavOTOOe+NPewaMCOv0Lq7NeEpzWphNGr/mN2/5oSriFBXFVIGrXz8LF/Lr/N0S0Z4Zxi4CLaMGr4ATaaXexC8SIbMMYJNDbZIQpg85b2LYZR6Xcf3/ug+mCmOUCCxsmALzd1J0k2YYz2jkjBrSAmZmFtsYtMwyvHkCu0mCnBH8vIlz5C3XH6IiLq6zfJVHaVFXNMllBWC5WJjBqObv8kDtnGHsBKFx1IAacDgKDr2JxzAEzjJIzw7Kk4Rze5D2NMZfZlVa5m++hHZCHBX8qMJLc6Bk82Yfv0mkTRi2A8aGYMzT2EyhawEh2TuYehCADeDqadzFf92jYl9zxvcF+BJ/uWKpwCcgWpqv5Ddz9nGZj8QJ43PAoAsMehq3BehbQPz2HsYexPMBcPY0rt++orzAL0L6EtEpgVQAZIovzYPSDZx9/KYRN2HkDlgbjjVP4zSDsgVEaC/h6kFUNoKtp/GYfq98+oAsfZMeVH5pbtLoTXmvYzKDugmDcsCbFbx5GpdZpC0gMHsKWQ9Csxl0vYrNU22gPtTNB9NStr8e2zLTGDr+JumAC79j3Yw3Qk8Grcki1Qz3PN+kJcqfo/VkNysQArBQoT7P3xWRDZphnCIRM2qwClhR1epN7KJQMssA5gHcJgllBrDzJ56VNZuay7qcar6TlIADG+r7AtwU2aI5xjQSNeMGtYCXOcU1CinzDGw+QG6a0GYAPQ9j2wrt9klUTjdo40oiAxJZbkk+jGjZrGMfgaqJYmDAkzaePIyNJJJmHiM9guTEMVMfmj7GzuljpgpIy/Np84+NU8bEgBdRtT7GvkXEvOkgN3WMm2Nse3grSrS7rEPzNstjVEwT32gpeABiyyzBbzGtmmWsY1A0crwL+NHCj0exj0XOTOOfRxCcKA6aQdG7WDjd6t+pfjF4lrOS02vPjGPeFKt+ASeSSr2LbbNe7ZsYapNGshmu87UHD69+lHVtU81W0jKwwGFLzN9PMW2aYUxj0DNqXAu4md/cJYuYWcY5b6A3Sbwzg6A/Ma8nyWMaT7Z7kycHB0jcUgvwY7x2zTEG8tA0bhwMODLBkT8xkYugecZF36A4TXw0hqQ3MfIuetvV7K5z9BdK15O9xcURg4UTt9D8HRuvWTOMjzwkjRoeA4b0MeRNbOSiZ5ah0TMYThIYjeHoW1z8km1QMnFQPMoghFGvxGJc2alN842FJ/RMEQgDbuYX/3qImXPwmx56U4Y9TQj6E/PyeI3u0bZKmk+ThT1WDA6MeIUW4MQ4zZpj/OMgadwQGDCkjSF/YiEPPfMMh37BcJqgaApHj+Jitq5yhEP7A74pFG2nmyfli8IDlaDgEvwbv2mzjJN8ZI0cKwOmhmDKo7gpQNNMY6eXsJwohg6Apz9xtMrXL1GBrrN8N1kApWTgwIkpsQD3RrdpjrGSRs+4QTLgZn7xkEHMPAOhL9CbJvQZQdCbmNc+L4HyqeJdv34WOOTX+fsroj0zjHEEWkaNbwEn0kq9iWkkQmYZzyaH2iRxTB9yHsWwduoWb+epptwlyhWEByFusSW4LV7DZhnneIgaOeAFLJlhyaNYyEXRTIOid3CcKEwaw9KbePmA0iIu41c05eN8jBAsmDhF5u/X2EbNMD6yCBo1NgbszPJtPw5qZhkLPYLfJDHQEIb+xb87lBdZOu0jtUJhJKBiiy7ItzGNm3N8ZBA2TZwM2BqALf/iJ4uqecdR/+A5bVw1g6k38XWF8l2cNj9/RNEmidPJHm0SiMICTFhw/t5P1LQZxlURskaNqgFTwzDlTTwVommW0dRTWE4SSQfB04c4OuG2HOHy94I2Wcx4H84kW3ACJjyNYwQaOr5r+gGDoR2pAMfh1unHItqSTKkvTuCh3W0DYUK2CVIh0UeTIcWXSU/YoH+p01FLmeWcfoIz4GjeM5piBAHCmOXOBwY4bmxzBKRhHWwpxoHqEnfkZNhaoR+l7bAmAwiuj2DQ/jBrD9M0YV5Bqel2a/EndLignvGjx1VNU77h10prCpR3clxmG3Qd50WJHc7XqEBMf2OqB1R25S82r/G69v3t773OO3x4WL+gXfTPnzdfs7pzo69Jj4iBAo937QpLIf/2o7gO/L1QVtQilami/ZnHvP2i4Io1iM9wo6KI0207YMmbbriPty+8NikpeLIoiNStFzPQElFXOrVgp7d0OYL0P/Iq7n8H13OxzVFz4P4qaf6H6yuklQso5BIJiFTmwKHiGQa3GNdEjMToXsPqtuxyBKAL8Komy0CgQEx6cDqE+M5XP1FEpex8/VKnX3jiW9BMpgRXxWQhQCe3BHXaF2cbca2H75I6D0UUFZIrK0x95GdedWQJYD9KulDee8oaPlS1o6m9jcA6yM+8mvol1P2F38nJU7yFvRtfcerklOFVzBRT1/4hz76h9HOcfrtJIZIoynPVISOBSsgS3qN9lvP8uopALKOIRk+NN2nN5TlSqq9XTqW2Y1GIn5PVT3zlW0mvACDs32ffBTG++SIK6M1HAHuBDZ4+iSqA2V6vtVc/XuKvMT9PYAvxra/7qKr0wE3QOOo7t5f6RdTNXEXFtxrTnLqOX3i1HD9qBAD8nokiCLRFVIGgLaVRsygl5pRR1Q1Me6/WWZrt3h7KHEW8eER952KGLKKpaEiTe+UgKgc2nf9Ej1qQphhIjrqkZlJXs8CUoASPLKtM9vrF1VLVSfpzvOWIcPjAq+/wTc27rPP/dlKPX0X/u6CmU5Ehg7t7FG2aS6v1BqInKs3B6IFwkMw1ri7qX7cpHq8YtkDEQ7M9fDbg1pWo2ZuEpymKjDf7ICgnkZIsCpPkHhX7GkfxV64HYEoIM4JTIZ1x/e0ryl9j9F3Wk9LS8nE2QzBINhILx8GznshCJpotEfAZ1ED1IBtKqtkYgtqoCWC/oEELbISpH5DoQznFokGr2RWDJmZg5iwnUEdzE6Pm0BPTJNoSi6jB4vMZGLbFLMqbswK30ko+wOV8HERpt5BHCW4QS2wo/2OBl/Z6H7TbIeMAbo+YiWG7umGndmtYOnAbaFLjHqkhOqxDhAw0+kPAw9QVa0RGHXK4mzaPjxxuxCnpz+gVJdpNkrIAN0vCRd20z/EzunxbJ2hVx+BvdYdfvfITSVFBnpj8soD1nLIgd+ejpgBvYUdUkrvCwy0cA9K7Pplgko0topqVgE21Pd7UPVgl6LIqymwnXhURlOMuFfOKAmYhuuJo83jzR7bhKYEtwp0voErBVsP/yMr4ORaufbFFRKvk/VLg1a8VKkr1yhtZSrIS1i8Il0Gwutr/KqsTOIN9SMThYy+toZb2yKotfolvm8/yWLD4zRaS+c1+OWD9oqlR6rusVuBU6LE4fwqU/CytDzTl2e5KwYYhGd3xCom3uPTLDZ1b055IM5k10zELYbeQBeRGoF2pEH1UCUW1eghsTJRNK1RpDY9CmcWwRIA8gb19h80Q2DLc3IAupq5dcAceI4GgHE8KblEdnKzQbl+zEK4ECgrKUdMvqyWMUghI5aBKL/O689ZR0tXES03oEtzMhCwESAz3uLvwMn+6ESWGTBFuYkiVUlfNfbqbqZ1biicApyBYht4jqiIBekUktR9LAarmvVbH1s4rxRWALQiRQfDiD0cOQUm+LNzCAHmY9xdYQZgiXAmoUoAdAaLD5owEwpLcHQP8wrpJxYeoiIu6MfU4NC2eUd5amzK1EJGpEww+pa7Y1DIWUGoBlVpoLqGuzJdZVTvuN6CsVGm1jATBkNwSz5oUOB2qi+glmRSlXrZJEOvKfyQGapcpr5aVIoGEgKL4nuWbGjiovMdpS8FLVPnF+KGAV1KVCRZZeyRFPFNEl+BmgUQhyPDwoiyjmtFG2CN0Ae6oiSijrvQTSvbtSRSmutMnXkWHr+oqfq/zkKw/W9Wc5XiOt5VwH76ahCeSigoo6mWWVLsUJCK3qFA0TmmASJ+vHveb2sI/1Yaf5W83/P3F/GJcUTglAZO6+I4U4B59SVnu1K6oOFQq5WZ2fjGxLLrb2vtUitk9cVGVOHrzfASlrJtUM350KWDVio3qnDLCyvW2rDck6jEcv5hQBu3RXENlmDlq0AoFtpNDclipkjI1CVBmzfSMwwGa88JJgaIbZr8cTuo0DUIEFFs7YePwAMy5gqiAIuvPvh6ZyByDfIKPKAKsUbWxnldIWLfmFvuWRjXrzC0lFkFz/pkiUkwuSksDZNKbZqSJYTKBZdGRAbBAJSwpkUV7qYqgkwNGtYTEFAPWDpgPFZQTSqE/M9qSwQ4USMqKJTI6WtCQwiZtxUWFMhlN3/YpZXO4gnIqYTRmc1sy0JSuuKhYHpPJ3Y4SOsMrLy4RzXCut6VWT/gKyokF0p767d5L6t8rx5eCLCOUoF8MXDtsKU5WWCKP0aKc6H0QvlDAZUp+WV1h2HuSFEKxBGrhaBqgkPCFBHlxoYDGSwp3dQBqstduU107IcOb6xQU5M52cstCFp+l9qY2NT0r04GOJmoGAEYwByqe/2y/wA63Su4FYEpIDrseCoEP1aq2XfGLASQAbrjiUb0HyvEeLkid1t1WOhehaN0JAyOT7zwYck+MZAFIfrkFlFBz1alHO0T4IUt9YD56TXO0PDhs4U2D05DWas/9wBDCs3YwpTkweRexQcVXOU0wpZ74Ctfau+YMtN0RdyXnPsOfenzUWyAFTAjJGt2St+Qddc2/SoygAF4j1jBTlqV09o5UGkChvFUomBaBlDZVJ1uNazjwC7hRUv8ORah6hPcuLkkx/duEgHoR3WZrv5EER+BFcQ1z3dve9JV5quHp8B1tBJWxetWghihE0PYZqZM8+dxTyqktrBbVRK6Uxz8j3nCgPw03W3K5H+jvlURWPRp/i0Nr5/Q36wpR+XZJ8fkqgcjHnhj+PJcjI3DSLMrgOHlrZ3OyuyGN8dEe7n+iuAvxwS1uvTk81ZLXTfYVK7hFcqhKdDyIkMSB6YyuCJjn4BSeZ+MPyHz6gJIs3RarTOYoeqXEwvPmeBrZZReTcg2Ja0MWGt3fngVDvoLCZt/ztqE1lOQHu0pQoF5Ydo4NP4GZ4CtDfb+g5QaMC3zZ3bFP7dfj37d5vI25eYMJG3GjhffkNq3nfJVhCHL/btsn8pKWVC26AvdJ9Fmsbn1WKjWpLgHu6UlcdBadcVhUg08vjuDo6UXE44ShJT93bIbCuXPLza2h99n3pxNLfiOJMpbEZSh7NzgfCXnXM5s3k7hTWtzSfjFZxGHut+6CjvDi6gmaDDZbfmHbYHbfYIDJ0sXm00j2BnAVphUU7uAtvtGcZiO6rtyKekD4B9HZRIknylHYioJi9grpb6wHAkVBYlUlvEMErTbIL5YVoQKFsPBMG3+C1hPUkz6BHKhZE4Y64YEq0PWX4znKkRQA94ljOMOxGk3MLypa3S/rdi5zDDVwX7cxm9BRkbtLtqSv/jDzBPbVp5hhOVaI6zefqKHY+DRJM67S2ZlDkNuGkNn0YwOnJ60oRuHO5QTzVsZxEh42Vyorbmne3ReFsMMJuUZ45V2oZJphYddIYOYnLG03A3K7mnNshjLb45SbZ0OVGR6v4JyXqo8tuovwo9LSRndF3Nh0WwhX6LypPW8pae2p1DhLi657ujsmdNxtVDw9ZFXOV4KwrFh86tHCRnrBi4Q8Om7rmW8OlLCK8i3i4l5Y1oUBTKuG9oSFBiBIAueoYHe88Qu4UgwcJCSBGilD9vL5paT2yKE2hkiycZD0Xqkl9rSUZTXpIookGx9X46oMlGWLC9vMPTVwN6DBigybV2w+jWTe6n36iJ6jKim7d1p5LVbSwJLu/vvGTOLNe7NYyIk9e8f56kBVIFOAkNnEiw+KUZiMnGBxylAMXBUULkewPqgHbjcLMxXs4mrPmaAtPqNGHqeWq0NCOYbrHe/oDvGmezete7jvK+NPh8spZI0acgCQ+359O9EgfZZ+qEqa6VQtlTAUS1MJbCFJQWJ13WQiRagWjoSFF9F4xqEpNUBTjOFKx1MPEz+0k1cBlauArK1YG0rRSFyZ8stShEbSyhKMlbNOohrxaoyo6NjjYVyYWa0ZQTWGo2IZqUujkqf8vRKOFNU6D7h2uvJToMkPVYH98niTChMrp5bH0N74lE7VlCVIrqWmgBsl6QKIplmkYhoraZlDbaop7bhpvhobeLqKKr1M31O3LU63oDSoLTn61FS3HKGYpiJL2Vs1qt1G7VUh41AVyRiKG2cpTZw6UyWcrTUzabG9RrYvpcHCsbCsTV/RVkLQHH6y1VhFWOWUmlsDFeNgXjGXo1/HTS6jddneRg7GsZTEcm+f6qI10P9iWRFqjAsKz7PxfSg+UczlsZ4qbb0xw03J8FS+4Bbfw8sFSiehzcOlBwEIw5z9V5Z3qeZa6pok3qZ4xeqkMHEuYcxrUqVB6+M3AVq7iHoUO2k3EraCmtoJwcNEgUBNzdeGyjoA1b9fbF7jIsu1blVXktoMadw6eWqjSzhSFODeFTnRMpRDRHRuJcr9KSKyEcLaRGjqPZ+qcWGRlMg2mnq1MWohvllXCORCI0Hx+SqBsYcee5gBEQSuTWc8xZy2D+FHXF5j9P0U3Mk4ebxcXnFnvgYf2cyhkJ1g9xOnnHRmUkgnkBZarZDcaVfRD8DodRBF7WW3yLY5QomcdoH6RCyQ1qVzcdCBltVIjom0oUyTe4VlwGBRg8ppN6gGh2BaiIJMNrT6j2TyrRFtJNPkXiH5QCd5akWDytqB9XYJsauOuKAfMlNlwAW69qnoF3lR8AqrVGR1lSI6N90DmV7S7CsNll52nO5EljkTN116vE7GuAfFHLzsMFZcdXU8GjfdUY/BNx/eeh+Mu0XNycvuEYutrlZG66a7ur0Pxp0koveya2hh1ZWxFG66QWdEByd3O6hz1I32HFEdiez4IQUjL7EulBrihYSkjtCvvb5rwsbLboINz3UI3XTRA0qLuKwTdZzpfUavKDHuJgArL7tKIre6Ximx65iinleBkwOVZni3jU9RhViN0T5hMeLJCpd7nz7Hz+jybZ2gVR6tv9Vx4eq1NtCn2z0uFiXEBQmye/uM+LjMX/gCEbxERVwrtdmuX3zKkg3KVemgKaszU63IYmXFbZrrlCohvJLGIahRDj+59F0PZdHneLNBTVXKIRaIzqUBCQQgmAnL2MWL6EE1thBMIcw7IuxHD5DzeFMnEVWCLquizHZaOQCU1KZBceskWfBLDN8m3/FDm8ebP+q8C3hkQE1lUz10deR2c+ajfaWojg/Iyi9KEY8xF4YAlfApnZvEpOrjuxIFmNREy/A8gnYqQjuAymVgn1BddU/+kZXxc7xu2yzb9s7Rmwa5fJehux35tIwMksmP9lXa30QCUGGvuKv9Kh6ohJj5AWmlT+F2tmly9cAySjWVVZc+tVL6f9yjdbyPBbPLQMpFKUcV/WXll6UIVaSXEjgN8iOrhvB3T91+qodqv09iPkjkBKMtGsOdtoFSulatUFF+znS8LYzQpilxaiQYcL87UZDCuahI5q8UrmWQdQDNiSBy2syJDQz87LScwAV26KlG4nerCgAajsvHpsdpNB/rgjlicWGrzZjIAMjWHYZj0jcY6aKu19IPNUGOMblVj97rnUIatwqb7jHPtsGnF8RUqjmWVCuEqwvPTOgyKtE2y2NU6D3gKaWz6VzZCrl66X92oRzgQ58CiqUohDSBfhVQs+nROGyiF3FJy55EJC6QM7YivkRxKpuelZQ+nzANdDBs4SUgRGvn/UQb7UdUB+gZXrqos+TKE5Ucb8EQLmgoKFz7kv6e2Cnuvj3w1ngHQEXiwrewdyZTXywrQnzPP7fcOCiZRgnK6OL25v7xGi+/gk/rUjY4D5uqklcOXLJvi7pWJuziNgj1UhWILztbIyzy4QoEyR6Otk7ORKY2kwmUQ84nMhKT04qczxbv54AbupLGrg/sVyYYaVjCHdUwZQwQll6AAnRyIhWRI3VwoiL1zbpCZLkRtySkIcNu95lODRDLcJwfTakEUeDhlnNg3x6pAuoaZu4NOCkF3UWgPIQico2NKfIKbqu7MYuOonokgHESq6T+B/9VBNucAKGzulzvh3JUGxfkFHNXSB/KmnNVYyTpBgY4VAnQKRq3yfnIDVdkHkwpl05zqrk52OTsAuZj23l59joOwPIxj2jE+Xy2ejFXXtnh56n7TOEb/yBkNjHF1Eeem2a/OlCMwo/KCeatDInNwDYKsiTOmufFquJjc+mfWi9duaWvIHZu/5BvXufZjhCeY01yCrcKIysn4Ud9sq0amPdV0Vj1NtMpQ+VxxaUXooDDP45XvQLUwNLIjKXHmTCV3u9+qmaV6XkQsvxy/MeB1XWO/qpQun6DJ3FQUpvGxK2TYCEo4UhRChejJlqGcihjaSB+rANgXRSB8yZOZm6n6eSnw3e06fkFxesMIiL3y1/TbEQ9cF6h3b7uA42jZWBaN8sk/UoF2iKLuFIWeAlRSLU8BT3RNSiMjik+QgOHGfEw/JgY2ajGJVGpdWPSM6KRjGdEBTyRnGGGIp+hMW7I6EZxmcdlvI6SmjncKtRENlFB1UYQM9+sK0R1jZ2k+HyV0Ef8ibnKNnolnTRkwogh2fFZdFeFK7QDYOA+xwXeRQYjGEu9qyjfIsVWOQgDsYLcXtE2A/VDT6rLCFyhd4oD6sd2aiaJoyWIo/g8cFI4QkLorsHtrfEYR+kGngIBqGwqgq6OPFXJfLSvFNUV6rLyi1KE3EXKijtq1KQeAvwS8xQPL4+iAtk7QHQh9wkerthds++iN/zuEp541ltIgRHa9BOcGgkG3O9OFKTwnCqSZSpF7kUVFE4bOLov6WRqHnDStigZlQPkHKvjabX30b5SYFbEL78oRYAsh1vcUaPGN5g8xk/6bqt2zVLDZkCEVtHC1kjqlvfdiYJU9qMgWaZSFLYkp3DawAmMKltXOcKW/oCnmNBWJ70DE9vFEbdWStWCMs4UpjQ0NdlylNQfArGVqAZNHIpRGjq+8VX5+iUq0HWW7zSsTk1lFUlUdaRmmY/2laKyLFn5OSuibxI97irr6Rd11Jgp510UN7VxyjlbYphWDce71vozZPhsglIxYkrY/FxbiWCOrv3oj6Lkb0OwxeY+RblC+S5Omx8/omiTxKnG3kI4sU3HKqiVYCIs40xhirADIVu+kuQjKQDVKA0e3QjJ9fsPUREXdSxd5VFa1C1vV3ZM7sQDc7KJPIgIkv0SIoJxlKx1Vx6Ax/kptr/75ImuU+/+QZZ8YuVIarSwG8iu6nufsly2+Uybx4gqAXIXplpQkhE7QrxNTZuHy9xzPsrGf/UHKcbREsrInU/nSiDRsaD8KArWipRqFuemVMa8e1UaOIc+9aSKmVOIhG1n1WMwVXAcf/srKehlVtXDoTdz76ti4M5BEDVL+oIq51SBWt5VTLp0pRHWeJMWCK/btFXGqHioGlWssuaKmy6zN8uE9Xj7lyGbdR6YgwfdapRX6/Ee1TaW37EDH3mY7IEHL3IX40cdJnjQwQ+FKfagQ0mnGXT7oMLbV5QX+MbJugiSbGjX5OBfsCTEhE5xkDSWu+HI3Ty/VrNw5wyouiUqZUo6VqSWG5URn4PySKdIVmY4wyzi4p9TMO0UDR6jdpdRviziMjqWz6PTpJuXQHTjbGbyO295qgd1NlbDhGz8c1b9jPO9wSLN+7E7xMgbCdlMvzDmo9J79+QZGgCHg3/YF1/QB6YZrRvMYM/hINu/NPwe1rkqW/WGGpDSP4yzT0Ioy46kZpNnRp2+2TYvJWKZTbTX0BkpIbP3nui8VK0/4+zonRe/1IbFhc0vCUraVA0uwNxVwaMybajCaTFl5tK4u6govmf55h4VqLzHF0AXwFuqgJQ2FcGrkjpbzivgRknKGwQUNItVjBZgFoORhyLDst1sUFOVUAvccjYVQFVAEDPfBje7fVLwoean80akoLxNNZwqIuj6P9tsPOgNSKbkPBv81Ocpamu/kEpojsC+NFUD1KMAGqAq88aCQOwYwE4beI/WMdrHNUK4Ozg5pdxAF+tixCdryzJav6CNzpqwksZqzxOVkQqhPtlWhgry4tJzVcAnlOxX6AcwXktK21TAoRqC6vSjvUYr+ptbbk4N/R2lm6y/WBAll1n6HG8rnc10BlxsKklVPcFNXdi9UhWo0qI/b0UqNt/pMXC5vDc71f4ZN6dxLrOk2qXc9EeXxUTKYWtqBVLUwC00XO2frx73m6hEn+KizPK3mxLtgD4WRmnVHXCqJBXFLeBGSSqfqaJZgmI+Z+soudjmqLlD7Cpp/ge/VkWH3Ka6hPUSbCSlHCpOASsY4dkoSxFugZQu46wv6svXL/Erwv+Gp9FASvtoI6vkaIou4EZJIFuU0CxXMSC7kxG5N7lpVbVCRWlubApqV7jqVytUGFnIndI0jE9Idx6K0jBGMeFYBjm56jSzUymVM3zx84P+R/tK0TE49wnnlIrQMagJksmRVfOhKuIUFYWm5SjIrCOmXx+rF/KrA8VArEdIsDhlQCxITOHchMZXj9G7wkBK6+iRvUnLL+BGSRCbGuvBYb8UA7EvKZFzE5tKVeTG4SFXzA5hZx15EDlYHcOoRlQ8xKK1GQVlC3QE8RL6nJy7jrmp3+BKOAMujlEuvlFJXdi9UvX9xjh3xc1Pkfo+QcJgZFfgm2rxX4Y38g7g5hi/XDFUyhYQjad0fQeh5hMUzVOQvgMBMBrZkfiueqNrsIz4OMa47CYaSPExlKvvOsa6H2uuCtV3EVIWIzsHH1VMH0839ggARo4RLD2UDyo/ioL1vYKURVBqoxF9zyDnMbJr8EnNmssIEhIn2ORP+p6+WFYE1FzdrxFM0XioWU2wDjCeOm7SEuXP0Vp3i4eKzjpCiApZvVCfXSgHYi1iiiUqBGJBEhLnZjSJio5PP2qmnEpC+wgiauToh/ruREEgqxKTLFQpIMuS0Lg3rYnVtPr/yzvb3TZhKAzfyrQbyA2gSVuzTpXWtWrW/XfhlCKByQxU693PhHyQ+Os44RgUfgbO62M/OW9rHMBQrHNWe//bwjZAWFf9zDZwx3GkAP1MaJTODJqfSc3agGadCMazTRverC5QdIA8TRnSjCNC8TTdqGYLiql7be6NNG1atptVeRkMISaop9OsOlhqDBkwnOGsshlAwhnQrgtgwilg874CtMrIass0g++fJQDjY7cQ133jwvCx1SjXe6HxdL8MtluN8MRzwoiQDl4/pzlVSGoEESiMsayiq4aDMZpdRW62EXH1+vnMM981TKR8+PrS5NVA00YRgkMZ0SWcDSyUMZ1KenOOju+RfbRvOrkV8Bd47PtoHE49eNVp0qrUtEF00DD+dOnmAQrjTaeQ3JoTQXdfJpCf50qblKrS9jmNrHoRRKA8nKgXXTUcD/cZVKGsNwYukcXwBGnTvTrb13co9fDVpabVENMF0UFDedChmwcolB9dQnpLjo6ujBuxeSnfqr2dE1LvqSq6BYK606bWATQE0kLEmdWtnR84nHkR4gAGngjKRsRvrILbUhS+DnZLh6/Ak5waXkoEESiUS22iq4aDcqJVRW/B0XB1T0GA8DScQzZ4PfXzqXCOzxKAwRjMKLg6GBhDmRXkZhoDTzetbRd7mjPWSrF6gkrSJNYx04ZRwsM5zqWcEzCcK53SAPYcH+EKeJXV2Tuc8bAeRjt43SlJVWCaECpYGHPaVdcOCGNGh4zciJNA9giianflucSIiDbo6u00uQWiGkoN08uoVvVcAXoZ2S4PZ+gJIP0Nosj45swSWJJn3PcZKnwLg9emIbWK0RhICxFja4x2fuAwdkaJyc08AZT+a0MBl4WMV/kDX+D7rAMFWQIaZeBP8ApCXoWBdnNHU+jAgzhqYXcv+HPF0uMmTs5cDOLCuepY01TcbIByInD2vDT8lHTKsOzeQ+mCDVxrUa07B0CG32k8wC7jysbbA226jdlZnHRX8UsHFi06bfs4KpOTE7E/Fy1W8RsUbHtAfqxLIf9mb+7dqjZHo8VTI9UFdJ+WUGXpoYlItsnloGXOQ6O7mDv+Wj6Kcg1i0+9+j3Yhu9Nb1PdQs0QW9ldRZ68srg/vCvv86Q/LGxnyvXiB5I4/NPW6qeWQoXjJP/owooU9f7RQ+hx1T1lUQwxBdjNrt5J94N+aLE/2/b5leXViVlMTN5L+D5DHu+9y+0P/vqVfJUc2tMW3hDXwBPj+Yf/qga/YO5zTN1msPyFl8Yc8/p4lbeWaGnF/EcfYo2XGUsGKatvGQS8/yhpOin9f/gNjv4PV8kgUAA== + + + dbo + + \ No newline at end of file diff --git a/Infrastructure.DataAccess/Migrations/202210060603461_Add_Sts_Org_Import_Tables.Designer.cs b/Infrastructure.DataAccess/Migrations/202210060603461_Add_Sts_Org_Import_Tables.Designer.cs new file mode 100644 index 0000000000..f5df6cbc73 --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/202210060603461_Add_Sts_Org_Import_Tables.Designer.cs @@ -0,0 +1,29 @@ +// +namespace Infrastructure.DataAccess.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.4.4")] + public sealed partial class Add_Sts_Org_Import_Tables : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(Add_Sts_Org_Import_Tables)); + + string IMigrationMetadata.Id + { + get { return "202210060603461_Add_Sts_Org_Import_Tables"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/Infrastructure.DataAccess/Migrations/202210060603461_Add_Sts_Org_Import_Tables.cs b/Infrastructure.DataAccess/Migrations/202210060603461_Add_Sts_Org_Import_Tables.cs new file mode 100644 index 0000000000..1b59524468 --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/202210060603461_Add_Sts_Org_Import_Tables.cs @@ -0,0 +1,56 @@ +namespace Infrastructure.DataAccess.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class Add_Sts_Org_Import_Tables : DbMigration + { + public override void Up() + { + CreateTable( + "dbo.StsOrganizationConnections", + c => new + { + Id = c.Int(nullable: false), + OrganizationId = c.Int(nullable: false), + Connected = c.Boolean(nullable: false), + SynchronizationDepth = c.Int(), + ObjectOwnerId = c.Int(nullable: false), + LastChanged = c.DateTime(nullable: false, precision: 7, storeType: "datetime2"), + LastChangedByUserId = c.Int(nullable: false), + }) + .PrimaryKey(t => t.Id) + .ForeignKey("dbo.User", t => t.LastChangedByUserId) + .ForeignKey("dbo.User", t => t.ObjectOwnerId) + .ForeignKey("dbo.Organization", t => t.Id) + .Index(t => t.Id) + .Index(t => t.Connected) + .Index(t => t.ObjectOwnerId) + .Index(t => t.LastChangedByUserId); + + AddColumn("dbo.OrganizationUnit", "Origin", c => c.Int(nullable: false)); + AddColumn("dbo.OrganizationUnit", "ExternalOriginUuid", c => c.Guid()); + CreateIndex("dbo.OrganizationUnit", "Origin", name: "IX_OrganizationUnit_Origin"); + CreateIndex("dbo.OrganizationUnit", "ExternalOriginUuid", name: "IX_OrganizationUnit_UUID"); + + //Initially all units' origin is "Kitos" + Sql("UPDATE dbo.OrganizationUnit SET Origin = 0;"); + } + + public override void Down() + { + DropForeignKey("dbo.StsOrganizationConnections", "Id", "dbo.Organization"); + DropForeignKey("dbo.StsOrganizationConnections", "ObjectOwnerId", "dbo.User"); + DropForeignKey("dbo.StsOrganizationConnections", "LastChangedByUserId", "dbo.User"); + DropIndex("dbo.StsOrganizationConnections", new[] { "LastChangedByUserId" }); + DropIndex("dbo.StsOrganizationConnections", new[] { "ObjectOwnerId" }); + DropIndex("dbo.StsOrganizationConnections", new[] { "Connected" }); + DropIndex("dbo.StsOrganizationConnections", new[] { "Id" }); + DropIndex("dbo.OrganizationUnit", "IX_OrganizationUnit_UUID"); + DropIndex("dbo.OrganizationUnit", "IX_OrganizationUnit_Origin"); + DropColumn("dbo.OrganizationUnit", "ExternalOriginUuid"); + DropColumn("dbo.OrganizationUnit", "Origin"); + DropTable("dbo.StsOrganizationConnections"); + } + } +} diff --git a/Infrastructure.DataAccess/Migrations/202210060603461_Add_Sts_Org_Import_Tables.resx b/Infrastructure.DataAccess/Migrations/202210060603461_Add_Sts_Org_Import_Tables.resx new file mode 100644 index 0000000000..49728d088a --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/202210060603461_Add_Sts_Org_Import_Tables.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/Infrastructure.DataAccess/Migrations/202210271249212_Removed_Delegated_SystemUsages.Designer.cs b/Infrastructure.DataAccess/Migrations/202210271249212_Removed_Delegated_SystemUsages.Designer.cs new file mode 100644 index 0000000000..14cd503d6d --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/202210271249212_Removed_Delegated_SystemUsages.Designer.cs @@ -0,0 +1,29 @@ +// +namespace Infrastructure.DataAccess.Migrations +{ + using System.CodeDom.Compiler; + using System.Data.Entity.Migrations; + using System.Data.Entity.Migrations.Infrastructure; + using System.Resources; + + [GeneratedCode("EntityFramework.Migrations", "6.4.4")] + public sealed partial class Removed_Delegated_SystemUsages : IMigrationMetadata + { + private readonly ResourceManager Resources = new ResourceManager(typeof(Removed_Delegated_SystemUsages)); + + string IMigrationMetadata.Id + { + get { return "202210271249212_Removed_Delegated_SystemUsages"; } + } + + string IMigrationMetadata.Source + { + get { return null; } + } + + string IMigrationMetadata.Target + { + get { return Resources.GetString("Target"); } + } + } +} diff --git a/Infrastructure.DataAccess/Migrations/202210271249212_Removed_Delegated_SystemUsages.cs b/Infrastructure.DataAccess/Migrations/202210271249212_Removed_Delegated_SystemUsages.cs new file mode 100644 index 0000000000..db33d5279b --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/202210271249212_Removed_Delegated_SystemUsages.cs @@ -0,0 +1,22 @@ +namespace Infrastructure.DataAccess.Migrations +{ + using System; + using System.Data.Entity.Migrations; + + public partial class Removed_Delegated_SystemUsages : DbMigration + { + public override void Up() + { + DropForeignKey("dbo.ItSystemUsage", "OrganizationUnit_Id", "dbo.OrganizationUnit"); + DropIndex("dbo.ItSystemUsage", new[] { "OrganizationUnit_Id" }); + DropColumn("dbo.ItSystemUsage", "OrganizationUnit_Id"); + } + + public override void Down() + { + AddColumn("dbo.ItSystemUsage", "OrganizationUnit_Id", c => c.Int()); + CreateIndex("dbo.ItSystemUsage", "OrganizationUnit_Id"); + AddForeignKey("dbo.ItSystemUsage", "OrganizationUnit_Id", "dbo.OrganizationUnit", "Id"); + } + } +} diff --git a/Infrastructure.DataAccess/Migrations/202210271249212_Removed_Delegated_SystemUsages.resx b/Infrastructure.DataAccess/Migrations/202210271249212_Removed_Delegated_SystemUsages.resx new file mode 100644 index 0000000000..c9f9e55539 --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/202210271249212_Removed_Delegated_SystemUsages.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 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 + + + dbo + + \ No newline at end of file diff --git a/Infrastructure.DataAccess/Migrations/SQLScripts/Manually run scripts to fix staging DB/Delete_Users_Other_Than_Preserved_Users.sql b/Infrastructure.DataAccess/Migrations/SQLScripts/Manually run scripts to fix staging DB/Delete_Users_Other_Than_Preserved_Users.sql new file mode 100644 index 0000000000..30f0bc0b70 --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/SQLScripts/Manually run scripts to fix staging DB/Delete_Users_Other_Than_Preserved_Users.sql @@ -0,0 +1,75 @@ +/* +User story reference: + https://os2web.atlassian.net/browse/KITOSUDV-3402 + +Content: + Anonymizes users than Local admin and Api user +*/ + +BEGIN + -- Make sure the temp table doesn't exist + If(OBJECT_ID('tempdb..#idsToPreserve') Is Not Null) + Begin + Drop Table #idsToPreserve + End + + CREATE TABLE #idsToPreserve( + Id int + ) + + -- Insert values from the csv file + BULK INSERT #idsToPreserve + FROM 'D:\FileName.csv' + WITH + ( + FIRSTROW = 1, + DATAFILETYPE='widechar', -- UTF-16 + FIELDTERMINATOR = ';', + ROWTERMINATOR = '\n', + TABLOCK, + KEEPNULLS -- Treat empty fields as NULLs. + ) + + -- Delete users not in csv file + UPDATE [User] + SET + Name = 'Slettet bruger', + LockedOutDate = GETDATE(), + Email = CONVERT(NVARCHAR(36), NEWID()) + '_deleted_user@kitos.dk', + PhoneNumber = null, + LastName = '', + Password = NEWID(), + DeletedDate = GETDATE(), + Deleted = 1, + IsGlobalAdmin = 0, + HasApiAccess = 0, + HasStakeHolderAccess = 0 + FROM [User] + WHERE Deleted = 0 + AND Id NOT IN (SELECT * FROM #idsToPreserve); + + DELETE FROM DataProcessingRegistrationRights + WHERE UserId NOT IN (SELECT * FROM #idsToPreserve); + + DELETE FROM ItContractRights + WHERE UserId NOT IN (SELECT * FROM #idsToPreserve); + + DELETE FROM ItSystemRights + WHERE UserId NOT IN (SELECT * FROM #idsToPreserve); + + DELETE FROM OrganizationUnitRights + WHERE UserId NOT IN (SELECT * FROM #idsToPreserve); + + DELETE FROM OrganizationRights + WHERE UserId NOT IN (SELECT * FROM #idsToPreserve); + + DELETE FROM SsoUserIdentities + WHERE User_Id NOT IN (SELECT * FROM #idsToPreserve); + + + -- Make sure the temp table doesn't exist + If(OBJECT_ID('tempdb..#idsToPreserve') Is Not Null) + Begin + Drop Table #idsToPreserve + End +END \ No newline at end of file diff --git a/Infrastructure.DataAccess/Migrations/SQLScripts/Manually run scripts to fix staging DB/Get_Users_To_Preserve.sql b/Infrastructure.DataAccess/Migrations/SQLScripts/Manually run scripts to fix staging DB/Get_Users_To_Preserve.sql new file mode 100644 index 0000000000..bf4c072ab7 --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/SQLScripts/Manually run scripts to fix staging DB/Get_Users_To_Preserve.sql @@ -0,0 +1,18 @@ +/* +User story reference: + https://os2web.atlassian.net/browse/KITOSUDV-3402 + +Content: + +*/ + +BEGIN + SELECT DISTINCT T0.Id + FROM [User] T0 + LEFT JOIN OrganizationRights T1 + ON T0.Id = T1.UserId + WHERE T0.Deleted = 0 + AND (T1.Role = 1 + OR T0.IsGlobalAdmin = 1 + OR T0.HasApiAccess = 1 AND T1.UserId IS NOT NULL) +END \ No newline at end of file diff --git a/Infrastructure.DataAccess/Migrations/SQLScripts/Migrate_Users_Not_Associated_With_Any_Org.sql b/Infrastructure.DataAccess/Migrations/SQLScripts/Migrate_Users_Not_Associated_With_Any_Org.sql new file mode 100644 index 0000000000..f2594dac55 --- /dev/null +++ b/Infrastructure.DataAccess/Migrations/SQLScripts/Migrate_Users_Not_Associated_With_Any_Org.sql @@ -0,0 +1,62 @@ +/* +User story reference: + https://os2web.atlassian.net/browse/KITOSUDV-3422 + +Content: + Sets Users with no assossiated Organizations as deleted +*/ + +BEGIN + If(OBJECT_ID('tempdb..#get_userIds_to_delete') IS NOT NULL) + Begin + Drop Table #get_userIds_to_delete + End + + CREATE TABLE #get_userIds_to_delete + ( + Id int + ) + + INSERT INTO #get_userIds_to_delete + SELECT T0.Id + FROM [User] T0 + LEFT JOIN OrganizationRights T1 + ON T0.Id = T1.UserId + WHERE + T1.Id IS NULL AND T0.Deleted = 0 AND + T0.IsGlobalAdmin = 0; + + UPDATE [User] + SET + Name = 'Slettet bruger', + LockedOutDate = GETDATE(), + Email = CONVERT(NVARCHAR(36), NEWID()) + '_deleted_user@kitos.dk', + PhoneNumber = null, + LastName = '', + DeletedDate = GETDATE(), + Deleted = 1, + IsGlobalAdmin = 0, + HasApiAccess = 0, + HasStakeHolderAccess = 0 + WHERE Id IN (SELECT Id FROM #get_userIds_to_delete); + + DELETE FROM DataProcessingRegistrationRights + WHERE UserId IN (SELECT Id FROM #get_userIds_to_delete); + + DELETE FROM ItContractRights + WHERE UserId IN (SELECT Id FROM #get_userIds_to_delete); + + DELETE FROM ItSystemRights + WHERE UserId IN (SELECT Id FROM #get_userIds_to_delete); + + DELETE FROM OrganizationUnitRights + WHERE UserId IN (SELECT Id FROM #get_userIds_to_delete); + + DELETE FROM SsoUserIdentities + WHERE User_Id IN (SELECT Id FROM #get_userIds_to_delete); + + If(OBJECT_ID('tempdb..#get_userIds_to_delete') IS NOT NULL) + Begin + Drop Table #get_userIds_to_delete + End +END \ No newline at end of file diff --git a/Infrastructure.Ninject/DomainServices/NinjectCommandHandlerMediator.cs b/Infrastructure.Ninject/DomainServices/NinjectCommandHandlerMediator.cs new file mode 100644 index 0000000000..450690d3a5 --- /dev/null +++ b/Infrastructure.Ninject/DomainServices/NinjectCommandHandlerMediator.cs @@ -0,0 +1,20 @@ +using Core.DomainModel.Commands; +using Ninject; + +namespace Infrastructure.Ninject.DomainServices +{ + public class NinjectCommandHandlerMediator : ICommandBus + { + public TResult Execute(TCommand args) where TCommand : ICommand + { + return _kernel.Get>().Execute(args); + } + + private readonly IKernel _kernel; + + public NinjectCommandHandlerMediator(IKernel kernel) + { + _kernel = kernel; + } + } +} diff --git a/Infrastructure.Ninject/DomainServices/NinjectDomainEventsAdapter.cs b/Infrastructure.Ninject/DomainServices/NinjectDomainEventHandlerMediator.cs similarity index 89% rename from Infrastructure.Ninject/DomainServices/NinjectDomainEventsAdapter.cs rename to Infrastructure.Ninject/DomainServices/NinjectDomainEventHandlerMediator.cs index 6752387fe1..e8c7d4f5e6 100644 --- a/Infrastructure.Ninject/DomainServices/NinjectDomainEventsAdapter.cs +++ b/Infrastructure.Ninject/DomainServices/NinjectDomainEventHandlerMediator.cs @@ -9,11 +9,11 @@ namespace Infrastructure.Ninject.DomainServices /// /// We have chosen to use a simpler in-memory version of the Domain Events implementation, since we do not have a service bus or u-service architecture /// - public class NinjectDomainEventsAdapter : IDomainEvents + public class NinjectDomainEventHandlerMediator : IDomainEvents { private readonly IKernel _kernel; - public NinjectDomainEventsAdapter(IKernel kernel) + public NinjectDomainEventHandlerMediator(IKernel kernel) { _kernel = kernel; } diff --git a/Infrastructure.Ninject/Infrastructure.Ninject.csproj b/Infrastructure.Ninject/Infrastructure.Ninject.csproj index c5c0e7372c..65caaac063 100644 --- a/Infrastructure.Ninject/Infrastructure.Ninject.csproj +++ b/Infrastructure.Ninject/Infrastructure.Ninject.csproj @@ -45,7 +45,8 @@ - + + diff --git a/Infrastructure.STS.Common/Model/StsError.cs b/Infrastructure.STS.Common/Model/StsError.cs index 1ffd86e2bc..5ae5403ac0 100644 --- a/Infrastructure.STS.Common/Model/StsError.cs +++ b/Infrastructure.STS.Common/Model/StsError.cs @@ -4,6 +4,8 @@ public enum StsError { NotFound, BadInput, + MissingServiceAgreement, + ExistingServiceAgreementIssue, Unknown } } diff --git a/Infrastructure.STS.Common/Model/StsErrorParser.cs b/Infrastructure.STS.Common/Model/StsErrorParser.cs index b01380d06e..8983909e86 100644 --- a/Infrastructure.STS.Common/Model/StsErrorParser.cs +++ b/Infrastructure.STS.Common/Model/StsErrorParser.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Core.Abstractions.Types; namespace Infrastructure.STS.Common.Model @@ -10,7 +11,7 @@ public static class StsErrorParser { "44", StsError.NotFound }, { "40", StsError.BadInput } }; - public static Maybe ParseStsError(this string resultCode) + public static Maybe ParseStsErrorFromStandardResultCode(this string resultCode) { if (resultCode == "20") { @@ -19,5 +20,23 @@ public static Maybe ParseStsError(this string resultCode) return KnownErrors.TryGetValue(resultCode, out var knownError) ? knownError : StsError.Unknown; } + + public static Maybe ParseStsFromErrorCode(this string errorCode) + { + if (errorCode != null) + { + if (errorCode.Equals("ServiceAgreementNotFound", StringComparison.OrdinalIgnoreCase)) + { + return StsError.MissingServiceAgreement; + } + if (errorCode.Contains("ServiceAgreement")) + { + //Covers a lot of different erros related to the service agreement: https://www.serviceplatformen.dk/administration/errorcodes-doc/errorcodes/4afb35be-7b7a-45b3-ab01-bd5017a8b182_errorcodes.html + return StsError.ExistingServiceAgreementIssue; + } + } + + return StsError.Unknown; + } } } diff --git a/Infrastructure.STS.Company/DomainServices/StsOrganizationCompanyLookupService.cs b/Infrastructure.STS.Company/DomainServices/StsOrganizationCompanyLookupService.cs index 7dbc92e70c..2f9fe82c88 100644 --- a/Infrastructure.STS.Company/DomainServices/StsOrganizationCompanyLookupService.cs +++ b/Infrastructure.STS.Company/DomainServices/StsOrganizationCompanyLookupService.cs @@ -9,21 +9,24 @@ using Infrastructure.STS.Common.Factories; using Infrastructure.STS.Common.Model; using Infrastructure.STS.Company.ServiceReference; +using Serilog; namespace Infrastructure.STS.Company.DomainServices { public class StsOrganizationCompanyLookupService : IStsOrganizationCompanyLookupService { + private readonly ILogger _logger; private readonly string _certificateThumbprint; private readonly string _serviceRoot; - public StsOrganizationCompanyLookupService(StsOrganisationIntegrationConfiguration configuration) + public StsOrganizationCompanyLookupService(StsOrganisationIntegrationConfiguration configuration, ILogger logger) { + _logger = logger; _certificateThumbprint = configuration.CertificateThumbprint; _serviceRoot = $"https://{configuration.EndpointHost}/service/Organisation/Virksomhed/5"; } - public Result ResolveStsOrganizationCompanyUuid(Organization organization) + public Result> ResolveStsOrganizationCompanyUuid(Organization organization) { if (organization == null) { @@ -34,22 +37,43 @@ public Result ResolveStsOrganizationCompanyUuid(Organizati var channel = organizationPortTypeClient.ChannelFactory.CreateChannel(); var request = CreateSearchByCvrRequest(organization); - var response = channel.soeg(request); - var statusResult = response.SoegResponse1.SoegOutput.StandardRetur; - var stsError = statusResult.StatusKode.ParseStsError(); - if (stsError.HasValue) + try { - return new OperationError($"Error resolving the organization company from STS:{statusResult.StatusKode}:{statusResult.FejlbeskedTekst}", OperationFailure.UnknownError); + var response = channel.soeg(request); + + var statusResult = response.SoegResponse1.SoegOutput.StandardRetur; + var stsError = statusResult.StatusKode.ParseStsErrorFromStandardResultCode(); + if (stsError.HasValue) + { + return new DetailedOperationError(OperationFailure.UnknownError, stsError.Value, $"Error resolving the organization company from STS:{statusResult.StatusKode}:{statusResult.FejlbeskedTekst}"); + } + + var ids = response.SoegResponse1.SoegOutput.IdListe; + if (ids.Length != 1) + { + return new DetailedOperationError(OperationFailure.UnknownError, StsError.Unknown, $"Error resolving the organization company from STS. Expected a single UUID but got:{string.Join(",", ids)}"); + } + + return new Guid(ids.Single()); } + catch (FaultException spFault) + { + var knownStsError = spFault.Detail.ErrorList.Select(error => error.ErrorCode.ParseStsFromErrorCode()).FirstOrDefault(x => x.HasValue); + var stsError = knownStsError.GetValueOrFallback(StsError.Unknown); + var operationFailure = + stsError is StsError.MissingServiceAgreement or StsError.ExistingServiceAgreementIssue + ? OperationFailure.Forbidden + : OperationFailure.UnknownError; - var ids = response.SoegResponse1.SoegOutput.IdListe; - if (ids.Length != 1) + _logger.Error(spFault, "Service platform exception while finding company uuid from cvr {cvr} for organization with id {organizationId}", organization.Cvr, organization.Id); + return new DetailedOperationError(operationFailure, stsError, $"STS Organisation threw and exception while searching for uuid by cvr:{organization.Cvr} for organization with id:{organization.Id}"); + } + catch (Exception e) { - return new OperationError($"Error resolving the organization company from STS. Expected a single UUID but got:{string.Join(",", ids)}", OperationFailure.UnknownError); + _logger.Error(e, "Unknown Exception while finding company uuid from cvr {cvr} for organization with id {organizationId}", organization.Cvr, organization.Id); + return new DetailedOperationError(OperationFailure.UnknownError, StsError.Unknown, $"STS Organisation threw and unknown exception while searching for uuid by cvr:{organization.Cvr} for organization with id:{organization.Id}"); } - - return new Guid(ids.Single()); } private static soegRequest CreateSearchByCvrRequest(Organization organization) @@ -62,7 +86,7 @@ private static soegRequest CreateSearchByCvrRequest(Organization organization) { MunicipalityCVR = organization.Cvr }, - SoegInput = new SoegInputType1() + SoegInput = new SoegInputType1 { RelationListe = new RelationListeType(), FoersteResultatReference = "0", diff --git a/Infrastructure.STS.Company/Infrastructure.STS.Company.csproj b/Infrastructure.STS.Company/Infrastructure.STS.Company.csproj index 4fb2ba0d04..b23f065c72 100644 --- a/Infrastructure.STS.Company/Infrastructure.STS.Company.csproj +++ b/Infrastructure.STS.Company/Infrastructure.STS.Company.csproj @@ -32,6 +32,9 @@ 4 + + ..\packages\Serilog.2.11.0\lib\net46\Serilog.dll + @@ -138,6 +141,7 @@ Designer + diff --git a/Infrastructure.STS.Company/packages.config b/Infrastructure.STS.Company/packages.config new file mode 100644 index 0000000000..22e0304f77 --- /dev/null +++ b/Infrastructure.STS.Company/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Infrastructure.STS.Organization/DomainServices/StsOrganizationService.cs b/Infrastructure.STS.Organization/DomainServices/StsOrganizationService.cs index eee0b7998f..545cbfdfdf 100644 --- a/Infrastructure.STS.Organization/DomainServices/StsOrganizationService.cs +++ b/Infrastructure.STS.Organization/DomainServices/StsOrganizationService.cs @@ -22,7 +22,7 @@ public class StsOrganizationService : IStsOrganizationService private readonly ILogger _logger; private readonly string _certificateThumbprint; private readonly string _serviceRoot; - + public StsOrganizationService( StsOrganisationIntegrationConfiguration configuration, IStsOrganizationCompanyLookupService companyLookupService, @@ -36,6 +36,22 @@ public StsOrganizationService( _serviceRoot = $"https://{configuration.EndpointHost}/service/Organisation/Organisation/5"; } + public Maybe> ValidateConnection(Core.DomainModel.Organization.Organization organization) + { + return ResolveExternalUuid(organization) + .Match(_ => Maybe>.None, error => + { + var connectionError = error.Detail switch + { + ResolveOrganizationUuidError.InvalidCvrOnOrganization => CheckConnectionError.InvalidCvrOnOrganization, + ResolveOrganizationUuidError.MissingServiceAgreement => CheckConnectionError.MissingServiceAgreement, + ResolveOrganizationUuidError.ExistingServiceAgreementIssue => CheckConnectionError.ExistingServiceAgreementIssue, + _ => CheckConnectionError.Unknown + }; + return new DetailedOperationError(error.FailureType, connectionError, error.Message.GetValueOrFallback(string.Empty)); + }); + } + public Result> ResolveStsOrganizationUuid(Core.DomainModel.Organization.Organization organization) { if (organization == null) @@ -50,18 +66,10 @@ public Result> Resolv return fkOrgIdentity.ExternalUuid; } - if (organization.IsCvrInvalid()) - { - return new DetailedOperationError(OperationFailure.BadState, ResolveOrganizationUuidError.InvalidCvrOnOrganization); - } + var companyUuid = ResolveExternalUuid(organization); - //Resolve the associated company uuid - var companyUuid = _companyLookupService.ResolveStsOrganizationCompanyUuid(organization); if (companyUuid.Failed) - { - _logger.Error("Error {error} while resolving company uuid for organization with id {id}", companyUuid.Error.ToString(), organization.Id); - return new DetailedOperationError(OperationFailure.UnknownError, ResolveOrganizationUuidError.FailedToLookupOrganizationCompany); - } + return companyUuid.Error; //Search for the organization based on the resolved company (all organizations are tied to a company) using var clientCertificate = X509CertificateClientCertificateFactory.GetClientCertificate(_certificateThumbprint); @@ -71,7 +79,7 @@ public Result> Resolv var channel = organizationPortTypeClient.ChannelFactory.CreateChannel(); var response = channel.soeg(searchRequest); var statusResult = response.SoegResponse1.SoegOutput.StandardRetur; - var stsError = statusResult.StatusKode.ParseStsError(); + var stsError = statusResult.StatusKode.ParseStsErrorFromStandardResultCode(); if (stsError.HasValue) { _logger.Error("Failed to search for organization ({id}) by company uuid {uuid}. Failed with {stsError} {code} and {message}", organization.Id, companyUuid.Value, stsError.Value, statusResult.StatusKode, statusResult.FejlbeskedTekst); @@ -97,6 +105,40 @@ public Result> Resolv return uuid; } + private Result> ResolveExternalUuid(Core.DomainModel.Organization.Organization organization) + { + if (string.IsNullOrWhiteSpace(organization.Cvr) || organization.IsCvrInvalid()) + { + return new DetailedOperationError(OperationFailure.BadState, ResolveOrganizationUuidError.InvalidCvrOnOrganization); + } + + //Resolve the associated company uuid + var companyUuid = _companyLookupService.ResolveStsOrganizationCompanyUuid(organization); + if (companyUuid.Failed) + { + _logger.Error("Error {error} while resolving company uuid for organization with id {id}", + companyUuid.Error.ToString(), organization.Id); + + var detailedError = companyUuid.Error.Detail switch + { + StsError.MissingServiceAgreement => ResolveOrganizationUuidError.MissingServiceAgreement, + StsError.ExistingServiceAgreementIssue => ResolveOrganizationUuidError.ExistingServiceAgreementIssue, + _ => ResolveOrganizationUuidError.FailedToLookupOrganizationCompany + }; + + var operationFailure = companyUuid.Error.Detail switch + { + StsError.MissingServiceAgreement => companyUuid.Error.FailureType, + StsError.ExistingServiceAgreementIssue => companyUuid.Error.FailureType, + _ => OperationFailure.UnknownError + }; + + return new DetailedOperationError(operationFailure, detailedError); + } + + return companyUuid.Value; + } + private static soegRequest CreateSearchForOrganizationRequest(Core.DomainModel.Organization.Organization organization, Guid companyUuid) { return new soegRequest diff --git a/Infrastructure.STS.Organization/Infrastructure.STS.Organization.csproj b/Infrastructure.STS.Organization/Infrastructure.STS.Organization.csproj index d1925a11c3..3d13099bd2 100644 --- a/Infrastructure.STS.Organization/Infrastructure.STS.Organization.csproj +++ b/Infrastructure.STS.Organization/Infrastructure.STS.Organization.csproj @@ -168,7 +168,7 @@ Core.Abstractions - {a76a8e41-74f7-4443-a5f3-059b5414d83b} + {A76A8E41-74F7-4443-A5F3-059B5414D83B} Core.DomainModel diff --git a/Infrastructure.STS.OrganizationUnit/DomainServices/StsOrganizationUnitService.cs b/Infrastructure.STS.OrganizationUnit/DomainServices/StsOrganizationUnitService.cs index 6165947a6f..3a2c2841fa 100644 --- a/Infrastructure.STS.OrganizationUnit/DomainServices/StsOrganizationUnitService.cs +++ b/Infrastructure.STS.OrganizationUnit/DomainServices/StsOrganizationUnitService.cs @@ -11,6 +11,7 @@ using Infrastructure.STS.Common.Factories; using Infrastructure.STS.Common.Model; using Infrastructure.STS.OrganizationUnit.ServiceReference; +using Polly; using Serilog; namespace Infrastructure.STS.OrganizationUnit.DomainServices @@ -30,36 +31,36 @@ public StsOrganizationUnitService(IStsOrganizationService organizationService, S _serviceRoot = $"https://{configuration.EndpointHost}/service/Organisation/OrganisationEnhed/5"; } - public Result> ResolveOrganizationTree(Organization organization) + public Result> ResolveOrganizationTree(Organization organization) { //Resolve the org uuid var uuid = _organizationService.ResolveStsOrganizationUuid(organization); if (uuid.Failed) { var error = uuid.Error; - _logger.Error("Loading sts organization uuid from org with id: {id} failed with {detailedError} {errorCode} {errorMessage}", organization.Id, error.Detail, error.FailureType, error.Message); + _logger.Error("Loading sts organization uuid from org with id: {id} failed with {detailedError} {errorCode} {errorMessage}", organization.Id, error.Detail, error.FailureType, error.Message.GetValueOrFallback("")); return new DetailedOperationError(error.FailureType, ResolveOrganizationTreeError.FailedResolvingUuid, $"{error.Detail}:{error.Message}"); } //Search for org units by org uuid using var clientCertificate = X509CertificateClientCertificateFactory.GetClientCertificate(_certificateThumbprint); - using var client = CreateClient(BasicHttpBindingFactory.CreateHttpBinding(), _serviceRoot, clientCertificate); - - var channel = client.ChannelFactory.CreateChannel(); - const int pageSize = 100; + const int pageSize = 500; var totalIds = new List(); var totalResults = new List<(Guid, RegistreringType1)>(); var currentPage = new List(); var organizationStsUuid = uuid.Value; + + using var client = CreateClient(BasicHttpBindingFactory.CreateHttpBinding(), _serviceRoot, clientCertificate); + var channel = client.ChannelFactory.CreateChannel(); do { currentPage.Clear(); var searchRequest = CreateSearchOrgUnitsByOrgUuidRequest(organization.Cvr, organizationStsUuid, pageSize, totalIds.Count); - var searchResponse = channel.soeg(searchRequest); + var searchResponse = SearchOrganizationUnits(channel, searchRequest); var searchStatusResult = searchResponse.SoegResponse1.SoegOutput.StandardRetur; - var stsError = searchStatusResult.StatusKode.ParseStsError(); + var stsError = searchStatusResult.StatusKode.ParseStsErrorFromStandardResultCode(); if (stsError.HasValue) { _logger.Error("Failed to search for org units for org with sts uuid: {stsuuid} failed with {code} {message}", organizationStsUuid, searchStatusResult.StatusKode, searchStatusResult.FejlbeskedTekst); @@ -71,11 +72,10 @@ public Result>(); - var idToConvertedChildren = new Dictionary(); + var parentIdToConvertedChildren = new Dictionary>(); + var idToConvertedChildren = new Dictionary(); var root = roots.Single(); var processingStack = CreateOrgUnitConversionStack(root, unitsByParent); @@ -121,7 +121,7 @@ public Result string.IsNullOrEmpty(x.EnhedNavn) == false); var unitUuid = unit.Item1; - var organizationUnit = new StsOrganizationUnit(unitUuid, egenskabType.EnhedNavn, egenskabType.BrugervendtNoegleTekst, parentIdToConvertedChildren.ContainsKey(unitUuid) ? parentIdToConvertedChildren[unitUuid] : new List(0)); + var organizationUnit = new ExternalOrganizationUnit(unitUuid, egenskabType.EnhedNavn, new Dictionary() { { "UserFacingKey", egenskabType.BrugervendtNoegleTekst } }, parentIdToConvertedChildren.ContainsKey(unitUuid) ? parentIdToConvertedChildren[unitUuid] : new List(0)); idToConvertedChildren[organizationUnit.Uuid] = organizationUnit; var parentUnit = unit.Item2.RelationListe.Overordnet; if (parentUnit != null) @@ -129,7 +129,7 @@ public Result(); + parentToChildrenList = new List(); parentIdToConvertedChildren[parentId] = parentToChildrenList; } parentToChildrenList.Add(organizationUnit); @@ -140,6 +140,24 @@ public Result() + .WaitAndRetry(new double[] { 1, 3, 5, 10 }.Select(TimeSpan.FromSeconds)) + .Execute(() => channel.soeg(searchRequest)); + } + + private static listResponse LoadOrganizationUnits(OrganisationEnhedPortType channel, listRequest listRequest) + { + //This call is unstable, so we add some retries + return Policy + .Handle() + .WaitAndRetry(new double[] { 1, 3, 5, 10 }.Select(TimeSpan.FromSeconds)) + .Execute(() => channel.list(listRequest)); + } + private static Stack CreateOrgUnitConversionStack((Guid, RegistreringType1) root, Dictionary> unitsByParent) { var processingStack = new Stack(); diff --git a/Infrastructure.STS.OrganizationUnit/Infrastructure.STS.OrganizationUnit.csproj b/Infrastructure.STS.OrganizationUnit/Infrastructure.STS.OrganizationUnit.csproj index 48ed1c8d38..c7b219b934 100644 --- a/Infrastructure.STS.OrganizationUnit/Infrastructure.STS.OrganizationUnit.csproj +++ b/Infrastructure.STS.OrganizationUnit/Infrastructure.STS.OrganizationUnit.csproj @@ -32,6 +32,9 @@ 4 + + ..\packages\Polly.7.2.3\lib\net472\Polly.dll + ..\packages\Serilog.2.11.0\lib\net46\Serilog.dll diff --git a/Infrastructure.STS.OrganizationUnit/packages.config b/Infrastructure.STS.OrganizationUnit/packages.config index 22e0304f77..78898b3b3e 100644 --- a/Infrastructure.STS.OrganizationUnit/packages.config +++ b/Infrastructure.STS.OrganizationUnit/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/Presentation.Web/App_Start/MappingConfig.cs b/Presentation.Web/App_Start/MappingConfig.cs index ff5eb3b1e9..1e9b30b473 100644 --- a/Presentation.Web/App_Start/MappingConfig.cs +++ b/Presentation.Web/App_Start/MappingConfig.cs @@ -190,6 +190,7 @@ public MappingProfile() CreateMap(); CreateMap() + .ForMember(dest => dest.Children, opt => opt.MapFrom(unit => unit.Children.OrderBy(child => child.Name).ToList())) .ReverseMap() .ForMember(dest => dest.Children, opt => opt.Ignore()) .IgnoreDestinationEntityFields(); @@ -204,16 +205,6 @@ public MappingProfile() .ReverseMap() .IgnoreDestinationEntityFields(); - CreateMap() - .ForMember(dto => dto.HasDelegations, opt => opt.MapFrom(src => src.Children.Any())) - .ReverseMap() - .IgnoreDestinationEntityFields(); - - CreateMap() - .ForMember(dto => dto.HasDelegations, opt => opt.MapFrom(src => src.Children.Any())) - .ReverseMap() - .IgnoreDestinationEntityFields(); - CreateMap() .ReverseMap() .IgnoreDestinationEntityFields(); @@ -284,7 +275,7 @@ public MappingProfile() //Output only - this mapping should not be reversed CreateMap() .ForMember(dest => dest.AgreementElements, opt => opt.MapFrom(src => src.AssociatedAgreementElementTypes.Select(x => x.AgreementElementType))); - + CreateMap() .ReverseMap() .IgnoreDestinationEntityFields(); diff --git a/Presentation.Web/Content/img/loading-spinner.gif b/Presentation.Web/Content/img/loading-spinner.gif new file mode 100644 index 0000000000..32ac2b463b Binary files /dev/null and b/Presentation.Web/Content/img/loading-spinner.gif differ diff --git a/Presentation.Web/Content/less/kitos.less b/Presentation.Web/Content/less/kitos.less index 81cce076e2..d662aa0a4c 100644 --- a/Presentation.Web/Content/less/kitos.less +++ b/Presentation.Web/Content/less/kitos.less @@ -1,3 +1,11 @@ +/** Variables */ +@fkorg-orgunit-color: #a9e38f; +@fkorg-orgunit-color_selected: #4f8438; +@fkorg-orgunit-hover: #a4db8c; +@fkorg-orgunit_font-color: #345925; +@ui-tree-selected_font-color: white; +@ui-tee-default-color: #b1cff3; + /* Disable responsiveness */ .container { width: @container-desktop !important; @@ -675,6 +683,10 @@ div.pull-outside-table { margin-top: 50px; } +.margin-top-sm { + margin-top: 25px; +} + table.table-fixed { table-layout: fixed; } @@ -909,20 +921,35 @@ div.searchbox-wrapper { font-weight: normal; line-height: 20px; color: #376092 !important; - background: #b1cff3 !important; + background: @ui-tee-default-color !important; border: 1px solid #dae2ea; } +.angular-ui-tree-handle.org-unit-origin-fk-org { + background-color: @fkorg-orgunit-color !important; + color: @fkorg-orgunit_font-color !important; + + .glyphicon { + color: @fkorg-orgunit_font-color; + } +} + div.angular-ui-tree-handle.selected { background-color: rgb(55, 96, 146) !important; + color: @ui-tree-selected_font-color !important; } -div.angular-ui-tree-handle.selected a span { - color: white !important; +div.angular-ui-tree-handle.selected.org-unit-origin-fk-org { + background-color: @fkorg-orgunit-color_selected !important; + color: @ui-tree-selected_font-color !important; + + .glyphicon { + color: @ui-tree-selected_font-color; + } } -div.angular-ui-tree-handle.selected { - color: white !important; +div.angular-ui-tree-handle.selected a span { + color: @ui-tree-selected_font-color !important; } .angular-ui-tree-handle:hover { @@ -931,6 +958,15 @@ div.angular-ui-tree-handle.selected { border-color: #dce2e8; } +.angular-ui-tree-handle:hover.org-unit-origin-fk-org { + background-color: @fkorg-orgunit-hover !important; + color: @fkorg-orgunit_font-color !important; + + .glyphicon { + color: @fkorg-orgunit_font-color; + } +} + .angular-ui-tree-placeholder { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; @@ -958,7 +994,7 @@ tr.angular-ui-tree-empty { background-color: #f2dede; } -.nonDragable .tree-node-content { +.nonDragable { cursor: pointer !important; } @@ -1591,6 +1627,42 @@ tbody.bordered > tr > td { color: #888; } +.right-margin-5px { + margin-right: 5px; +} + +.progress-spinner-img { + height: 20px; + width: 20px; +} + .width-fit-content { width: fit-content !important; } + +.org-structure-legend { + margin-top: 25px; + margin-left: 7px; + + .org-structure-legend-color { + display: inline-block; + width: 25px; + height: 9px; + } + + .org-structure-legend-color-native-unit { + background-color: @ui-tee-default-color; + } + + .org-structure-legend-color-fk-org-unit { + background-color: @fkorg-orgunit-color; + } +} + +.wide-modal .modal-dialog { + width: 1000px !important; +} + +.input-validation-error{ + color:maroon !important; +} \ No newline at end of file diff --git a/Presentation.Web/Controllers/API/V1/AuthorizeController.cs b/Presentation.Web/Controllers/API/V1/AuthorizeController.cs index c5e2167ad8..05133270cc 100644 --- a/Presentation.Web/Controllers/API/V1/AuthorizeController.cs +++ b/Presentation.Web/Controllers/API/V1/AuthorizeController.cs @@ -20,11 +20,11 @@ using Core.DomainServices.Extensions; using Infrastructure.Services.Cryptography; using Newtonsoft.Json; -using Presentation.Web.Extensions; using Presentation.Web.Helpers; using Presentation.Web.Infrastructure.Attributes; using Presentation.Web.Models.API.V1; using Swashbuckle.Swagger.Annotations; +using AuthenticationScheme = Core.DomainModel.Users.AuthenticationScheme; namespace Presentation.Web.Controllers.API.V1 { @@ -62,7 +62,7 @@ public HttpResponseMessage GetLogin() [Route("api/authorize/GetOrganizations")] [SwaggerResponse(HttpStatusCode.OK, Type = typeof(ApiReturnDTO>))] - public HttpResponseMessage GetOrganizations([FromUri]string orderBy = null, [FromUri]bool? orderByAsc = true) + public HttpResponseMessage GetOrganizations([FromUri] string orderBy = null, [FromUri] bool? orderByAsc = true) { var orgs = GetOrganizationsWithMembershipAccess(); @@ -142,7 +142,7 @@ public HttpResponseMessage GetToken(LoginDTO loginDto) } try { - var result = AuthenticateUser(loginDto); + var result = AuthenticateUser(loginDto, AuthenticationScheme.Token); if (result.Failed) { @@ -151,12 +151,6 @@ public HttpResponseMessage GetToken(LoginDTO loginDto) var user = result.Value; - if (CanIssueTokenTo(user)) - { - Logger.Warn("User with Id {id} tried to use get a token for the API but was forbidden", user.Id); - return Forbidden(); - } - var token = new TokenValidator().CreateToken(user); var response = new GetTokenResponseDTO @@ -196,7 +190,7 @@ public HttpResponseMessage PostLogin(LoginDTO loginDto) try { - var result = AuthenticateUser(loginDto); + var result = AuthenticateUser(loginDto, AuthenticationScheme.Cookie); if (result.Failed) { @@ -284,8 +278,8 @@ public HttpResponseMessage GetAntiForgeryToken() return response; } - - private Result AuthenticateUser(LoginDTO loginDto) + + private Result AuthenticateUser(LoginDTO loginDto, AuthenticationScheme authenticationScheme) { if (!Membership.ValidateUser(loginDto.Email, loginDto.Password)) { @@ -304,12 +298,12 @@ private Result AuthenticateUser(LoginDTO loginDto) } } - if (user.CanAuthenticate()) + if (user.GetAuthenticationSchemes().Contains(authenticationScheme)) { return user; } - Logger.Info("'AUTH FAILED: Non-global admin' User with id {userId} and no organization rights denied access", user.Id); + Logger.Info("'AUTH FAILED: Non-global admin' User with id {userId} and no organization rights or wrong scheme {scheme} denied access", user.Id, authenticationScheme); { return Unauthorized(); } diff --git a/Presentation.Web/Controllers/API/V1/ItContractController.cs b/Presentation.Web/Controllers/API/V1/ItContractController.cs index 4e00df1f5d..8372858498 100644 --- a/Presentation.Web/Controllers/API/V1/ItContractController.cs +++ b/Presentation.Web/Controllers/API/V1/ItContractController.cs @@ -6,9 +6,9 @@ using System.Security; using System.Web.Http; using Core.Abstractions.Types; -using Core.ApplicationServices; using Core.ApplicationServices.Contract; using Core.DomainModel; +using Core.DomainModel.Extensions; using Core.DomainModel.ItContract; using Core.DomainModel.ItSystemUsage; using Core.DomainServices; @@ -264,13 +264,8 @@ public HttpResponseMessage GetHierarchy(int id, [FromUri] bool? hierarchy) { return Forbidden(); } - // this trick will put the first object in the result as well as the children - var children = new[] { itContract }.SelectNestedChildren(x => x.Children); - // gets parents only - var parents = itContract.SelectNestedParents(x => x.Parent); - // put it all in one result - var contracts = children.Union(parents); - return Ok(Map(contracts)); + + return Ok(Map(itContract.FlattenCompleteHierarchy().ToList())); } catch (Exception e) { diff --git a/Presentation.Web/Controllers/API/V1/OData/AdviceController.cs b/Presentation.Web/Controllers/API/V1/OData/AdviceController.cs index ece3f77b41..a90e08df97 100644 --- a/Presentation.Web/Controllers/API/V1/OData/AdviceController.cs +++ b/Presentation.Web/Controllers/API/V1/OData/AdviceController.cs @@ -284,7 +284,7 @@ public override IHttpActionResult Delete(int key) [ODataRoute("DeactivateAdvice")] public IHttpActionResult DeactivateAdvice([FromODataUri] int key) { - var transaction = _transactionManager.Begin(); + using var transaction = _transactionManager.Begin(); var entity = Repository.AsQueryable().ById(key); if (entity == null) return NotFound(); @@ -299,6 +299,7 @@ public IHttpActionResult DeactivateAdvice([FromODataUri] int key) } catch (Exception e) { + transaction.Rollback(); Logger.ErrorException("Failed to delete advice", e); return StatusCode(HttpStatusCode.InternalServerError); } diff --git a/Presentation.Web/Controllers/API/V1/OData/ItContractsController.cs b/Presentation.Web/Controllers/API/V1/OData/ItContractsController.cs index 870b7eaeb6..0b2498a9fa 100644 --- a/Presentation.Web/Controllers/API/V1/OData/ItContractsController.cs +++ b/Presentation.Web/Controllers/API/V1/OData/ItContractsController.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Net; using System.Web.Http; @@ -7,9 +6,6 @@ using Microsoft.AspNet.OData.Routing; using Core.DomainModel.ItContract; using Core.DomainServices; -using Core.DomainServices.Authorization; -using Core.DomainServices.Extensions; -using Core.DomainServices.Repositories.Organization; using Presentation.Web.Infrastructure.Attributes; using Swashbuckle.OData; using Swashbuckle.Swagger.Annotations; @@ -19,12 +15,9 @@ namespace Presentation.Web.Controllers.API.V1.OData [PublicApi] public class ItContractsController : BaseEntityController { - private readonly IOrganizationUnitRepository _organizationUnitRepository; - - public ItContractsController(IGenericRepository repository, IOrganizationUnitRepository organizationUnitRepository) + public ItContractsController(IGenericRepository repository) : base(repository) { - _organizationUnitRepository = organizationUnitRepository; } /// @@ -41,52 +34,6 @@ public override IHttpActionResult Get() return base.Get(); } - /// - /// Henter alle organisationens IT Kontrakter - /// - /// - /// - [EnableQuery(MaxExpansionDepth = 3)] - [ODataRoute("Organizations({key})/ItContracts")] - [SwaggerResponse(HttpStatusCode.OK, Type = typeof(ODataResponse>))] - [SwaggerResponse(HttpStatusCode.Forbidden)] - [RequireTopOnOdataThroughKitosToken] - public IHttpActionResult GetItContracts(int key) - { - var organizationDataReadAccessLevel = GetOrganizationReadAccessLevel(key); - if (organizationDataReadAccessLevel != OrganizationDataReadAccessLevel.All) - { - return Forbidden(); - } - - var result = Repository.AsQueryable().ByOrganizationId(key); - - return Ok(result); - } - - [EnableQuery(MaxExpansionDepth = 3)] - [ODataRoute("Organizations({orgKey})/OrganizationUnits({unitKey})/ItContracts")] - [SwaggerResponse(HttpStatusCode.OK, Type = typeof(ODataResponse>))] - [SwaggerResponse(HttpStatusCode.Forbidden)] - [RequireTopOnOdataThroughKitosToken] - public IHttpActionResult GetItContractsByOrgUnit(int orgKey, int unitKey) - { - var organizationDataReadAccessLevel = GetOrganizationReadAccessLevel(orgKey); - if (organizationDataReadAccessLevel < OrganizationDataReadAccessLevel.Public) - { - return Forbidden(); - } - - var orgUnitTreeIds = _organizationUnitRepository.GetIdsOfSubTree(orgKey, unitKey).ToList(); - - var result = Repository - .AsQueryable() - .ByOrganizationId(orgKey) - .Where(usage => usage.ResponsibleOrganizationUnitId != null && orgUnitTreeIds.Contains(usage.ResponsibleOrganizationUnitId.Value)); - - return Ok(result); - } - [NonAction] public override IHttpActionResult Post(int organizationId, ItContract entity) => throw new NotSupportedException(); } diff --git a/Presentation.Web/Controllers/API/V1/OData/ItSystemUsagesController.cs b/Presentation.Web/Controllers/API/V1/OData/ItSystemUsagesController.cs index 300c034794..d95b430599 100644 --- a/Presentation.Web/Controllers/API/V1/OData/ItSystemUsagesController.cs +++ b/Presentation.Web/Controllers/API/V1/OData/ItSystemUsagesController.cs @@ -1,15 +1,6 @@ -using System.Collections.Generic; -using System.Web.Http; -using Microsoft.AspNet.OData; -using Microsoft.AspNet.OData.Routing; -using System.Net; -using Core.DomainModel.ItSystemUsage; +using Core.DomainModel.ItSystemUsage; using Core.DomainServices; -using Core.DomainServices.Authorization; -using Core.DomainServices.Extensions; using Presentation.Web.Infrastructure.Attributes; -using Swashbuckle.OData; -using Swashbuckle.Swagger.Annotations; namespace Presentation.Web.Controllers.API.V1.OData { @@ -20,31 +11,5 @@ public ItSystemUsagesController(IGenericRepository repository) : base(repository) { } - - /// - /// Henter alle organisationens IT-Systemanvendelser. - /// - /// - /// - [EnableQuery(MaxExpansionDepth = 4)] // MaxExpansionDepth is 4 because we need to do MainContract($expand=ItContract($expand=Supplier)) - [ODataRoute("Organizations({orgKey})/ItSystemUsages")] - [SwaggerResponse(HttpStatusCode.OK, Type = typeof(ODataResponse>))] - [SwaggerResponse(HttpStatusCode.Forbidden)] - [RequireTopOnOdataThroughKitosToken] - public IHttpActionResult GetItSystems(int orgKey) - { - //Usages are local so full access is required - var accessLevel = GetOrganizationReadAccessLevel(orgKey); - if (accessLevel < OrganizationDataReadAccessLevel.All) - { - return Forbidden(); - } - - var result = Repository - .AsQueryable() - .ByOrganizationId(orgKey); - - return Ok(result); - } } } diff --git a/Presentation.Web/Controllers/API/V1/OData/OrganizationUnitsController.cs b/Presentation.Web/Controllers/API/V1/OData/OrganizationUnitsController.cs index d346cb9263..f05f260be3 100644 --- a/Presentation.Web/Controllers/API/V1/OData/OrganizationUnitsController.cs +++ b/Presentation.Web/Controllers/API/V1/OData/OrganizationUnitsController.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System; using System.Web.Http; using Microsoft.AspNet.OData; using Microsoft.AspNet.OData.Routing; @@ -41,5 +41,14 @@ public IHttpActionResult GetOrganizationUnits(int orgKey) return Ok(result); } + + [NonAction] + public override IHttpActionResult Delete(int key) => throw new NotSupportedException(); + + [NonAction] + public override IHttpActionResult Post(int organizationId, OrganizationUnit entity) => throw new NotSupportedException(); + + [NonAction] + public override IHttpActionResult Patch(int key, Delta delta) => throw new NotSupportedException(); } } diff --git a/Presentation.Web/Controllers/API/V1/OrganizationUnitController.cs b/Presentation.Web/Controllers/API/V1/OrganizationUnitController.cs index 480869998f..fb3ec7fd7b 100644 --- a/Presentation.Web/Controllers/API/V1/OrganizationUnitController.cs +++ b/Presentation.Web/Controllers/API/V1/OrganizationUnitController.cs @@ -3,7 +3,8 @@ using System.Linq; using System.Net.Http; using System.Web.Http; -using Core.ApplicationServices; +using Core.ApplicationServices.Organizations; +using Core.DomainModel.Extensions; using Core.DomainModel.Organization; using Core.DomainServices; using Core.DomainServices.Authorization; @@ -18,19 +19,16 @@ namespace Presentation.Web.Controllers.API.V1 public class OrganizationUnitController : GenericHierarchyApiController { private readonly IOrgUnitService _orgUnitService; - private readonly IGenericRepository _taskRepository; - private readonly IGenericRepository _taskUsageRepository; + private readonly IOrganizationUnitService _organizationUnitService; public OrganizationUnitController( IGenericRepository repository, IOrgUnitService orgUnitService, - IGenericRepository taskRepository, - IGenericRepository taskUsageRepository) + IOrganizationUnitService organizationUnitService) : base(repository) { _orgUnitService = orgUnitService; - _taskRepository = taskRepository; - _taskUsageRepository = taskUsageRepository; + _organizationUnitService = organizationUnitService; } public HttpResponseMessage Post(OrgUnitDTO dto) => base.Post(dto.OrganizationId, dto); @@ -59,9 +57,7 @@ public HttpResponseMessage GetByUser(bool? byUser, int organizationId) var userId = UserId; var orgUnits = Repository .Get(x => x.Rights.Any(y => y.UserId == userId) && x.OrganizationId == organizationId) - .SelectNestedChildren(x => x.Children).ToList(); - - orgUnits = orgUnits + .SelectMany(unit => unit.FlattenHierarchy()) .Distinct() .ToList(); @@ -124,20 +120,50 @@ public override HttpResponseMessage Patch(int id, int organizationId, JObject ob { try { - JToken jtoken; - if (obj.TryGetValue("parentId", out jtoken)) + var unit = Repository + .AsQueryable() + .ById(id); + if (unit == null) + { + return BadRequest($"Unit with id: {id} was not found"); + } + + var accessRightsResult = _organizationUnitService.GetAccessRights(unit.Organization.Uuid, unit.Uuid); + if (accessRightsResult.Failed) { - //TODO: You have to be local or global admin to change parent + return FromOperationError(accessRightsResult.Error); + } + var accessRights = accessRightsResult.Value; + if (obj.TryGetValue("parentId", out var jtoken)) + { var parentId = jtoken.Value(); + if (parentId != unit.ParentId.GetValueOrDefault()) + { + if (!accessRights.CanBeRearranged) + { + return BadRequest("Unit cannot change its parent"); + } + } //if the new parent is actually a descendant of the item, don't update - this would create a loop! - if (_orgUnitService.IsAncestorOf(parentId, id)) + if (_orgUnitService.DescendsFrom(parentId, id)) { return Conflict("OrgUnit loop detected"); } } + if (obj.TryGetValue("name", out jtoken)) + { + var newName = jtoken.Value(); + if (newName != unit.Name) + { + if (!accessRights.CanBeRenamed) + { + return BadRequest("Unit cannot be renamed"); + } + } + } } catch (Exception e) { @@ -149,128 +175,7 @@ public override HttpResponseMessage Patch(int id, int organizationId, JObject ob [NonAction] public override HttpResponseMessage Put(int id, int organizationId, JObject jObject) => throw new NotSupportedException(); - /// - /// Returns every task that a given OrgUnit can use. This depends on the task usages of the parent OrgUnit. - /// For every task returned, possibly a taskUsage is returned too, if the OrgUnit is currently using that task. - /// - /// ID of the OrgUnit - /// Optional id to filter by task group - /// Routing qualifier - /// Paging options - /// List of (task, taskUsage), where the taskUsage might be null - public HttpResponseMessage GetAccessibleTasks(int id, int? taskGroup, bool? tasks, [FromUri] PagingModel pagingModel) - { - try - { - var orgUnit = Repository.GetByKey(id); - - if (orgUnit == null) - return NotFound(); - - if (!AllowRead(orgUnit)) - return Forbidden(); - - IQueryable taskQuery; - // if the org unit has a parent, only select those tasks that is in use by the parent org unit - if (orgUnit.ParentId.HasValue) - { - // this is not so good performance wise - var orgUnitQueryable = Repository.AsQueryable().Where(unit => unit.Id == id); - taskQuery = orgUnitQueryable.SelectMany(u => u.Parent.TaskUsages.Select(usage => usage.TaskRef)); - - // it would have been better with: - // pagingModel.Where(taskRef => taskRef.Usages.Any(usage => usage.OrgUnitId == orgUnit.ParentId)); - // but we cant because of a bug in the mysql connector: http://bugs.mysql.com/bug.php?id=70722 - } - else - { - taskQuery = _taskRepository.AsQueryable(); - } - - // if a task group is given, only find the tasks in that group and sub groups - if (taskGroup.HasValue) - { - pagingModel.Where( - taskRef => - (taskRef.ParentId.Value == taskGroup.Value || - taskRef.Parent.ParentId.Value == taskGroup.Value) && - !taskRef.Children.Any()); - } - else - { - // else get all task leaves - pagingModel.Where(taskRef => !taskRef.Children.Any()); - } - - var theTasks = Page(taskQuery, pagingModel).ToList(); - - // convert tasks to DTO containing both the task and possibly also a taskUsage, if that exists - var dtos = (from taskRef in theTasks - let taskUsage = taskRef.Usages.FirstOrDefault(usage => usage.OrgUnitId == id) - select new TaskRefUsageDTO() - { - TaskRef = Map(taskRef), - Usage = Map(taskUsage) - }).ToList(); // must call .ToList here else the output will be wrapped in $type,$values - - return Ok(dtos); - } - catch (Exception e) - { - return LogError(e); - } - } - - /// - /// Returns the task usages of a given OrgUnit. - /// - /// ID of the OrgUnit - /// Optional id of a taskgroup - /// Routing qualifier - /// Paging options - /// List of (task, taskUsage) - public HttpResponseMessage GetTaskUsages(int id, int? taskGroup, bool? usages, - [FromUri] PagingModel pagingModel) - { - try - { - var organizationUnit = Repository.GetByKey(id); - if (organizationUnit == null) - return NotFound(); - - if (!AllowRead(organizationUnit)) - return Forbidden(); - - var usageQuery = _taskUsageRepository.AsQueryable(); - pagingModel.Where(usage => usage.OrgUnitId == id); - - // if a task group is given, only find the tasks in that group and sub groups - if (taskGroup.HasValue) - { - pagingModel.Where(taskUsage => taskUsage.TaskRef.ParentId.Value == taskGroup.Value || - taskUsage.TaskRef.Parent.ParentId.Value == taskGroup.Value); - } - - var theUsages = Page(usageQuery, pagingModel).ToList(); - - var dtos = (from usage in theUsages - select new TaskRefUsageDTO() - { - TaskRef = Map(usage.TaskRef), - Usage = Map(usage) - }).ToList(); // must call .ToList here else the output will be wrapped in $type,$values - - return Ok(dtos); - } - catch (Exception e) - { - return LogError(e); - } - } - - protected override void DeleteQuery(OrganizationUnit entity) - { - _orgUnitService.Delete(entity.Id); - } + [NonAction] + public override HttpResponseMessage Delete(int id, int organizationId) => throw new NotSupportedException(); } } diff --git a/Presentation.Web/Controllers/API/V1/OrganizationUnitLifeCycleController.cs b/Presentation.Web/Controllers/API/V1/OrganizationUnitLifeCycleController.cs new file mode 100644 index 0000000000..d05538f493 --- /dev/null +++ b/Presentation.Web/Controllers/API/V1/OrganizationUnitLifeCycleController.cs @@ -0,0 +1,36 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Web.Http; +using Core.ApplicationServices.Organizations; +using Presentation.Web.Infrastructure.Attributes; +using Swashbuckle.Swagger.Annotations; + +namespace Presentation.Web.Controllers.API.V1 +{ + [PublicApi] + [RoutePrefix("api/v1/organizations/{organizationUuid}/organization-units/{unitUuid}")] + + public class OrganizationUnitLifeCycleController : BaseApiController + { + private readonly IOrganizationUnitService _organizationUnitService; + + public OrganizationUnitLifeCycleController(IOrganizationUnitService organizationUnitService) + { + _organizationUnitService = organizationUnitService; + } + + [HttpDelete] + [Route("")] + [SwaggerResponse(HttpStatusCode.OK)] + [SwaggerResponse(HttpStatusCode.Forbidden)] + [SwaggerResponse(HttpStatusCode.BadRequest)] + [SwaggerResponse(HttpStatusCode.NotFound)] + public HttpResponseMessage Delete(Guid organizationUuid, Guid unitUuid) + { + return _organizationUnitService + .Delete(organizationUuid, unitUuid) + .Match(FromOperationError, Ok); + } + } +} \ No newline at end of file diff --git a/Presentation.Web/Controllers/API/V1/OrganizationUnitPermissionsController.cs b/Presentation.Web/Controllers/API/V1/OrganizationUnitPermissionsController.cs new file mode 100644 index 0000000000..32d78f8a11 --- /dev/null +++ b/Presentation.Web/Controllers/API/V1/OrganizationUnitPermissionsController.cs @@ -0,0 +1,74 @@ +using System.Collections.Generic; +using System.Net.Http; +using System.Net; +using System; +using System.Linq; +using System.Web.Http; +using Core.DomainModel.Organization; +using Presentation.Web.Infrastructure.Attributes; +using Presentation.Web.Models.API.V1.Organizations; +using Swashbuckle.Swagger.Annotations; +using Core.ApplicationServices.Organizations; + +namespace Presentation.Web.Controllers.API.V1 +{ + [PublicApi] + [RoutePrefix("api/v1/organizations/{organizationUuid}/organization-units")] + public class OrganizationUnitPermissionsController : BaseApiController + { + private readonly IOrganizationUnitService _organizationUnitService; + + public OrganizationUnitPermissionsController(IOrganizationUnitService organizationUnitService) + { + _organizationUnitService = organizationUnitService; + } + + [HttpGet] + [Route("{unitUuid}/access-rights")] + [SwaggerResponse(HttpStatusCode.OK)] + [SwaggerResponse(HttpStatusCode.Forbidden)] + [SwaggerResponse(HttpStatusCode.NotFound)] + public HttpResponseMessage GetUnitAccessRights(Guid organizationUuid, Guid unitUuid) + { + return _organizationUnitService.GetAccessRights(organizationUuid, unitUuid) + .Select(ToAccessRightsDto) + .Match(Ok, FromOperationError); + } + + [HttpGet] + [Route("all/access-rights")] + [SwaggerResponse(HttpStatusCode.OK)] + [SwaggerResponse(HttpStatusCode.Forbidden)] + [SwaggerResponse(HttpStatusCode.NotFound)] + public HttpResponseMessage GetUnitAccessRightsForOrganization(Guid organizationUuid) + { + return _organizationUnitService.GetAccessRightsByOrganization(organizationUuid) + .Select(ToUnitAccessRightsDtoWithUnitIdDtos) + .Match(Ok, FromOperationError); + } + + private static UnitAccessRightsDTO ToAccessRightsDto( + UnitAccessRights accessRights) + { + return new UnitAccessRightsDTO( + accessRights.CanBeRead, + accessRights.CanBeModified, + accessRights.CanBeRenamed, + accessRights.CanEanBeModified, + accessRights.CanDeviceIdBeModified, + accessRights.CanBeRearranged, + accessRights.CanBeDeleted); + } + + private static IEnumerable ToUnitAccessRightsDtoWithUnitIdDtos( + IEnumerable accessRights) + { + return accessRights.Select(ToUnitAccessRightsWithUnitIdDto).ToList(); + } + + private static UnitAccessRightsWithUnitIdDTO ToUnitAccessRightsWithUnitIdDto(UnitAccessRightsWithUnitData x) + { + return new UnitAccessRightsWithUnitIdDTO(x.OrganizationUnit.Id, ToAccessRightsDto(x.UnitAccessRights)); + } + } +} \ No newline at end of file diff --git a/Presentation.Web/Controllers/API/V1/OrganizationUnitRegistrationController.cs b/Presentation.Web/Controllers/API/V1/OrganizationUnitRegistrationController.cs new file mode 100644 index 0000000000..d7d8b9d6d1 --- /dev/null +++ b/Presentation.Web/Controllers/API/V1/OrganizationUnitRegistrationController.cs @@ -0,0 +1,121 @@ +using System; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Web.Http; +using Core.ApplicationServices.Model.Organizations; +using Core.ApplicationServices.Organizations; +using Core.DomainModel.ItContract; +using Core.DomainModel.Organization; +using Presentation.Web.Controllers.API.V1.Mapping; +using Presentation.Web.Infrastructure.Attributes; +using Presentation.Web.Models.API.V1; +using Presentation.Web.Models.API.V1.Organizations; +using Swashbuckle.Swagger.Annotations; + +namespace Presentation.Web.Controllers.API.V1 +{ + [PublicApi] + [RoutePrefix("api/v1/organizations/{organizationUuid}/organization-units/{unitUuid}")] + + public class OrganizationUnitRegistrationController: BaseApiController + { + private readonly IOrganizationUnitService _organizationUnitService; + + public OrganizationUnitRegistrationController(IOrganizationUnitService organizationUnitService) + { + _organizationUnitService = organizationUnitService; + } + + [HttpGet] + [Route("registrations")] + [SwaggerResponse(HttpStatusCode.OK)] + [SwaggerResponse(HttpStatusCode.Forbidden)] + [SwaggerResponse(HttpStatusCode.NotFound)] + public HttpResponseMessage GetRegistrations(Guid organizationUuid, Guid unitUuid) + { + return _organizationUnitService.GetRegistrations(organizationUuid, unitUuid) + .Select(ToRegistrationDto) + .Match(Ok, FromOperationError); + } + + [HttpDelete] + [Route("registrations")] + [SwaggerResponse(HttpStatusCode.OK)] + [SwaggerResponse(HttpStatusCode.Forbidden)] + [SwaggerResponse(HttpStatusCode.NotFound)] + public HttpResponseMessage RemoveRegistrations(Guid organizationUuid, Guid unitUuid, [FromBody] ChangeOrganizationUnitRegistrationRequestDTO requestDto) + { + var changeParameters = ToChangeParameters(requestDto); + return _organizationUnitService.DeleteRegistrations(organizationUuid, unitUuid, changeParameters) + .Match(FromOperationError, Ok); + } + + [HttpPut] + [Route("registrations")] + [SwaggerResponse(HttpStatusCode.OK)] + [SwaggerResponse(HttpStatusCode.Forbidden)] + [SwaggerResponse(HttpStatusCode.NotFound)] + public HttpResponseMessage TransferRegistrations(Guid organizationUuid, Guid unitUuid, [FromBody] TransferOrganizationUnitRegistrationRequestDTO requestDto) + { + var changeParameters = ToChangeParameters(requestDto); + return _organizationUnitService.TransferRegistrations(organizationUuid, unitUuid, requestDto.TargetUnitUuid, changeParameters) + .Match(FromOperationError, Ok); + } + + private static OrganizationRegistrationUnitDTO ToRegistrationDto(OrganizationUnitRegistrationDetails details) + { + return new OrganizationRegistrationUnitDTO + { + OrganizationUnitRights = details.OrganizationUnitRights.Select(MapUnitRightToNamedEntityDtoWithUserFullNameDto).ToList(), + ItContractRegistrations = details.ItContractRegistrations.Select(x => x.MapToNamedEntityDTO()).ToList(), + Payments = details.PaymentRegistrationDetails.Select(ToPaymentRegistrationDto).ToList(), + RelevantSystems = details.RelevantSystems.Select(x => x.MapToNamedEntityWithEnabledStatusDTO()).ToList(), + ResponsibleSystems = details.ResponsibleSystems.Select(x => x.MapToNamedEntityWithEnabledStatusDTO()).ToList() + }; + } + + private static PaymentRegistrationDTO ToPaymentRegistrationDto(PaymentRegistrationDetails details) + { + return new PaymentRegistrationDTO + { + ItContract = details.ItContract.MapToNamedEntityDTO(), + InternalPayments = details.InternalPayments.Select(MapPaymentToNamedEntityDto).ToList(), + ExternalPayments = details.ExternalPayments.Select(MapPaymentToNamedEntityDto).ToList() + }; + } + + private static NamedEntityWithUserFullNameDTO MapUnitRightToNamedEntityDtoWithUserFullNameDto(OrganizationUnitRight right) + { + return new NamedEntityWithUserFullNameDTO + { + Id = right.Id, + Name = right.Role.Name, + UserFullName = right.User.GetFullName() + }; + } + + private static NamedEntityDTO MapPaymentToNamedEntityDto(EconomyStream payment) + { + return new NamedEntityDTO + { + Id = payment.Id, + Name = $"{payment.Acquisition}, {payment.Operation}, {payment.Other}" + }; + } + + private static OrganizationUnitRegistrationChangeParameters ToChangeParameters( + ChangeOrganizationUnitRegistrationRequestDTO requestDto) + { + return new OrganizationUnitRegistrationChangeParameters + ( + requestDto.OrganizationUnitRights, + requestDto.ItContractRegistrations, + requestDto.PaymentRegistrationDetails.Select(x => + new PaymentChangeParameters(x.ItContractId, x.InternalPayments, x.ExternalPayments)), + requestDto.ResponsibleSystems, + requestDto.RelevantSystems + ); + } + } +} \ No newline at end of file diff --git a/Presentation.Web/Controllers/API/V1/StsOrganizationSynchronizationController.cs b/Presentation.Web/Controllers/API/V1/StsOrganizationSynchronizationController.cs index 0b9a009cad..feede2d6d0 100644 --- a/Presentation.Web/Controllers/API/V1/StsOrganizationSynchronizationController.cs +++ b/Presentation.Web/Controllers/API/V1/StsOrganizationSynchronizationController.cs @@ -1,10 +1,11 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Web.Http; using Core.Abstractions.Extensions; using Core.ApplicationServices.Organizations; -using Core.DomainServices.Model.StsOrganization; +using Core.DomainModel.Organization; using Presentation.Web.Infrastructure.Attributes; using Presentation.Web.Models.API.V1.Organizations; @@ -23,7 +24,7 @@ public StsOrganizationSynchronizationController(IStsOrganizationSynchronizationS [HttpGet] [Route("snapshot")] - public HttpResponseMessage GetSnapshotFromStsOrganization(Guid organizationId, uint? levels = null) + public HttpResponseMessage GetSnapshotFromStsOrganization(Guid organizationId, int? levels = null) { return _stsOrganizationSynchronizationService .GetStsOrganizationalHierarchy(organizationId, levels.FromNullableValueType()) @@ -31,15 +32,191 @@ public HttpResponseMessage GetSnapshotFromStsOrganization(Guid organizationId, u .Match(Ok, FromOperationError); } - private static StsOrganizationOrgUnitDTO MapOrganizationUnitDTO(StsOrganizationUnit organizationUnit) + [HttpGet] + [Route("connection-status")] + public HttpResponseMessage GetSynchronizationStatus(Guid organizationId) + { + return _stsOrganizationSynchronizationService + .GetSynchronizationDetails(organizationId) + .Select(details => new StsOrganizationSynchronizationDetailsResponseDTO + { + Connected = details.Connected, + SynchronizationDepth = details.SynchronizationDepth, + CanCreateConnection = details.CanCreateConnection, + CanDeleteConnection = details.CanDeleteConnection, + CanUpdateConnection = details.CanUpdateConnection, + AccessStatus = new StsOrganizationAccessStatusResponseDTO + { + AccessGranted = details.CheckConnectionError == null, + Error = details.CheckConnectionError + } + }) + .Match(Ok, FromOperationError); + + } + + [HttpPost] + [Route("connection")] + public HttpResponseMessage CreateConnection(Guid organizationId, [FromBody] ConnectToStsOrganizationRequestDTO request) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + return _stsOrganizationSynchronizationService + .Connect(organizationId, (request?.SynchronizationDepth).FromNullableValueType()) + .Match(FromOperationError, Ok); + } + + [HttpDelete] + [Route("connection")] + public HttpResponseMessage Disconnect(Guid organizationId) + { + return _stsOrganizationSynchronizationService + .Disconnect(organizationId) + .Match(FromOperationError, Ok); + } + + [HttpGet] + [Route("connection/update")] + public HttpResponseMessage GetUpdateConsequences(Guid organizationId, int? synchronizationDepth = null) + { + if (synchronizationDepth is < 1) + { + return BadRequest($"{nameof(synchronizationDepth)} must greater than 0"); + } + + return _stsOrganizationSynchronizationService + .GetConnectionExternalHierarchyUpdateConsequences(organizationId, synchronizationDepth.FromNullableValueType()) + .Select(MapUpdateConsequencesResponseDTO) + .Match(Ok, FromOperationError); + } + + [HttpPut] + [Route("connection")] + public HttpResponseMessage UpdateConnection(Guid organizationId, [FromBody] ConnectToStsOrganizationRequestDTO request) + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + return _stsOrganizationSynchronizationService + .UpdateConnection(organizationId, (request?.SynchronizationDepth).FromNullableValueType()) + .Match(FromOperationError, Ok); + } + + #region DTO Mapping + private static ConnectionUpdateConsequencesResponseDTO MapUpdateConsequencesResponseDTO(OrganizationTreeUpdateConsequences consequences) + { + var dtos = new List(); + dtos.AddRange(MapAddedOrganizationUnits(consequences)); + dtos.AddRange(MapRenamedOrganizationUnits(consequences)); + dtos.AddRange(MapMovedOrganizationUnits(consequences)); + dtos.AddRange(MapRemovedOrganizationUnits(consequences)); + dtos.AddRange(MapConvertedOrganizationUnits(consequences)); + return new ConnectionUpdateConsequencesResponseDTO + { + Consequences = dtos + .OrderBy(x => x.Name) + .ThenBy(x => x.Category) + .ToList() + }; + } + + private static IEnumerable MapConvertedOrganizationUnits(OrganizationTreeUpdateConsequences consequences) + { + return consequences + .DeletedExternalUnitsBeingConvertedToNativeUnits + .Select(converted => new ConnectionUpdateOrganizationUnitConsequenceDTO + { + Name = converted.Name, + Category = ConnectionUpdateOrganizationUnitChangeCategory.Converted, + Uuid = converted.ExternalOriginUuid.GetValueOrDefault(), + Description = $"'{converted.Name}' er slettet i FK Organisation men konverteres til KITOS enhed, da den anvendes aktivt i KITOS." + }) + .ToList(); + } + + private static IEnumerable MapRemovedOrganizationUnits(OrganizationTreeUpdateConsequences consequences) + { + return consequences + .DeletedExternalUnitsBeingDeleted + .Select(deleted => new ConnectionUpdateOrganizationUnitConsequenceDTO + { + Name = deleted.Name, + Category = ConnectionUpdateOrganizationUnitChangeCategory.Deleted, + Uuid = deleted.ExternalOriginUuid.GetValueOrDefault(), + Description = $"'{deleted.Name}' slettes." + }) + .ToList(); + } + + private static IEnumerable MapMovedOrganizationUnits(OrganizationTreeUpdateConsequences consequences) + { + return consequences + .OrganizationUnitsBeingMoved + .Select(moved => + { + var (movedUnit, oldParent, newParent) = moved; + return new ConnectionUpdateOrganizationUnitConsequenceDTO + { + Name = movedUnit.Name, + Category = ConnectionUpdateOrganizationUnitChangeCategory.Moved, + Uuid = movedUnit.ExternalOriginUuid.GetValueOrDefault(), + Description = $"'{movedUnit.Name}' flyttes fra at være underenhed til '{oldParent.Name}' til fremover at være underenhed for {newParent.Name}" + }; + }) + .ToList(); + } + + private static IEnumerable MapRenamedOrganizationUnits(OrganizationTreeUpdateConsequences consequences) + { + return consequences + .OrganizationUnitsBeingRenamed + .Select(renamed => + { + var (affectedUnit, oldName, newName) = renamed; + return new ConnectionUpdateOrganizationUnitConsequenceDTO + { + Name = oldName, + Category = ConnectionUpdateOrganizationUnitChangeCategory.Renamed, + Uuid = affectedUnit.ExternalOriginUuid.GetValueOrDefault(), + Description = $"'{oldName}' omdøbes til '{newName}'" + }; + }) + .ToList(); + } + + private static IEnumerable MapAddedOrganizationUnits(OrganizationTreeUpdateConsequences consequences) + { + return consequences + .AddedExternalOrganizationUnits + .Select(added => new ConnectionUpdateOrganizationUnitConsequenceDTO + { + Name = added.unitToAdd.Name, + Category = ConnectionUpdateOrganizationUnitChangeCategory.Added, + Uuid = added.unitToAdd.Uuid, + Description = $"'{added.unitToAdd.Name}' tilføjes som underenhed til '{added.parent.Name}'" + } + ) + .ToList(); + } + + private static StsOrganizationOrgUnitDTO MapOrganizationUnitDTO(ExternalOrganizationUnit organizationUnit) { - return new StsOrganizationOrgUnitDTO() + return new StsOrganizationOrgUnitDTO { Uuid = organizationUnit.Uuid, Name = organizationUnit.Name, - UserFacingKey = organizationUnit.UserFacingKey, - Children = organizationUnit.Children.Select(MapOrganizationUnitDTO).ToList() + Children = organizationUnit + .Children + .OrderBy(x => x.Name) + .Select(MapOrganizationUnitDTO) + .ToList() }; } + #endregion DTO Mapping } } \ No newline at end of file diff --git a/Presentation.Web/Controllers/API/V1/TaskUsageController.cs b/Presentation.Web/Controllers/API/V1/TaskUsageController.cs deleted file mode 100644 index 6463451357..0000000000 --- a/Presentation.Web/Controllers/API/V1/TaskUsageController.cs +++ /dev/null @@ -1,328 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Dynamic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Text; -using System.Web.Http; -using Core.ApplicationServices; -using Core.DomainModel.ItSystemUsage; -using Core.DomainModel.Organization; -using Core.DomainServices; -using Core.DomainServices.Authorization; -using Newtonsoft.Json.Linq; -using Presentation.Web.Infrastructure.Attributes; -using Presentation.Web.Infrastructure.Authorization.Controller.Crud; -using Presentation.Web.Models.API.V1; -using Swashbuckle.Swagger.Annotations; - -namespace Presentation.Web.Controllers.API.V1 -{ - [PublicApi] - public class TaskUsageController : GenericHierarchyApiController - { - private readonly IGenericRepository _orgUnitRepository; - private readonly IGenericRepository _taskRepository; - - public TaskUsageController( - IGenericRepository repository, - IGenericRepository orgUnitRepository, - IGenericRepository taskRepository) - : base(repository) - { - _orgUnitRepository = orgUnitRepository; - _taskRepository = taskRepository; - } - - protected override IControllerCrudAuthorization GetCrudAuthorization() - { - return new ChildEntityCrudAuthorization(x => _orgUnitRepository.GetByKey(x.OrgUnitId), base.GetCrudAuthorization()); - } - - [HttpGet] - [Route("api/taskUsage/")] - [SwaggerResponse(HttpStatusCode.OK, Type = typeof(ApiReturnDTO>))] - public HttpResponseMessage Get(int orgUnitId, int organizationId, bool onlyStarred, [FromUri] PagingModel pagingModel) - { - try - { - if (GetOrganizationReadAccessLevel(organizationId) < OrganizationDataReadAccessLevel.All) - { - return Forbidden(); - } - - pagingModel.Where(usage => usage.OrgUnitId == orgUnitId); - - if (onlyStarred) pagingModel.Where(usage => usage.Starred); - - var usages = Page(Repository.AsQueryable(), pagingModel).ToList(); - - var dtos = new List(); - - foreach (var taskUsage in usages) - { - var dto = Map(taskUsage); - dto.HasWriteAccess = AllowModify(taskUsage); - dto.SystemUsages = AssociatedSystemUsages(taskUsage); - dtos.Add(dto); - } - - return Ok(dtos); - } - catch (Exception e) - { - return LogError(e); - } - } - - [HttpPost] - [Route("api/taskUsage/taskGroup")] - public HttpResponseMessage PostTaskGroup(int orgUnitId, int? taskId) - { - try - { - var orgUnit = _orgUnitRepository.GetByKey(orgUnitId); - if (orgUnit == null) - return NotFound(); - List tasks; - if (taskId.HasValue) - { - // get child leaves of taskId that havn't got a usage in the org unit - tasks = _taskRepository.Get( - x => - (x.ParentId == taskId || x.Parent.ParentId == taskId) && !x.Children.Any() && - x.Usages.All(y => y.OrgUnitId != orgUnitId)).ToList(); - } - else - { - // no taskId was specified so get everything - tasks = _taskRepository.Get( - x => - !x.Children.Any() && - x.Usages.All(y => y.OrgUnitId != orgUnitId)).ToList(); - } - - if (!tasks.Any()) - return NotFound(); - - foreach (var task in tasks) - { - var taskUsage = new TaskUsage() - { - OrgUnitId = orgUnitId, - TaskRefId = task.Id, - }; - if (!AllowCreate(orgUnit.OrganizationId, taskUsage)) - { - return Forbidden(); - } - Repository.Insert(taskUsage); - } - Repository.Save(); - return Ok(); - } - catch (Exception e) - { - return LogError(e); - } - } - - [NonAction] - public override HttpResponseMessage Post(int organizationId, TaskUsageDTO taskUsageDto) => throw new NotSupportedException(); - - [HttpPost] - [Route("api/taskUsage/")] - public HttpResponseMessage Post(CreateTaskUsageDTO taskUsageDto) - { - try - { - var item = new TaskUsage - { - TaskRefId = taskUsageDto.TaskRefId, - OrgUnitId = taskUsageDto.OrgUnitId, - }; - var organizationUnit = _orgUnitRepository.GetByKey(taskUsageDto.OrgUnitId); - if (organizationUnit == null) - { - return BadRequest("Invalid organizationId"); - } - if (!AllowCreate(organizationUnit.OrganizationId, item)) - { - return Forbidden(); - } - var savedItem = PostQuery(item); - - return Created(Map(savedItem), new Uri(Request.RequestUri + "/" + savedItem.Id)); - } - catch (Exception e) - { - // check if inner message is a duplicate, if so return conflict - if (e.InnerException?.InnerException != null) - { - if (e.InnerException.InnerException.Message.Contains("Duplicate entry")) - { - return Conflict(e.InnerException.InnerException.Message); - } - } - return LogError(e); - } - } - - [HttpDelete] - [Route("api/taskUsage/")] - public HttpResponseMessage DeleteTaskGroup(int orgUnitId, int? taskId) - { - try - { - var orgUnit = _orgUnitRepository.GetByKey(orgUnitId); - if (orgUnit == null) - return NotFound(); - - List taskUsages; - if (taskId.HasValue) - { - taskUsages = orgUnit.TaskUsages.Where( - taskUsage => taskUsage.TaskRef.ParentId == taskId || taskUsage.TaskRef.Parent.ParentId == taskId).ToList(); - } - else - { - // no taskId was specified so get everything - taskUsages = orgUnit.TaskUsages.ToList(); - } - - if (!taskUsages.Any()) - return NotFound(); - - foreach (var taskUsage in taskUsages) - { - if (!AllowDelete(taskUsage)) - { - return Forbidden(); - } - Repository.DeleteByKey(taskUsage.Id); - } - Repository.Save(); - return Ok(); - } - catch (Exception e) - { - return LogError(e); - } - } - - [HttpGet] - [Route("api/taskUsage/")] - public HttpResponseMessage GetExcel(bool? csv, int orgUnitId, bool onlyStarred) - { - try - { - var organizationUnit = _orgUnitRepository.GetByKey(orgUnitId); - - if (organizationUnit == null) - return NotFound(); - - if (!AllowRead(organizationUnit)) - return Forbidden(); - - var usages = Repository - .Get(usage => usage.OrgUnitId == orgUnitId && usage.Starred == onlyStarred); - - var dtos = new List(); - - foreach (var taskUsage in usages) - { - var dto = Map(taskUsage); - dto.SystemUsages = AssociatedSystemUsages(taskUsage); - dtos.Add(dto); - } - - var list = new List(); - var header = new ExpandoObject() as IDictionary; - header.Add("OrgUnit", "Organisationsenhed"); - header.Add("KLEID", "KLE ID"); - header.Add("KLENavn", "KLE Navn"); - header.Add("Teknologi", "Teknologi"); - header.Add("Anvendelse", "Anvendelse"); - header.Add("Kommentar", "Kommentar"); - header.Add("System", "IT System"); - list.Add(header); - - // Adding via recursive method so that children are - // placed directly after their parent in the output - Action addUsageToList = null; - addUsageToList = elem => - { - var obj = new ExpandoObject() as IDictionary; - obj.Add("OrgUnit", elem.OrgUnitName); - obj.Add("KLEID", elem.TaskRefTaskKey); - obj.Add("KLENavn", elem.TaskRefDescription); - obj.Add("Teknologi", elem.TechnologyStatus); - obj.Add("Anvendelse", elem.UsageStatus); - obj.Add("Kommentar", elem.Comment); - obj.Add("System", String.Join(",", elem.SystemUsages.Select(x => x.ItSystemName))); - list.Add(obj); - foreach (var child in elem.Children) - { - addUsageToList(child); // recursive call - } - }; - - foreach (var usage in dtos) - { - addUsageToList(usage); - } - var s = list.ToCsv(); - var bytes = Encoding.Unicode.GetBytes(s); - var stream = new MemoryStream(); - stream.Write(bytes, 0, bytes.Length); - stream.Seek(0, SeekOrigin.Begin); - - var result = new HttpResponseMessage(HttpStatusCode.OK); - result.Content = new StreamContent(stream); - result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv"); - result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileNameStar = "organisationsoverblik.csv", DispositionType = "ISO-8859-1" }; - return result; - } - catch (Exception e) - { - return LogError(e); - } - } - - protected override TaskUsage PostQuery(TaskUsage item) - { - var orgUnit = _orgUnitRepository.GetByKey(item.OrgUnitId); - - if (orgUnit.ParentId != null) - { - var parentUsage = orgUnit.Parent.TaskUsages.First(usage => usage.TaskRefId == item.TaskRefId); - item.Parent = parentUsage; - } - - return base.PostQuery(item); - } - - public override HttpResponseMessage Put(int id, int organizationId, JObject jObject) - { - return NotAllowed(); - } - - private IEnumerable AssociatedSystemUsages(TaskUsage taskUsage) - { - var indirectUsages = - taskUsage.TaskRef.ItSystems.SelectMany(system => system.Usages) - .Where(usage => usage.OrganizationId == taskUsage.OrgUnit.OrganizationId); - - var directUsages = - taskUsage.TaskRef.ItSystemUsages.Where( - usage => usage.OrganizationId == taskUsage.OrgUnit.OrganizationId); - - var allUsages = indirectUsages.Union(directUsages); - - return Map, IEnumerable>(allUsages); - } - } -} diff --git a/Presentation.Web/Controllers/API/V1/UserController.cs b/Presentation.Web/Controllers/API/V1/UserController.cs index 480fed64b7..8c43ff0bf2 100644 --- a/Presentation.Web/Controllers/API/V1/UserController.cs +++ b/Presentation.Web/Controllers/API/V1/UserController.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Net; using System.Net.Http; using System.Web; using System.Web.Http; @@ -32,20 +31,17 @@ public class UserController : GenericApiController private readonly IUserService _userService; private readonly IOrganizationService _organizationService; private readonly IUserRightsService _userRightsService; - private readonly IEntityIdentityResolver _identityResolver; public UserController( IGenericRepository repository, IUserService userService, IOrganizationService organizationService, - IUserRightsService userRightsService, - IEntityIdentityResolver identityResolver) + IUserRightsService userRightsService) : base(repository) { _userService = userService; _organizationService = organizationService; _userRightsService = userRightsService; - _identityResolver = identityResolver; } [NonAction] @@ -180,19 +176,10 @@ public HttpResponseMessage PostDefaultOrgUnit(bool? updateDefaultOrgUnit, Update } } - /// - /// Deletes user from the system - /// - /// The id of the user to be deleted - /// Not used in this case. Should remain empty - /// + [NonAction] public override HttpResponseMessage Delete(int id, int organizationId = 0) { - // NOTE: Only exists to apply optional param for org id - var uuid = _identityResolver.ResolveUuid(id); - return uuid.IsNone - ? NotFound() - : _userService.DeleteUserFromKitos(uuid.Value).Match(FromOperationError, Ok); + throw new NotSupportedException(); } diff --git a/Presentation.Web/Controllers/API/V1/UserDeletionController.cs b/Presentation.Web/Controllers/API/V1/UserDeletionController.cs new file mode 100644 index 0000000000..577bbc4177 --- /dev/null +++ b/Presentation.Web/Controllers/API/V1/UserDeletionController.cs @@ -0,0 +1,60 @@ +using System.Net; +using System.Net.Http; +using System.Web.Http; +using Core.ApplicationServices; +using Core.DomainModel; +using Core.DomainServices.Generic; +using Presentation.Web.Infrastructure.Attributes; +using Swashbuckle.Swagger.Annotations; + +namespace Presentation.Web.Controllers.API.V1 +{ + [PublicApi] + [RoutePrefix("api/v1/user/delete")] + public class UserDeletionController : BaseApiController + { + private readonly IUserService _userService; + private readonly IEntityIdentityResolver _identityResolver; + + public UserDeletionController(IUserService userService, IEntityIdentityResolver identityResolver) + { + _userService = userService; + _identityResolver = identityResolver; + } + + /// + /// Deletes user from the system + /// + /// The id of the user to be deleted + /// + [HttpDelete] + [Route("{id}")] + [SwaggerResponse(HttpStatusCode.OK)] + [SwaggerResponse(HttpStatusCode.Forbidden)] + [SwaggerResponse(HttpStatusCode.NotFound)] + [SwaggerResponse(HttpStatusCode.BadRequest)] + public HttpResponseMessage Delete(int id) + { + var uuid = _identityResolver.ResolveUuid(id); + return uuid.Match(val => _userService.DeleteUser(val).Match(FromOperationError, Ok), NotFound); + } + + /// + /// Deletes user from the organization + /// + /// The id of the user to be deleted + /// The id of the current organization from which the user is to be deleted + /// + [HttpDelete] + [Route("{id}/{organizationId}")] + [SwaggerResponse(HttpStatusCode.OK)] + [SwaggerResponse(HttpStatusCode.Forbidden)] + [SwaggerResponse(HttpStatusCode.NotFound)] + [SwaggerResponse(HttpStatusCode.BadRequest)] + public HttpResponseMessage Delete(int id, int organizationId) + { + var uuid = _identityResolver.ResolveUuid(id); + return uuid.Match(val => _userService.DeleteUser(val, organizationId).Match(FromOperationError, Ok), NotFound); + } + } +} \ No newline at end of file diff --git a/Presentation.Web/Controllers/API/V2/External/Organizations/OrganizationV2Controller.cs b/Presentation.Web/Controllers/API/V2/External/Organizations/OrganizationV2Controller.cs index f8bb514e12..b112967f18 100644 --- a/Presentation.Web/Controllers/API/V2/External/Organizations/OrganizationV2Controller.cs +++ b/Presentation.Web/Controllers/API/V2/External/Organizations/OrganizationV2Controller.cs @@ -207,7 +207,7 @@ public IHttpActionResult GetOrganizationUnits( /// An organization unit [HttpGet] [Route("organizations/{organizationUuid}/organization-units/{organizationUnitId}")] - [SwaggerResponse(HttpStatusCode.OK, Type = typeof(OrganizationUserResponseDTO))] + [SwaggerResponse(HttpStatusCode.OK, Type = typeof(OrganizationUnitResponseDTO))] [SwaggerResponse(HttpStatusCode.BadRequest)] [SwaggerResponse(HttpStatusCode.NotFound)] [SwaggerResponse(HttpStatusCode.Forbidden)] @@ -251,11 +251,7 @@ private static OrganizationUnitResponseDTO ToOrganizationUnitResponseDto(Organiz Name = unit.Name, UnitId = unit.LocalId, Ean = unit.Ean, - ParentOrganizationUnit = unit.Parent?.Transform(parent => parent.MapIdentityNamePairDTO()), - Kle = unit - .TaskUsages - .Select(taskUsage => taskUsage.TaskRef.MapIdentityNamePairDTO()) - .ToList() + ParentOrganizationUnit = unit.Parent?.Transform(parent => parent.MapIdentityNamePairDTO()) }; } private OrganizationUserResponseDTO ToUserResponseDTO((Guid organizationUuid, User user) context) diff --git a/Presentation.Web/Models/API/V1/CreateTaskUsageDTO.cs b/Presentation.Web/Models/API/V1/CreateTaskUsageDTO.cs deleted file mode 100644 index b316b71858..0000000000 --- a/Presentation.Web/Models/API/V1/CreateTaskUsageDTO.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Presentation.Web.Models.API.V1 -{ - public class CreateTaskUsageDTO - { - public int TaskRefId { get; set; } - public int OrgUnitId { get; set; } - } -} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/NamedEntityWithUserFullNameDTO.cs b/Presentation.Web/Models/API/V1/NamedEntityWithUserFullNameDTO.cs new file mode 100644 index 0000000000..3590500e84 --- /dev/null +++ b/Presentation.Web/Models/API/V1/NamedEntityWithUserFullNameDTO.cs @@ -0,0 +1,8 @@ +namespace Presentation.Web.Models.API.V1 +{ + public class NamedEntityWithUserFullNameDTO : NamedEntityDTO + { + public string UserFullName { get; set; } + + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/OrgUnitDTO.cs b/Presentation.Web/Models/API/V1/OrgUnitDTO.cs index 799569093f..74ada06ac2 100644 --- a/Presentation.Web/Models/API/V1/OrgUnitDTO.cs +++ b/Presentation.Web/Models/API/V1/OrgUnitDTO.cs @@ -1,4 +1,5 @@ -using System; +using Core.DomainModel.Organization; +using System; using System.Collections.Generic; namespace Presentation.Web.Models.API.V1 @@ -17,14 +18,13 @@ public class OrgUnitDTO public string ObjectOwnerName { get; set; } public string ObjectOwnerLastName { get; set; } - public string ObjectOwnerFullName - { - get { return ObjectOwnerName + " " + ObjectOwnerLastName; } - } + public string ObjectOwnerFullName => $"{ObjectOwnerName} {ObjectOwnerLastName}"; public DateTime LastChanged { get; set; } public int LastChangedByUserId { get; set; } public Guid Uuid { get; set; } + public OrganizationUnitOrigin Origin { get; set; } + public Guid? ExternalOriginUuid { get; set; } } public class OrgUnitSimpleDTO @@ -34,10 +34,7 @@ public class OrgUnitSimpleDTO public int OrganizationId { get; set; } public string OrganizationName { get; set; } - public string QualifiedName - { - get { return Name + ", " + OrganizationName; } - } + public string QualifiedName => $"{Name}, {OrganizationName}"; } public class SimpleOrgUnitDTO diff --git a/Presentation.Web/Models/API/V1/Organizations/ChangeOrganizationUnitRegistrationRequestDTO.cs b/Presentation.Web/Models/API/V1/Organizations/ChangeOrganizationUnitRegistrationRequestDTO.cs new file mode 100644 index 0000000000..5abfd95a8a --- /dev/null +++ b/Presentation.Web/Models/API/V1/Organizations/ChangeOrganizationUnitRegistrationRequestDTO.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace Presentation.Web.Models.API.V1.Organizations +{ + public class ChangeOrganizationUnitRegistrationRequestDTO + { + public ChangeOrganizationUnitRegistrationRequestDTO() + { + OrganizationUnitRights = new List(); + ItContractRegistrations = new List(); + PaymentRegistrationDetails = new List(); + ResponsibleSystems = new List(); + RelevantSystems = new List(); + } + + public IEnumerable OrganizationUnitRights { get; set; } + public IEnumerable ItContractRegistrations { get; set; } + public IEnumerable PaymentRegistrationDetails { get; set; } + public IEnumerable ResponsibleSystems { get; set; } + public IEnumerable RelevantSystems { get; set; } + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/Organizations/ChangePaymentRegistrationRequestDTO.cs b/Presentation.Web/Models/API/V1/Organizations/ChangePaymentRegistrationRequestDTO.cs new file mode 100644 index 0000000000..d47000aae1 --- /dev/null +++ b/Presentation.Web/Models/API/V1/Organizations/ChangePaymentRegistrationRequestDTO.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace Presentation.Web.Models.API.V1.Organizations +{ + public class ChangePaymentRegistrationRequestDTO + { + public ChangePaymentRegistrationRequestDTO() + { + InternalPayments = new List(); + ExternalPayments = new List(); + } + + public int ItContractId { get; set; } + public IEnumerable InternalPayments { get; set; } + public IEnumerable ExternalPayments { get; set; } + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/Organizations/ConnectToStsOrganizationRequestDTO.cs b/Presentation.Web/Models/API/V1/Organizations/ConnectToStsOrganizationRequestDTO.cs new file mode 100644 index 0000000000..78dbd0979d --- /dev/null +++ b/Presentation.Web/Models/API/V1/Organizations/ConnectToStsOrganizationRequestDTO.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; + +namespace Presentation.Web.Models.API.V1.Organizations +{ + public class ConnectToStsOrganizationRequestDTO + { + [Range(1, int.MaxValue)] + public int? SynchronizationDepth { get; set; } + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/Organizations/ConnectionUpdateConsequencesResponseDTO.cs b/Presentation.Web/Models/API/V1/Organizations/ConnectionUpdateConsequencesResponseDTO.cs new file mode 100644 index 0000000000..c1c40f68e7 --- /dev/null +++ b/Presentation.Web/Models/API/V1/Organizations/ConnectionUpdateConsequencesResponseDTO.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Presentation.Web.Models.API.V1.Organizations +{ + public class ConnectionUpdateConsequencesResponseDTO + { + public IEnumerable Consequences { get; set; } + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/Organizations/ConnectionUpdateOrganizationUnitChangeCategory.cs b/Presentation.Web/Models/API/V1/Organizations/ConnectionUpdateOrganizationUnitChangeCategory.cs new file mode 100644 index 0000000000..5683bfac83 --- /dev/null +++ b/Presentation.Web/Models/API/V1/Organizations/ConnectionUpdateOrganizationUnitChangeCategory.cs @@ -0,0 +1,11 @@ +namespace Presentation.Web.Models.API.V1.Organizations +{ + public enum ConnectionUpdateOrganizationUnitChangeCategory + { + Added = 0, + Renamed = 1, + Moved = 2, + Deleted = 3, + Converted = 4 + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/Organizations/ConnectionUpdateOrganizationUnitConsequenceDTO.cs b/Presentation.Web/Models/API/V1/Organizations/ConnectionUpdateOrganizationUnitConsequenceDTO.cs new file mode 100644 index 0000000000..eb363aefc4 --- /dev/null +++ b/Presentation.Web/Models/API/V1/Organizations/ConnectionUpdateOrganizationUnitConsequenceDTO.cs @@ -0,0 +1,12 @@ +using System; + +namespace Presentation.Web.Models.API.V1.Organizations +{ + public class ConnectionUpdateOrganizationUnitConsequenceDTO + { + public Guid Uuid { get; set; } + public string Name { get; set; } + public ConnectionUpdateOrganizationUnitChangeCategory Category { get; set; } + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/Organizations/OrganizationRegistrationUnitDTO.cs b/Presentation.Web/Models/API/V1/Organizations/OrganizationRegistrationUnitDTO.cs new file mode 100644 index 0000000000..f8e219d6c8 --- /dev/null +++ b/Presentation.Web/Models/API/V1/Organizations/OrganizationRegistrationUnitDTO.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; + +namespace Presentation.Web.Models.API.V1.Organizations +{ + public class OrganizationRegistrationUnitDTO + { + public OrganizationRegistrationUnitDTO() + { + OrganizationUnitRights = new List(); + ItContractRegistrations = new List(); + Payments = new List(); + RelevantSystems = new List(); + ResponsibleSystems = new List(); + } + + public IEnumerable OrganizationUnitRights { get; set; } + public IEnumerable ItContractRegistrations { get; set; } + public IEnumerable Payments { get; set; } + public IEnumerable ResponsibleSystems { get; set; } + public IEnumerable RelevantSystems { get; set; } + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/Organizations/PaymentRegistrationDTO.cs b/Presentation.Web/Models/API/V1/Organizations/PaymentRegistrationDTO.cs new file mode 100644 index 0000000000..b7b10b8730 --- /dev/null +++ b/Presentation.Web/Models/API/V1/Organizations/PaymentRegistrationDTO.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace Presentation.Web.Models.API.V1.Organizations +{ + public class PaymentRegistrationDTO + { + public PaymentRegistrationDTO() + { + ItContract = new NamedEntityDTO(); + InternalPayments = new List(); + ExternalPayments = new List(); + } + public NamedEntityDTO ItContract { get; set; } + public IEnumerable InternalPayments { get; set; } + public IEnumerable ExternalPayments { get; set; } + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/Organizations/StsOrganizationAccessStatusResponseDTO.cs b/Presentation.Web/Models/API/V1/Organizations/StsOrganizationAccessStatusResponseDTO.cs new file mode 100644 index 0000000000..b127eb48ae --- /dev/null +++ b/Presentation.Web/Models/API/V1/Organizations/StsOrganizationAccessStatusResponseDTO.cs @@ -0,0 +1,16 @@ +using Core.DomainServices.Model.StsOrganization; + +namespace Presentation.Web.Models.API.V1.Organizations +{ + public class StsOrganizationAccessStatusResponseDTO + { + /// + /// Determines if KITOS has access to data from FK Organisation + /// + public bool AccessGranted { get; set; } + /// + /// If is false, this field contains the access error + /// + public CheckConnectionError? Error { get; set; } + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/Organizations/StsOrganizationOrgUnitDTO.cs b/Presentation.Web/Models/API/V1/Organizations/StsOrganizationOrgUnitDTO.cs index c83aec1807..4403eb177b 100644 --- a/Presentation.Web/Models/API/V1/Organizations/StsOrganizationOrgUnitDTO.cs +++ b/Presentation.Web/Models/API/V1/Organizations/StsOrganizationOrgUnitDTO.cs @@ -7,7 +7,6 @@ public class StsOrganizationOrgUnitDTO { public Guid Uuid { get; set; } public string Name { get; set; } - public string UserFacingKey { get; set; } public IEnumerable Children { get; set; } } } \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/Organizations/StsOrganizationSynchronizationDetailsResponseDTO.cs b/Presentation.Web/Models/API/V1/Organizations/StsOrganizationSynchronizationDetailsResponseDTO.cs new file mode 100644 index 0000000000..1968ba16e1 --- /dev/null +++ b/Presentation.Web/Models/API/V1/Organizations/StsOrganizationSynchronizationDetailsResponseDTO.cs @@ -0,0 +1,12 @@ +namespace Presentation.Web.Models.API.V1.Organizations +{ + public class StsOrganizationSynchronizationDetailsResponseDTO + { + public StsOrganizationAccessStatusResponseDTO AccessStatus { get; set; } + public bool Connected { get; set; } + public int? SynchronizationDepth { get; set; } + public bool CanCreateConnection { get; set; } + public bool CanUpdateConnection { get; set; } + public bool CanDeleteConnection { get; set; } + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/Organizations/TransferOrganizationUnitRegistrationRequestDTO.cs b/Presentation.Web/Models/API/V1/Organizations/TransferOrganizationUnitRegistrationRequestDTO.cs new file mode 100644 index 0000000000..d435dbd278 --- /dev/null +++ b/Presentation.Web/Models/API/V1/Organizations/TransferOrganizationUnitRegistrationRequestDTO.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Web; + +namespace Presentation.Web.Models.API.V1.Organizations +{ + public class TransferOrganizationUnitRegistrationRequestDTO : ChangeOrganizationUnitRegistrationRequestDTO + { + public Guid TargetUnitUuid { get; set; } + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/Organizations/UnitAccessRightsDTO.cs b/Presentation.Web/Models/API/V1/Organizations/UnitAccessRightsDTO.cs new file mode 100644 index 0000000000..8269291603 --- /dev/null +++ b/Presentation.Web/Models/API/V1/Organizations/UnitAccessRightsDTO.cs @@ -0,0 +1,30 @@ +namespace Presentation.Web.Models.API.V1.Organizations +{ + public class UnitAccessRightsDTO + { + public UnitAccessRightsDTO(bool canBeRead, bool canBeModified, bool canNameBeModified, bool canEanBeModified, bool canDeviceIdBeModified, bool canBeRearranged, bool canBeDeleted) + { + CanBeRead = canBeRead; + CanBeModified = canBeModified; + CanNameBeModified = canNameBeModified; + CanEanBeModified = canEanBeModified; + CanDeviceIdBeModified = canDeviceIdBeModified; + CanBeRearranged = canBeRearranged; + CanBeDeleted = canBeDeleted; + } + + public UnitAccessRightsDTO(UnitAccessRightsDTO other) + : this(other.CanBeRead, other.CanBeModified, other.CanNameBeModified, other.CanEanBeModified, other.CanDeviceIdBeModified, other.CanBeRearranged, other.CanBeDeleted) + { + + } + + public bool CanBeRead { get; } + public bool CanBeModified { get; } + public bool CanNameBeModified { get; } + public bool CanEanBeModified { get; } + public bool CanDeviceIdBeModified { get; } + public bool CanBeRearranged { get; } + public bool CanBeDeleted { get; } + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/Organizations/UnitAccessRightsWithUnitIdDTO.cs b/Presentation.Web/Models/API/V1/Organizations/UnitAccessRightsWithUnitIdDTO.cs new file mode 100644 index 0000000000..b2b74f660b --- /dev/null +++ b/Presentation.Web/Models/API/V1/Organizations/UnitAccessRightsWithUnitIdDTO.cs @@ -0,0 +1,13 @@ +namespace Presentation.Web.Models.API.V1.Organizations +{ + public class UnitAccessRightsWithUnitIdDTO : UnitAccessRightsDTO + { + public int UnitId { get; set; } + + public UnitAccessRightsWithUnitIdDTO(int unitId, UnitAccessRightsDTO rights) + : base(rights) + { + UnitId = unitId; + } + } +} \ No newline at end of file diff --git a/Presentation.Web/Models/API/V1/TaskRefUsageDTO.cs b/Presentation.Web/Models/API/V1/TaskRefUsageDTO.cs deleted file mode 100644 index 7d08870483..0000000000 --- a/Presentation.Web/Models/API/V1/TaskRefUsageDTO.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Presentation.Web.Models.API.V1 -{ - public class TaskRefUsageDTO - { - public TaskRefDTO TaskRef { get; set; } - public TaskUsageDTO Usage { get; set; } - } -} diff --git a/Presentation.Web/Models/API/V1/TaskUsageDTO.cs b/Presentation.Web/Models/API/V1/TaskUsageDTO.cs deleted file mode 100644 index 47ae9d2567..0000000000 --- a/Presentation.Web/Models/API/V1/TaskUsageDTO.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Presentation.Web.Models.API.V1 -{ - public class TaskUsageDTO - { - public int Id { get; set; } - public int TaskRefId { get; set; } - public int OrgUnitId { get; set; } - - public bool Starred { get; set; } - public int TechnologyStatus { get; set; } - public int UsageStatus { get; set; } - public string Comment { get; set; } - - public bool HasDelegations { get; set; } - } -} diff --git a/Presentation.Web/Models/API/V1/TaskUsageNestedDTO.cs b/Presentation.Web/Models/API/V1/TaskUsageNestedDTO.cs deleted file mode 100644 index 63242b0499..0000000000 --- a/Presentation.Web/Models/API/V1/TaskUsageNestedDTO.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Collections.Generic; - -namespace Presentation.Web.Models.API.V1 -{ - public class TaskUsageNestedDTO - { - public TaskUsageNestedDTO() - { - // initializing selfmade properites to avoid null exceptions - SystemUsages = new List(); - } - public int Id { get; set; } - - public int TaskRefId { get; set; } - public string TaskRefTaskKey { get; set; } - public string TaskRefDescription { get; set; } - - public int OrgUnitId { get; set; } - public string OrgUnitName { get; set; } - - public bool Starred { get; set; } - public int TechnologyStatus { get; set; } - public int UsageStatus { get; set; } - public string Comment { get; set; } - - public IEnumerable Children { get; set; } - public bool HasDelegations { get; set; } - - public IEnumerable SystemUsages { get; set; } - public bool HasWriteAccess { get; set; } - } -} diff --git a/Presentation.Web/Models/API/V2/Response/Organization/OrganizationUnitResponseDTO.cs b/Presentation.Web/Models/API/V2/Response/Organization/OrganizationUnitResponseDTO.cs index 64c2d65cb2..4316f3389c 100644 --- a/Presentation.Web/Models/API/V2/Response/Organization/OrganizationUnitResponseDTO.cs +++ b/Presentation.Web/Models/API/V2/Response/Organization/OrganizationUnitResponseDTO.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using Presentation.Web.Models.API.V2.Response.Generic.Identity; +using Presentation.Web.Models.API.V2.Response.Generic.Identity; namespace Presentation.Web.Models.API.V2.Response.Organization { @@ -10,10 +9,6 @@ public class OrganizationUnitResponseDTO : IdentityNamePairResponseDTO /// public IdentityNamePairResponseDTO ParentOrganizationUnit { get; set; } /// - /// Kle relevant for the organization unit - /// - public IEnumerable Kle { get; set; } - /// /// Optional EAN number for the organization unit. /// public long? Ean { get; set; } diff --git a/Presentation.Web/Models/Application/FeatureToggle/TemporaryFeature.cs b/Presentation.Web/Models/Application/FeatureToggle/TemporaryFeature.cs index 59869c1f8f..70a5b54a29 100644 --- a/Presentation.Web/Models/Application/FeatureToggle/TemporaryFeature.cs +++ b/Presentation.Web/Models/Application/FeatureToggle/TemporaryFeature.cs @@ -5,5 +5,6 @@ /// public enum TemporaryFeature { + FK_Organisation = 0 } } \ No newline at end of file diff --git a/Presentation.Web/Ninject/KernelBuilder.cs b/Presentation.Web/Ninject/KernelBuilder.cs index 94f233d631..0077d3bfc6 100644 --- a/Presentation.Web/Ninject/KernelBuilder.cs +++ b/Presentation.Web/Ninject/KernelBuilder.cs @@ -107,7 +107,6 @@ using Core.ApplicationServices.Organizations.Handlers; using Core.ApplicationServices.Tracking; using Core.ApplicationServices.UIConfiguration; -using Core.ApplicationServices.UIConfiguration.Handlers; using Core.BackgroundJobs.Model.Maintenance; using Core.DomainModel.ItContract.Read; using Core.DomainServices.Repositories.UICustomization; @@ -118,6 +117,8 @@ using Presentation.Web.Controllers.API.V2.External.ItSystems.Mapping; using Presentation.Web.Controllers.API.V2.External.ItInterfaces.Mapping; using System.Linq; +using Core.ApplicationServices.Users.Handlers; +using Core.DomainModel.Commands; using Infrastructure.Services.Types; namespace Presentation.Web.Ninject @@ -186,6 +187,7 @@ public StandardKernel Build() public void RegisterServices(IKernel kernel) { RegisterDomainEventsEngine(kernel); + RegisterDomainCommandsEngine(kernel); RegisterDataAccess(kernel); kernel.Bind().To().InSingletonScope(); kernel.Bind().ToMethod(_ => new KitosUrl(new Uri(Settings.Default.BaseUrl))).InSingletonScope(); @@ -250,6 +252,7 @@ public void RegisterServices(IKernel kernel) kernel.Bind().To().InCommandScope(Mode); kernel.Bind().To().InCommandScope(Mode); kernel.Bind().To().InCommandScope(Mode); + kernel.Bind().To().InCommandScope(Mode); //Role assignment services RegisterRoleAssignmentService(kernel); @@ -323,8 +326,8 @@ private void RegisterSSO(IKernel kernel) private void RegisterDomainEventsEngine(IKernel kernel) { - kernel.Bind().To().InCommandScope(Mode); - + kernel.Bind().To().InCommandScope(Mode); + //Auth cache RegisterDomainEvents(kernel); @@ -366,7 +369,6 @@ private void RegisterDomainEventsEngine(IKernel kernel) //Organization RegisterDomainEvents(kernel); - RegisterDomainEvents(kernel); } private void RegisterDomainEvents(IKernel kernel) @@ -379,6 +381,25 @@ private void RegisterDomainEvents(IKernel kernel) .ForEach(tHandlerInterface => kernel.Bind(tHandlerInterface).To().InCommandScope(Mode)); } + private void RegisterDomainCommandsEngine(IKernel kernel) + { + kernel.Bind().To().InCommandScope(Mode); + + RegisterCommands(kernel); + RegisterCommands(kernel); + RegisterCommands(kernel); + } + + private void RegisterCommands(IKernel kernel) + { + //Register all exposed handlers + typeof(THandler) + .GetInterfaces() + .Where(tType => tType.IsImplementationOfGenericType(typeof(ICommandHandler<,>))) + .ToList() + .ForEach(tHandlerInterface => kernel.Bind(tHandlerInterface).To().InCommandScope(Mode)); + } + private void RegisterOptions(IKernel kernel) { //Data processing registrations diff --git a/Presentation.Web/Presentation.Web.csproj b/Presentation.Web/Presentation.Web.csproj index 2e0cbdb8a2..34abfaf910 100644 --- a/Presentation.Web/Presentation.Web.csproj +++ b/Presentation.Web/Presentation.Web.csproj @@ -356,16 +356,32 @@ + + + + + + + + + + + + + + + + @@ -375,6 +391,9 @@ + + + @@ -390,14 +409,32 @@ + + + + + + + + + + + + + + + + + + @@ -635,15 +672,23 @@ + + + + + + + + @@ -652,6 +697,7 @@ + @@ -683,7 +729,6 @@ - @@ -832,7 +877,9 @@ + + @@ -863,11 +910,15 @@ + + + + @@ -877,7 +928,7 @@ - + @@ -892,6 +943,8 @@ + + @@ -1040,7 +1093,6 @@ - @@ -1077,10 +1129,7 @@ - - - @@ -1410,13 +1459,7 @@ - - - - - - @@ -1461,7 +1504,6 @@ - @@ -1508,7 +1550,6 @@ - @@ -1609,7 +1650,7 @@ Core.BackgroundJobs - {a76a8e41-74f7-4443-a5f3-059b5414d83b} + {A76A8E41-74F7-4443-A5F3-059B5414D83B} Core.DomainModel diff --git a/Presentation.Web/Tests/PageObjects/Organization/UsersPage.po.ts b/Presentation.Web/Tests/PageObjects/Organization/UsersPage.po.ts index 3778355460..470f169300 100644 --- a/Presentation.Web/Tests/PageObjects/Organization/UsersPage.po.ts +++ b/Presentation.Web/Tests/PageObjects/Organization/UsersPage.po.ts @@ -29,7 +29,7 @@ class UsersPage implements IPageObject { "it-system.catalog", "it-contract.overview", "data-processing.overview", - "organization.overview" + "organization.structure" ].map(x => x.replace(".", "_")); } } diff --git a/Presentation.Web/app/Constants/Constants.ts b/Presentation.Web/app/Constants/Constants.ts index 87c9e26dcd..70eca95185 100644 --- a/Presentation.Web/app/Constants/Constants.ts +++ b/Presentation.Web/app/Constants/Constants.ts @@ -6,7 +6,7 @@ static readonly SystemCatalog = "it-system.catalog"; static readonly ContractOverview = "it-contract.overview"; static readonly DataProcessingRegistrationOverview = "data-processing.overview"; - static readonly OrganizationOverview = "organization.overview"; + static readonly OrganizationOverview = "organization.structure"; static readonly InterfaceCatalog = "it-system.interfaceCatalog"; } diff --git a/Presentation.Web/app/components/global-admin/global-admin-contract.view.html b/Presentation.Web/app/components/global-admin/global-admin-contract.view.html index adc958e4ef..daeff3694c 100644 --- a/Presentation.Web/app/components/global-admin/global-admin-contract.view.html +++ b/Presentation.Web/app/components/global-admin/global-admin-contract.view.html @@ -3,7 +3,7 @@
-
+
diff --git a/Presentation.Web/app/components/global-admin/global-admin-data-processing.view.html b/Presentation.Web/app/components/global-admin/global-admin-data-processing.view.html index 8cc9f6876c..a62894d505 100644 --- a/Presentation.Web/app/components/global-admin/global-admin-data-processing.view.html +++ b/Presentation.Web/app/components/global-admin/global-admin-data-processing.view.html @@ -1,5 +1,5 @@ 
-
-
+
+
-
\ No newline at end of file +
\ No newline at end of file diff --git a/Presentation.Web/app/components/global-admin/global-admin-edit-options.controller.ts b/Presentation.Web/app/components/global-admin/global-admin-edit-options.controller.ts index 36ba6621e0..bb134cb18d 100644 --- a/Presentation.Web/app/components/global-admin/global-admin-edit-options.controller.ts +++ b/Presentation.Web/app/components/global-admin/global-admin-edit-options.controller.ts @@ -8,6 +8,7 @@ hasWriteAccess: boolean; description: string; buttonDisabled: boolean; + disableDescription: boolean; static $inject: string[] = ["$uibModalInstance", "$stateParams", "$http", "notify", "user","inMemoryCacheService"]; @@ -25,6 +26,7 @@ this.optionId = this.$stateParams["id"]; this.optionType = this.$stateParams["optionType"]; this.initModal(this.optionId, this.optionsUrl); + this.disableDescription = (this.$stateParams["disableDescription"] === "true"); this.buttonDisabled = false; } @@ -140,7 +142,7 @@ states.forEach(currentStateConfig => $stateProvider.state(currentStateConfig.id, { - url: `/{:optionsUrl}/{id:int}/{:optionType}/${currentStateConfig.urlSuffix}`, + url: `/{:optionsUrl}/{id:int}/{:optionType}/{:disableDescription}/${currentStateConfig.urlSuffix}`, onEnter: [ "$state", "$stateParams", "$uibModal", ($state: ng.ui.IStateService, diff --git a/Presentation.Web/app/components/global-admin/global-admin-misc.view.html b/Presentation.Web/app/components/global-admin/global-admin-misc.view.html index 9b2e392263..aa9e742116 100644 --- a/Presentation.Web/app/components/global-admin/global-admin-misc.view.html +++ b/Presentation.Web/app/components/global-admin/global-admin-misc.view.html @@ -66,7 +66,7 @@

Oversigt over brugere med API relaterede rettigheder

Organisation Navn Email - API adgang + API bruger @@ -92,7 +92,7 @@

Oversigt over brugere med API relaterede rettigheder

Navn Email - API adgang + API bruger Interessentadgang diff --git a/Presentation.Web/app/components/global-admin/global-admin-option-edit-types.modal.view.html b/Presentation.Web/app/components/global-admin/global-admin-option-edit-types.modal.view.html index 24955b6788..d45b385adb 100644 --- a/Presentation.Web/app/components/global-admin/global-admin-option-edit-types.modal.view.html +++ b/Presentation.Web/app/components/global-admin/global-admin-option-edit-types.modal.view.html @@ -24,7 +24,7 @@

{{vm.pageTitle}}

-
+
diff --git a/Presentation.Web/app/components/global-admin/global-admin-organization-modal.view.html b/Presentation.Web/app/components/global-admin/global-admin-organization-modal.view.html index 2338462d46..7b43a3aafe 100644 --- a/Presentation.Web/app/components/global-admin/global-admin-organization-modal.view.html +++ b/Presentation.Web/app/components/global-admin/global-admin-organization-modal.view.html @@ -11,7 +11,7 @@
-
+ -
+
- + +
-
+
- + +
@@ -37,11 +43,15 @@

Profilindstillinger

-
+
- + +
diff --git a/Presentation.Web/app/components/home/home.controller.ts b/Presentation.Web/app/components/home/home.controller.ts index ce69ff0041..baed7753f1 100644 --- a/Presentation.Web/app/components/home/home.controller.ts +++ b/Presentation.Web/app/components/home/home.controller.ts @@ -16,8 +16,8 @@ } ]); - app.controller("home.IndexCtrl", ["$rootScope", "$scope", "$http", "$state", "$stateParams", "notify", "userService", "texts", "navigationService", "$sce", "$location", "$", - ($rootScope, $scope, $http, $state, $stateParams, notify, userService, texts, navigationService, $sce, $location, $) => { + app.controller("home.IndexCtrl", ["$rootScope", "$scope", "$http", "$state", "notify", "userService", "texts", "navigationService", "$sce", "$location", "$", "featureToggleService", + ($rootScope, $scope, $http, $state, notify, userService, texts, navigationService, $sce, $location, $, featureToggleService: Kitos.Services.FeatureToggle.IFeatureToggleService) => { const factory = new Kitos.Models.ViewModel.Sso.SsoStateViewModelFactory($); let ssoStateViewModel = factory.createFromViewState(); @@ -30,6 +30,12 @@ } } + const ftFactory = new Kitos.Models.ViewModel.FeatureToggle.FeatureToggleViewModelFactory($); + const ftViewModel = ftFactory.createFromViewState(); + if (ftViewModel.featureToggle !== null) { + featureToggleService.addFeature(ftViewModel.featureToggle); + } + $rootScope.page.title = "Index"; $rootScope.page.subnav = []; $scope.texts = []; diff --git a/Presentation.Web/app/components/it-contract/tabs/it-contract-tab-main.controller.ts b/Presentation.Web/app/components/it-contract/tabs/it-contract-tab-main.controller.ts index 0d6490ee02..cb587def91 100644 --- a/Presentation.Web/app/components/it-contract/tabs/it-contract-tab-main.controller.ts +++ b/Presentation.Web/app/components/it-contract/tabs/it-contract-tab-main.controller.ts @@ -31,28 +31,9 @@ .create(Kitos.Services.LocalOptions.LocalOptionType.ProcurementStrategyTypes).getAll() ], orgUnits: [ - '$http', 'contract', function ($http, contract) { - return $http.get('api/organizationUnit?organization=' + contract.organizationId).then(function (result) { - var options: Kitos.Models.ViewModel.Generic.Select2OptionViewModelWithIndentation[] = []; - - function visit(orgUnit: Kitos.Models.Api.Organization.OrganizationUnit, indentationLevel: number) { - var option = { - id: String(orgUnit.id), - text: orgUnit.name, - indentationLevel: indentationLevel - }; - - options.push(option); - - _.each(orgUnit.children, function (child) { - return visit(child, indentationLevel + 1); - }); - - } - visit(result.data.response, 0); - return options; - }); - } + "organizationApiService", "contract", (organizationApiService: Kitos.Services.IOrganizationApiService, contract) => + organizationApiService.getOrganizationUnit(contract.organizationId).then(result => + Kitos.Helpers.Select2OptionsFormatHelper.addIndentationToUnitChildren(result, 0)) ], kitosUsers: [ '$http', 'user', '_', function ($http, user, _) { diff --git a/Presentation.Web/app/components/it-contract/tabs/it-contract-tab-main.view.html b/Presentation.Web/app/components/it-contract/tabs/it-contract-tab-main.view.html index 92b11f1ae1..467143f86a 100644 --- a/Presentation.Web/app/components/it-contract/tabs/it-contract-tab-main.view.html +++ b/Presentation.Web/app/components/it-contract/tabs/it-contract-tab-main.view.html @@ -62,7 +62,7 @@

{{contract.name}}

+ ng-disabled="!hasWriteAccess"/>
diff --git a/Presentation.Web/app/components/it-system/edit/tabs/it-system-edit-tab-main.controller.ts b/Presentation.Web/app/components/it-system/edit/tabs/it-system-edit-tab-main.controller.ts index 784a881902..2ecc1470e1 100644 --- a/Presentation.Web/app/components/it-system/edit/tabs/it-system-edit-tab-main.controller.ts +++ b/Presentation.Web/app/components/it-system/edit/tabs/it-system-edit-tab-main.controller.ts @@ -39,12 +39,12 @@ $scope.itSystemsSelectOptions = select2LoadingService.loadSelect2( "api/itsystem", true, - [`excludeId=${itSystem.id}`, `orgId=${user.currentOrganizationId}`, `take=25`], + [`excludeId=${itSystem.id}`, `orgId=${user.currentOrganizationId}`, `take=100`], false); $scope.organizationSelectOptions = select2LoadingService.loadSelect2( "api/organization", true, - [`orgId=${user.currentOrganizationId}`, 'take=25'], + [`orgId=${user.currentOrganizationId}`, 'take=100'], false); $scope.hasWriteAccess = hasWriteAccess; diff --git a/Presentation.Web/app/components/it-system/it-interface/it-interface-catalog.controller.ts b/Presentation.Web/app/components/it-system/it-interface/it-interface-catalog.controller.ts index 7534c6976c..9e9e639d16 100644 --- a/Presentation.Web/app/components/it-system/it-interface/it-interface-catalog.controller.ts +++ b/Presentation.Web/app/components/it-system/it-interface/it-interface-catalog.controller.ts @@ -221,7 +221,7 @@ }, groupable: false, columnMenu: true, - height: window.innerHeight - 200, + height: window.innerHeight - 150, dataBound: this.saveGridOptions, columnResize: this.saveGridOptions, columnHide: this.saveGridOptions, diff --git a/Presentation.Web/app/components/it-system/it-system-catalog.controller.ts b/Presentation.Web/app/components/it-system/it-system-catalog.controller.ts index b0fa71ae3c..ee3c312070 100644 --- a/Presentation.Web/app/components/it-system/it-system-catalog.controller.ts +++ b/Presentation.Web/app/components/it-system/it-system-catalog.controller.ts @@ -349,7 +349,7 @@ }, groupable: false, columnMenu: true, - height: window.innerHeight - 200, + height: window.innerHeight - 150, dataBound: this.saveGridOptions, columnResize: this.saveGridOptions, columnHide: this.saveGridOptions, diff --git a/Presentation.Web/app/components/it-system/usage/tabs/it-system-usage-tab-contracts.controller.ts b/Presentation.Web/app/components/it-system/usage/tabs/it-system-usage-tab-contracts.controller.ts index 4581e69e16..46ff4c4f21 100644 --- a/Presentation.Web/app/components/it-system/usage/tabs/it-system-usage-tab-contracts.controller.ts +++ b/Presentation.Web/app/components/it-system/usage/tabs/it-system-usage-tab-contracts.controller.ts @@ -16,14 +16,14 @@ ($scope, $http, itSystemUsage, entityMapper, uiState: Kitos.Models.UICustomization.ICustomizedModuleUI, apiUseCaseFactory: Kitos.Services.Generic.IApiUseCaseFactory, contractUiState: Kitos.Models.UICustomization.ICustomizedModuleUI, itSystemUsageService: Kitos.Services.ItSystemUsage.IItSystemUsageService) => { var usageId = itSystemUsage.id; bindContracts(itSystemUsage); - var currentMainContract = null; + var currentMainContract: number; const reloadContractState = () => { return itSystemUsageService.getItSystemUsage(usageId) .then((usage) => bindContracts(usage)); } - $scope.saveMainContract = id => { + $scope.saveMainContract = (id: any) => { if (currentMainContract === id || _.isUndefined(id)) { return; } @@ -38,17 +38,29 @@ } }; - function bindContracts(usage) { - $scope.usage = usage; - $scope.contracts = entityMapper.mapApiResponseToSelect2ViewModel(usage.contracts); + function bindContracts(usage: any) { + $scope.contracts = usage.contracts.map(contract => { + return { + id: contract.id, + name: contract.name, + contractTypeName: contract.contractTypeName, + supplierName: contract.supplierName, + hasOperationElement: contract.hasOperationElement, + concluded: Kitos.Helpers.RenderFieldsHelper.renderDate(contract.concluded), + expirationDate: Kitos.Helpers.RenderFieldsHelper.renderDate(contract.expirationDate), + terminated: Kitos.Helpers.RenderFieldsHelper.renderDate(contract.terminated) + } + }); + $scope.contractsToSelect = entityMapper.mapApiResponseToSelect2ViewModel(usage.contracts); + $scope.mainContractId = usage.mainContractId; currentMainContract = usage.mainContractId; - let match + let match; if (usage.mainContractId !== null) { match = usage.contracts && usage.contracts.find(x => { return x.id === usage.mainContractId }); } itSystemUsage.mainContractIsActive = match?.isActive; - + $scope.mainContractIsActive = match?.isActive; } //UI Customization diff --git a/Presentation.Web/app/components/it-system/usage/tabs/it-system-usage-tab-contracts.view.html b/Presentation.Web/app/components/it-system/usage/tabs/it-system-usage-tab-contracts.view.html index 07c0fefa13..922b26a1f4 100644 --- a/Presentation.Web/app/components/it-system/usage/tabs/it-system-usage-tab-contracts.view.html +++ b/Presentation.Web/app/components/it-system/usage/tabs/it-system-usage-tab-contracts.view.html @@ -29,42 +29,42 @@

{{systemUsageName}}

- + - {{ contract.name ? contract.name : 'Unavngiven' }} + {{:: contract.name ? contract.name : 'Unavngiven' }} - {{ contract.contractTypeName }} + {{::contract.contractTypeName }} - {{ contract.supplierName }} + {{::contract.supplierName }} - + - + {{::contract.concluded}} - + {{::contract.expirationDate}} - + {{::contract.terminated}} @@ -81,7 +81,7 @@

{{systemUsageName}}

@@ -89,10 +89,10 @@

{{systemUsageName}}

IT systemet har nu status som: - + Aktivt - + Inaktivt
diff --git a/Presentation.Web/app/components/local-config/import/fk-organization-import-config-import-modal.dialog.ts b/Presentation.Web/app/components/local-config/import/fk-organization-import-config-import-modal.dialog.ts new file mode 100644 index 0000000000..1a8c7fc373 --- /dev/null +++ b/Presentation.Web/app/components/local-config/import/fk-organization-import-config-import-modal.dialog.ts @@ -0,0 +1,157 @@ +module Kitos.LocalAdmin.FkOrganisation.Modals { + export enum FKOrganisationImportFlow { + Create = "create", + Update = "update" + } + + export interface IFKOrganisationImportDialogFactory { + open(flow: FKOrganisationImportFlow, organizationUuid: string, synchronizationDepth: number | null): ng.ui.bootstrap.IModalInstanceService + } + + export class FKOrganisationImportDialogFactory implements IFKOrganisationImportDialogFactory { + static $inject = ["$uibModal"]; + constructor(private readonly $uibModal: ng.ui.bootstrap.IModalService) { } + + open(flow: FKOrganisationImportFlow, organizationUuid: string, synchronizationDepth: number | null): ng.ui.bootstrap.IModalInstanceService { + return this.$uibModal.open({ + windowClass: "modal fade in wide-modal", + templateUrl: "app/components/local-config/import/fk-organization-import-config-import-modal.view.html", + controller: FKOrganisationImportController, + controllerAs: "vm", + resolve: { + "flow": [() => flow], + "orgUuid": [() => organizationUuid], + "synchronizationDepth": [() => synchronizationDepth] + }, + backdrop: "static", //Make sure accidental click outside the modal does not close it during the import process + }); + } + } + + class FKOrganisationImportController { + static $inject = ["flow", "orgUuid", "synchronizationDepth", "stsOrganizationSyncService", "$uibModalInstance", "notify"]; + isConsequencesCollapsed: boolean = false; + isHierarchyCollapsed: boolean = false; + busy: boolean = false; + updating: boolean = false; + loadingHierarchy: boolean | null; + consequencesAwaitingApproval: Array | null = null; + fkOrgHierarchy: Kitos.Shared.Components.Organization.IOrganizationTreeComponentOptions | null = null; + constructor( + readonly flow: FKOrganisationImportFlow, + private readonly organizationUuid: string, + initialImportDepth: number | null, + private readonly stsOrganizationSyncService: Services.Organization.IStsOrganizationSyncService, + private readonly $uibModalInstance: ng.ui.bootstrap.IModalServiceInstance, + private readonly notify) { + this.fkOrgHierarchy = { + availableLevels: initialImportDepth, + root: null + } + } + + $onInit() { + this.loadingHierarchy = true; + this.isConsequencesCollapsed = this.isHierarchyCollapsed = false; + this.consequencesAwaitingApproval = null; + this.stsOrganizationSyncService + .getSnapshot(this.organizationUuid) + .then(root => { + this.fkOrgHierarchy.root = this.createNodeVm(root); + this.loadingHierarchy = false; + }, error => { + console.error(error); + this.notify.addErrorMessage("Fejl i indlæsning af hierarkiet fra FK Organisation. Genindlæs siden og prøv igen."); + }); + } + + private createNodeVm(stsNode: Kitos.Models.Api.Organization.StsOrganizationOrgUnitDTO): Kitos.Shared.Components.Organization.IOrganizationTreeNode { + return { + id: stsNode.uuid, + name: stsNode.name, + origin: Kitos.Models.Api.Organization.OrganizationUnitOrigin.STS_Organisation, + nodes: stsNode.children.map(child => this.createNodeVm(child)) + }; + } + + cancel() { + if (!this.busy) { + this.$uibModalInstance.dismiss(); + } + } + + performImport() { + if (!this.busy) { + this.busy = true; + if (this.flow === FKOrganisationImportFlow.Create) { + this.createConnection(); + } else if (this.flow === FKOrganisationImportFlow.Update) { + this.updateConnection(); + } + } + } + + acceptConsequences() { + this.performUpdate(); + } + + rejectConsequences() { + this.updating = false; + this.consequencesAwaitingApproval = null; + this.isHierarchyCollapsed = false; + } + + private performUpdate() { + + this.updating = true; + this.busy = true; + + return this.stsOrganizationSyncService.updateConnection(this.organizationUuid, this.fkOrgHierarchy.availableLevels) + .then(() => { + this.closeDialog(); + }, error => { + console.error("Error: ", error); + this.updating = false; + this.busy = false; + this.notify.addErrorMessage("Fejl ifm. oprettelse af opdateringen. Prøv igen."); + }); + } + + private createConnection() { + this.stsOrganizationSyncService + .createConnection(this.organizationUuid, this.fkOrgHierarchy.availableLevels) + .then(() => { + this.closeDialog(); + }, error => { + console.error("Error:", error); + this.busy = false; + this.notify.addErrorMessage("Fejl ifm. oprettelse af forbindelsen. Prøv igen."); + }); + } + + private closeDialog() { + this.busy = false; + this.$uibModalInstance.close(); + } + + private updateConnection() { + this.isConsequencesCollapsed = false; + this.stsOrganizationSyncService + .getConnectionUpdateConsequences(this.organizationUuid, this.fkOrgHierarchy.availableLevels) + .then(consequences => { + if (consequences.consequences.length > 0) { + this.consequencesAwaitingApproval = consequences.consequences; + this.busy = false; + } else { + return this.performUpdate(); + } + }, error => { + console.error(error); + this.busy = false; + this.notify.addErrorMessage("Fejl ifm. oprettelse af opdateringen. Prøv igen."); + }); + } + } + + app.service("fkOrganisationImportDialogFactory", FKOrganisationImportDialogFactory) +} \ No newline at end of file diff --git a/Presentation.Web/app/components/local-config/import/fk-organization-import-config-import-modal.view.html b/Presentation.Web/app/components/local-config/import/fk-organization-import-config-import-modal.view.html new file mode 100644 index 0000000000..0ed0df7ddf --- /dev/null +++ b/Presentation.Web/app/components/local-config/import/fk-organization-import-config-import-modal.view.html @@ -0,0 +1,87 @@ + + + + + \ No newline at end of file diff --git a/Presentation.Web/app/components/local-config/import/fk-organization-import-config.component.ts b/Presentation.Web/app/components/local-config/import/fk-organization-import-config.component.ts new file mode 100644 index 0000000000..c9322fa976 --- /dev/null +++ b/Presentation.Web/app/components/local-config/import/fk-organization-import-config.component.ts @@ -0,0 +1,179 @@ +module Kitos.LocalAdmin.Components { + "use strict"; + + function setupComponent(): ng.IComponentOptions { + return { + bindings: { + currentOrganizationUuid: "<" + }, + controller: FkOrganizationImportController, + controllerAs: "ctrl", + templateUrl: `app/components/local-config/import/fk-organization-import-config.view.html` + }; + } + + enum CommandCategory { + Create = "create", + Update = "update", + Delete = "delete" + } + + interface IFkOrganizationCommand { + id: string + text: string + onClick: () => void + enabled: boolean + category: CommandCategory + } + + interface IFkOrganizationSynchronizationStatus { + connected: boolean + synchronizationDepth: number | null + } + + interface IFkOrganizationImportController extends ng.IComponentController { + currentOrganizationUuid: string + accessGranted: boolean | null + accessError: string | null + synchronizationStatus: IFkOrganizationSynchronizationStatus | null + commands: Array | null + busy: boolean + } + + class FkOrganizationImportController implements IFkOrganizationImportController { + currentOrganizationUuid: string | null = null; //note set by bindings + accessGranted: boolean | null = null; + accessError: string | null = null; + synchronizationStatus: IFkOrganizationSynchronizationStatus | null = null; + commands: Array | null = null; + busy: boolean = false; + + static $inject: string[] = ["stsOrganizationSyncService", "fkOrganisationImportDialogFactory"]; + constructor( + private readonly stsOrganizationSyncService: Kitos.Services.Organization.IStsOrganizationSyncService, + private readonly fkOrganisationImportDialogFactory: Kitos.LocalAdmin.FkOrganisation.Modals.IFKOrganisationImportDialogFactory) { + } + + $onInit() { + if (this.currentOrganizationUuid === null) { + console.error("missing attribute: 'currentOrganizationUuid'"); + } else { + this.loadState(); + } + } + + private resetState() { + this.accessGranted = null; + this.accessError = null; + this.synchronizationStatus = null; + this.commands = null; + this.busy = false; + } + + private loadState() { + this.resetState(); + this.stsOrganizationSyncService + .getConnectionStatus(this.currentOrganizationUuid) + .then(result => { + this.bindAccessProperties(result); + this.bindSynchronizationStatus(result); + this.bindCommands(result); + }, error => { + console.error(error); + this.accessGranted = false; + this.accessError = "Der skete en fejl ifm. tjek for forbindelsen til FK Organisation. Genindlæs venligst siden for at prøve igen."; + }); + } + + private bindCommands(result: Models.Api.Organization.StsOrganizationSynchronizationStatusResponseDTO) { + const newCommands: Array = []; + if (result.connected) { + newCommands.push({ + id: "updateSync", + text: "Rediger", + category: CommandCategory.Update, + enabled: result.canUpdateConnection, + onClick: () => { + this.fkOrganisationImportDialogFactory + .open(Kitos.LocalAdmin.FkOrganisation.Modals.FKOrganisationImportFlow.Update, this.currentOrganizationUuid, this.synchronizationStatus.synchronizationDepth) + .closed.then(() => { + //Reload state from backend if the dialog was closed + this.loadState(); + }); + } + }); + newCommands.push({ + id: "breakSync", + text: "Afbryd", + category: CommandCategory.Delete, + enabled: result.canDeleteConnection, + onClick: () => { + if (confirm("Afbryd forbindelsen til FK Organisation? Ved afbrydelse af forbindelsen, konverteres alle organisationsenheder til KITOS enheder, hvorefter de frit kan redigeres.")) { + this.busy = true; + this.stsOrganizationSyncService + .disconnect(this.currentOrganizationUuid) + .then(success => { + if (success) { + this.loadState(); + } else { + this.busy = false; + } + }, _ => { + this.busy = false; + }); + } + } + }); + } else { + newCommands.push({ + id: "createSync", + text: "Forbind", + category: CommandCategory.Create, + enabled: result.canCreateConnection, + onClick: () => { + this.fkOrganisationImportDialogFactory + .open(Kitos.LocalAdmin.FkOrganisation.Modals.FKOrganisationImportFlow.Create, this.currentOrganizationUuid, null) + .closed.then(() => { + //Reload state from backend if the dialog was closed + this.loadState(); + }); + } + }); + } + + this.commands = newCommands; + } + + private bindSynchronizationStatus(result: Models.Api.Organization.StsOrganizationSynchronizationStatusResponseDTO) { + this.synchronizationStatus = { + connected: result.connected, + synchronizationDepth: result.synchronizationDepth + }; + } + + private bindAccessProperties(result: Models.Api.Organization.StsOrganizationSynchronizationStatusResponseDTO) { + if (result.accessStatus.accessGranted) { + this.accessGranted = true; + } else { + this.accessGranted = false; + switch (result.accessStatus.error) { + case Models.Api.Organization.CheckConnectionError.ExistingServiceAgreementIssue: + this.accessError = "Der er problemer med den eksisterende serviceaftale, der giver KITOS adgang til data fra din kommune i FK Organisatoin. Kontakt venligst den KITOS ansvarlige i din kommune for hjælp."; + break; + case Models.Api.Organization.CheckConnectionError.InvalidCvrOnOrganization: + this.accessError = "Der enten mangler eller er registreret et ugyldigt CVR nummer på din kommune i KITOS."; + break; + case Models.Api.Organization.CheckConnectionError.MissingServiceAgreement: + this.accessError = "Din organisation mangler en gyldig serviceaftale der giver KITOS adgang til data fra din kommune i FK Organisation. Kontakt venligst den KITOS ansvarlige i din kommune for hjælp."; + break; + case Models.Api.Organization.CheckConnectionError.Unknown: //intended fallthrough + default: + this.accessError = "Der skete en ukendt fejl ifm. tjek for forbindelsen til FK Organisation. Genindlæs venligst siden for at prøve igen."; + break; + } + } + } + } + angular.module("app") + .component("fkOrgnizationImportConfig", setupComponent()); +} \ No newline at end of file diff --git a/Presentation.Web/app/components/local-config/import/fk-organization-import-config.view.html b/Presentation.Web/app/components/local-config/import/fk-organization-import-config.view.html new file mode 100644 index 0000000000..d3e3bcee81 --- /dev/null +++ b/Presentation.Web/app/components/local-config/import/fk-organization-import-config.view.html @@ -0,0 +1,38 @@ +
+ +
+
+ +
+ KITOS har adgang til organisationens data via FK Organisation + KITOS har ikke adgang til organisationens data via FK Organisation +
+
+ + {{::ctrl.accessError}} +
+
+
+ +
+ + Organisationen er forbundet til FK Organisation + + + + KITOS er forbundet i "{{::ctrl.synchronizationStatus.synchronizationDepth}}" niveauer fra FK Organisation. + + Organisationen er ikke forbundet til FK Organisation +
+ +
+
+ + +
\ No newline at end of file diff --git a/Presentation.Web/app/components/local-config/import/fk-organization-import-consequences-log.component.ts b/Presentation.Web/app/components/local-config/import/fk-organization-import-consequences-log.component.ts new file mode 100644 index 0000000000..dd7b5c1b99 --- /dev/null +++ b/Presentation.Web/app/components/local-config/import/fk-organization-import-consequences-log.component.ts @@ -0,0 +1,106 @@ +module Kitos.LocalAdmin.Components { + "use strict"; + + function setupComponent(): ng.IComponentOptions { + return { + bindings: { + consequences: "<" + }, + controller: FkOrgnizationImportConsequencesLogController, + controllerAs: "ctrl", + templateUrl: `app/components/local-config/import/fk-organization-import-consequences-log.view.html` + }; + } + + export interface IConsequenceRow { + name: string + category: string + description: string + } + + interface IFkOrgnizationImportConsequencesLogController extends ng.IComponentController, Utility.KendoGrid.IGridViewAccess { + consequences: Array + } + + class FkOrgnizationImportConsequencesLogController implements IFkOrgnizationImportConsequencesLogController { + consequences: Array | null = null; + mainGrid: IKendoGrid; + mainGridOptions: IKendoGridOptions; + + static $inject: string[] = ["kendoGridLauncherFactory", "$scope", "userService"]; + constructor( + private readonly kendoGridLauncherFactory: Utility.KendoGrid.IKendoGridLauncherFactory, + private readonly $scope: ng.IScope, + private readonly userService: Kitos.Services.IUserService) { + } + + $onInit() { + if (this.consequences) { + this.loadGrid(); + } else { + console.error("Missing parameter 'consequences'"); + } + } + + private loadGrid() { + const kendoOptions = [ + Models.Api.Organization.ConnectionUpdateOrganizationUnitChangeCategory.Added, + Models.Api.Organization.ConnectionUpdateOrganizationUnitChangeCategory.Renamed, + Models.Api.Organization.ConnectionUpdateOrganizationUnitChangeCategory.Moved, + Models.Api.Organization.ConnectionUpdateOrganizationUnitChangeCategory.Converted, + Models.Api.Organization.ConnectionUpdateOrganizationUnitChangeCategory.Deleted + ].map(optionType => { + return { + textValue: Kitos.Models.ViewModel.Organization.ConnectionUpdateOrganizationUnitChangeCategoryOptions.getText(optionType) + }; + }); + + this.userService.getUser().then(user => { + this.kendoGridLauncherFactory + .create() + .withUser(user) + .withGridBinding(this) + .withFlexibleWidth() + .withArrayDataSource(this.consequences.map(row => { + return { + category: Kitos.Models.ViewModel.Organization.ConnectionUpdateOrganizationUnitChangeCategoryOptions.getText(row.category), + description: row.description, + name: row.name + }; + })) + .withEntityTypeName("FK Organisation - Konsekvenser ved opdatering") + .withStorageKey("fkOrgConsequences") + .withScope(this.$scope) + .withoutPersonalFilterOptions() + .withoutGridResetControls() + .withDefaultPageSize(10) + .withColumn(builder => builder + .withId("name") + .withDataSourceName("name") + .withTitle("Organisationsenhed") + .withSourceValueEchoRendering() + .withFilteringOperation(Kitos.Utility.KendoGrid.KendoGridColumnFiltering.Contains) + ) + .withColumn(builder => builder + .withId("category") + .withDataSourceName("category") + .withTitle("Ændring") + .withSourceValueEchoRendering() + .withFilteringOperation(Kitos.Utility.KendoGrid.KendoGridColumnFiltering.FixedValueRange) + .withFixedValueRange(kendoOptions, false) + ) + .withColumn(builder => builder + .withId("description") + .withDataSourceName("description") + .withTitle("Beskrivelse") + .withSourceValueEchoRendering() + .withFilteringOperation(Kitos.Utility.KendoGrid.KendoGridColumnFiltering.Contains) + ) + .resetAnySavedSettings() + .launch(); + }); + } + } + angular.module("app") + .component("fkOrgnizationImportConsequencesLog", setupComponent()); +} \ No newline at end of file diff --git a/Presentation.Web/app/components/local-config/import/fk-organization-import-consequences-log.view.html b/Presentation.Web/app/components/local-config/import/fk-organization-import-consequences-log.view.html new file mode 100644 index 0000000000..fbe663efda --- /dev/null +++ b/Presentation.Web/app/components/local-config/import/fk-organization-import-consequences-log.view.html @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/Presentation.Web/app/components/local-config/import/local-config-import-org.controller.ts b/Presentation.Web/app/components/local-config/import/local-config-import-org.controller.ts index d56f36a18e..18251692c5 100644 --- a/Presentation.Web/app/components/local-config/import/local-config-import-org.controller.ts +++ b/Presentation.Web/app/components/local-config/import/local-config-import-org.controller.ts @@ -10,11 +10,12 @@ ]); app.controller('local-config.import.ImportOrgCtrl', [ - '$rootScope', '$scope', '$http', 'notify', 'user', - function ($rootScope, $scope, $http, notify, user) { + '$scope', '$http', 'notify', 'user', 'featureToggleService', + function ($scope, $http, notify, user, featureToggleService: Kitos.Services.FeatureToggle.IFeatureToggleService) { $scope.url = 'api/excel?organizationId=' + user.currentOrganizationId + '&exportOrgUnits'; $scope.title = 'organisationsenheder'; - + $scope.showFkOrgImport = featureToggleService.hasFeature(Kitos.Services.FeatureToggle.TemporaryFeature.FK_Organisation); + $scope.currentOrganizationUuid = user.currentOrganizationUuid; //Import OrganizationUnits $scope.submit = function () { var msg = notify.addInfoMessage("Læser excel ark...", false); diff --git a/Presentation.Web/app/components/local-config/import/local-config-import-template.view.html b/Presentation.Web/app/components/local-config/import/local-config-import-template.view.html index 29488b1060..b70f810bd1 100644 --- a/Presentation.Web/app/components/local-config/import/local-config-import-template.view.html +++ b/Presentation.Web/app/components/local-config/import/local-config-import-template.view.html @@ -1,40 +1,56 @@ 
-
-
-
- Hent excel-ark til import af {{title}}. +
+
+ Via Excel
-
- - -
- - +
+
+
+
+ Hent excel-ark til import af {{title}}. +
+
+ + +
+ +
- -
-

-

- - Fejl ved import -

- Der var {{errorData.errors.length}} fejl i den uploadede fil og derfor er intet blevet importeret. Ret og prøv igen. -

-
    -
  • - Faneblad {{error.sheetName}}, celle {{error.column}}{{error.row}}: {{error.message}} -
  • -
+ +
+

+

+ + Fejl ved import +

+ Der var {{errorData.errors.length}} fejl i den uploadede fil og derfor er intet blevet importeret. Ret og prøv igen. +

+
    +
  • + Faneblad {{error.sheetName}}, celle {{error.column}}{{error.row}}: {{error.message}} +
  • +
+
+
+

+

+ + Fejl ved import +

+ Der skete en uforudset fejl i forbindelse med importen. Intet er derfor blevet importeret. +
+ Rapportér fejlen til din lokale adminstrator sammen med den excel fil du forsøgte at importere. Tak. +

+
+
-
-

-

- - Fejl ved import -

- Der skete en uforudset fejl i forbindelse med importen. Intet er derfor blevet importeret. -
- Rapportér fejlen til din lokale adminstrator sammen med den excel fil du forsøgte at importere. Tak. -

+ +
+
+ Via FK Organisation +
+
+ +
diff --git a/Presentation.Web/app/components/local-config/local-config-contract.view.html b/Presentation.Web/app/components/local-config/local-config-contract.view.html index da1481df29..09de5b564a 100644 --- a/Presentation.Web/app/components/local-config/local-config-contract.view.html +++ b/Presentation.Web/app/components/local-config/local-config-contract.view.html @@ -38,7 +38,7 @@
-
+
diff --git a/Presentation.Web/app/components/local-config/local-config-current-org.view.html b/Presentation.Web/app/components/local-config/local-config-current-org.view.html index b7fc8155f9..35cea992e0 100644 --- a/Presentation.Web/app/components/local-config/local-config-current-org.view.html +++ b/Presentation.Web/app/components/local-config/local-config-current-org.view.html @@ -24,31 +24,3 @@
-
-
- -
-
- -
-
- -
-
- -
-
-
-
-
diff --git a/Presentation.Web/app/components/local-config/local-config-dataProcessing.view.html b/Presentation.Web/app/components/local-config/local-config-dataProcessing.view.html index ac98389062..24d4871a5b 100644 --- a/Presentation.Web/app/components/local-config/local-config-dataProcessing.view.html +++ b/Presentation.Web/app/components/local-config/local-config-dataProcessing.view.html @@ -16,8 +16,8 @@
-
-
+
+
-
+
diff --git a/Presentation.Web/app/components/local-config/local-config-org.controller.ts b/Presentation.Web/app/components/local-config/local-config-org.controller.ts index 0cbdd6e0e1..a401140a01 100644 --- a/Presentation.Web/app/components/local-config/local-config-org.controller.ts +++ b/Presentation.Web/app/components/local-config/local-config-org.controller.ts @@ -162,7 +162,7 @@ }, groupable: false, columnMenu: true, - height: window.innerHeight - 200, + height: window.innerHeight - 150, dataBound: this.saveGridOptions, columnResize: this.saveGridOptions, columnHide: this.saveGridOptions, diff --git a/Presentation.Web/app/components/local-config/local-config-system.view.html b/Presentation.Web/app/components/local-config/local-config-system.view.html index 4a4a1e39d9..3a9250bbad 100644 --- a/Presentation.Web/app/components/local-config/local-config-system.view.html +++ b/Presentation.Web/app/components/local-config/local-config-system.view.html @@ -42,8 +42,8 @@
-
+
-
+
diff --git a/Presentation.Web/app/components/local-config/localOptionList/localOptionList.directive.ts b/Presentation.Web/app/components/local-config/localOptionList/localOptionList.directive.ts index 169eebeea2..822bd1b221 100644 --- a/Presentation.Web/app/components/local-config/localOptionList/localOptionList.directive.ts +++ b/Presentation.Web/app/components/local-config/localOptionList/localOptionList.directive.ts @@ -7,7 +7,8 @@ editState: "@state", dirId: "@", optionType: "@", - currentOrgId: "@" + currentOrgId: "@", + disableEdit: "@" }, controller: LocalOptionListDirective, controllerAs: "ctrl", @@ -35,6 +36,7 @@ public optionId: string; public dirId: string; public optionType: string; + public disableEdit: boolean; public mainGrid: IKendoGrid; public mainGridOptions: IKendoGridOptions; @@ -52,6 +54,7 @@ this.editState = $scope.editState; this.dirId = $scope.dirId; this.optionType = $scope.optionType; + this.disableEdit = ($scope.disableEdit === "true"); this.mainGridOptions = { dataSource: { @@ -117,10 +120,15 @@ operator: "contains" } } - }, + } as any + ] + }; + + if (!this.disableEdit) { + this.mainGridOptions.columns.push( { field: "Description", title: "Beskrivelse", width: 230, - persistId: "description", + persistId: "description", template: (dataItem) => dataItem.Description, hidden: false, filterable: { @@ -135,12 +143,12 @@ { name: "editOption", text: "Redigér", - template: "", + template: ``, title: " ", width: 176 } as any - ] - }; + ); + } function customFilter(args) { args.element.kendoAutoComplete({ diff --git a/Presentation.Web/app/components/org/org-subnav.controller.ts b/Presentation.Web/app/components/org/org-subnav.controller.ts index c77bf0643d..4cf65ad5b8 100644 --- a/Presentation.Web/app/components/org/org-subnav.controller.ts +++ b/Presentation.Web/app/components/org/org-subnav.controller.ts @@ -22,10 +22,6 @@ var subnav = []; - if (user.currentConfig.showTabOverview) { - subnav.push({ state: 'organization.overview', text: 'Overblik' }); - } - subnav.push({ state: 'organization.structure', text: 'Organisation' }); subnav.push({ state: 'organization.user', text: 'Brugere' }); subnav.push({ state: 'organization.gdpr', text: 'Stamdata' }); diff --git a/Presentation.Web/app/components/org/overview/org-overview-modal-comment.view.html b/Presentation.Web/app/components/org/overview/org-overview-modal-comment.view.html deleted file mode 100644 index 0116567fe2..0000000000 --- a/Presentation.Web/app/components/org/overview/org-overview-modal-comment.view.html +++ /dev/null @@ -1,28 +0,0 @@ - - - diff --git a/Presentation.Web/app/components/org/overview/org-overview-task-foldout-leaf.view.html b/Presentation.Web/app/components/org/overview/org-overview-task-foldout-leaf.view.html deleted file mode 100644 index 5b274e7735..0000000000 --- a/Presentation.Web/app/components/org/overview/org-overview-task-foldout-leaf.view.html +++ /dev/null @@ -1,40 +0,0 @@ -
- -
- {{ indent(usage.level) }} - - {{ usage.orgUnitName }} -
- - -
-
- -
-
- -
-
- - -
-
- - -
-
diff --git a/Presentation.Web/app/components/org/overview/org-overview-task-foldout-node.view.html b/Presentation.Web/app/components/org/overview/org-overview-task-foldout-node.view.html deleted file mode 100644 index 8c86cb1c4b..0000000000 --- a/Presentation.Web/app/components/org/overview/org-overview-task-foldout-node.view.html +++ /dev/null @@ -1,48 +0,0 @@ -
-
-
- {{ indent(usage.level) }} - - - {{ usage.orgUnitName }} - -
- -
-
-
-
- - -
-
- -
-
-
- -
-
-
-
-
-
-
-
-
-
-
diff --git a/Presentation.Web/app/components/org/overview/org-overview-usage.view.html b/Presentation.Web/app/components/org/overview/org-overview-usage.view.html deleted file mode 100644 index 532353b54d..0000000000 --- a/Presentation.Web/app/components/org/overview/org-overview-usage.view.html +++ /dev/null @@ -1,105 +0,0 @@ -
- -
- - {{ usage.orgUnitName }} -
- - -
{{ usage.taskRefTaskKey }}
-
{{ usage.taskRefDescription }}
- - -
-
- -
-
- -
-
- - -
-
- - -
- - - -
-
- -
-
- - - - -
{{ usage.taskRefTaskKey }}
-
{{ usage.taskRefDescription }}
- - -
-
-
- -
- - -
-
- - -
- - - -
-
- - -
-
-
-
-
-
-
-
-
-
-
diff --git a/Presentation.Web/app/components/org/overview/org-overview.controller.ts b/Presentation.Web/app/components/org/overview/org-overview.controller.ts deleted file mode 100644 index bd98a3ec8a..0000000000 --- a/Presentation.Web/app/components/org/overview/org-overview.controller.ts +++ /dev/null @@ -1,242 +0,0 @@ -(function(ng, app) { - function indent(level) { - var result = ""; - for (var i = 0; i < level; i++) result += "....."; - - return result; - }; - - app.config([ - '$stateProvider', function($stateProvider) { - $stateProvider.state('organization.overview', { - url: '/overview', - templateUrl: 'app/components/org/overview/org-overview.view.html', - controller: 'org.OverviewCtrl', - resolve: { - orgUnits: [ - '$http', 'user', function ($http, user) { - return $http.get('api/organizationUnit?organization=' + user.currentOrganizationId).then(function (result) { - var options: Kitos.Models.ViewModel.Generic.Select2OptionViewModelWithIndentation[] = []; - - function visit(orgUnit: Kitos.Models.Api.Organization.OrganizationUnit, indentationLevel: number) { - var option = { - id: String(orgUnit.id), - text: orgUnit.name, - indentationLevel: indentationLevel - }; - - options.push(option); - - _.each(orgUnit.children, function (child) { - return visit(child, indentationLevel + 1); - }); - - } - visit(result.data.response, 0); - return options; - }); - } - ], - } - }); - } - ]); - - app.controller('org.OverviewCtrl', [ - '$rootScope', '$scope', '$http', '$uibModal', 'user', "orgUnits", - function ($rootScope, $scope, $http, $modal, user, orgUnits: Kitos.Models.ViewModel.Generic.Select2OptionViewModelWithIndentation[]) { - - $scope.orgUnits = orgUnits; - $scope.allowClear = false; - - $rootScope.page.title = 'Organisation - Overblik'; - - function checkForDefaultUnit() { - if (!user.currentOrganizationUnitId) return; - - var selectedDefaultOrganization = _.find($scope.orgUnits, (orgUnit) => orgUnit.id === String(user.currentOrganizationUnitId)); - if (selectedDefaultOrganization !== undefined) { - $scope.orgUnitId = user.currentOrganizationUnitId; - } - } - checkForDefaultUnit(); - - $scope.pagination = { - skip: 0, - take: 10, - orderBy: 'taskRef.taskKey' - }; - - $scope.csvUrl = 'api/taskusage/?csv&orgUnitId=' + $scope.orgUnitId + '&onlyStarred=true' + '&orgUnitId=' + user.currentOrganizationId; - - $scope.$watchCollection('pagination', function() { - loadUsages(); - }); - - /* load task usages */ - function loadUsages() { - if (!$scope.orgUnitId) return; - if (!$scope.orgUnitId.id) return; - - var url = 'api/taskusage/?orgUnitId=' + $scope.orgUnitId.id + '&onlyStarred=true' + '&organizationId=' + user.currentOrganizationId; - - url += '&skip=' + $scope.pagination.skip; - url += '&take=' + $scope.pagination.take; - - if ($scope.pagination.orderBy) { - url += '&orderBy=' + $scope.pagination.orderBy; - if ($scope.pagination.descending) url += '&descending=' + $scope.pagination.descending; - } - - $http.get(url) - .then(function onSuccess(result) { - var paginationHeader = JSON.parse(result.headers('X-Pagination')); - $scope.totalCount = paginationHeader.TotalCount; - $scope.taskUsages = result.data.response; - - /* visit every task usage and delegation */ - function visit(usage, parent, level) { - usage.updateUrl = 'api/taskUsage/' + usage.id; - usage.parent = parent; - usage.level = level; - - if (parent) usage.hasWriteAccess = parent.hasWriteAccess; - - /* if this task hasn't been delegated, it's a leaf. A leaf can select and update the statuses - * at which point we need to update the parents statuses as well - */ - if (!usage.hasDelegations) { - $scope.$watch(function() { return usage.technologyStatus; }, function(newVal, oldVal) { - updateTechStatus(usage); - }); - $scope.$watch(function() { return usage.usageStatus; }, function(newVal, oldVal) { - updateUsageStatus(usage); - }); - } - - /* visit children */ - _.each(usage.children, function(child) { - visit(child, usage, level + 1); - }); - } - - /* each of these are root usages */ - _.each($scope.taskUsages, function(usage: { isRoot }) { - usage.isRoot = true; - - visit(usage, null, 0); - - updateTechStatus(usage); - updateUsageStatus(usage); - }); - }); - }; - - $scope.loadUsages = loadUsages; - - function updateTechStatus(usage) { - if (usage.parent) { - updateTechStatus(usage.parent); - } else { - calculateTechStatus(usage); - } - }; - - function updateUsageStatus(usage) { - if (usage.parent) { - updateUsageStatus(usage.parent); - } else { - calculateUsageStatus(usage); - } - }; - - /* helper function to aggregate status-trafficlight */ - function addToStatusResult(status, result) { - if (status == 3) result.green++; - else if (status == 2) result.yellow++; - else if (status == 1) result.red++; - else result.white++; - - result.max++; - - return result; - } - - /* helper function to sum two status-trafficlights */ - function sumStatusResult(result1, result2) { - return { - max: result1.max + result2.max, - white: result1.white + result2.white, - red: result1.red + result2.red, - yellow: result1.yellow + result2.yellow, - green: result1.green + result2.green - }; - } - - function calculateTechStatus(usage) { - - /* this will hold the aggregated tech status of this node */ - var result = { - max: 0, - white: 0, - red: 0, - yellow: 0, - green: 0, - }; - - /* if the usage isn't delegated, the agg result is just this tech status */ - if (!usage.hasDelegations) { - result = addToStatusResult(usage.technologyStatus, result); - } else { - _.each(usage.children, function(child) { - var delegationResult = calculateTechStatus(child); - result = sumStatusResult(result, delegationResult); - }); - } - - usage.calculatedTechStatus = result; - - return result; - }; - - - function calculateUsageStatus(usage) { - var result = { - max: 0, - white: 0, - red: 0, - yellow: 0, - green: 0 - }; - - if (!usage.hasDelegations) { - return addToStatusResult(usage.usageStatus, result); - } - - _.each(usage.children, function(child) { - var delegationResult = calculateUsageStatus(child); - result = sumStatusResult(result, delegationResult); - }); - - usage.calculatedUsageStatus = result; - - return result; - }; - - $scope.indent = indent; - - $scope.openComment = function(usage) { - $modal.open({ - templateUrl: 'app/components/org/overview/org-overview-modal-comment.view.html', - controller: [ - '$scope', '$uibModalInstance', 'autofocus', function ($modalScope, $modalInstance, autofocus) { - autofocus(); - $modalScope.usage = usage; - $modalScope.hasWriteAccess = usage.hasWriteAccess; - } - ] - }); - }; - } - ]); -})(angular, app); diff --git a/Presentation.Web/app/components/org/overview/org-overview.view.html b/Presentation.Web/app/components/org/overview/org-overview.view.html deleted file mode 100644 index dd489d12bb..0000000000 --- a/Presentation.Web/app/components/org/overview/org-overview.view.html +++ /dev/null @@ -1,46 +0,0 @@ - - -
-
- - -
-
- KLE ID - -
-
- KLE Navn - -
-
-
- Digitaliseringsgrad -
-
- Teknologi - Anvendelse -
- -
-
IT System
-
- -
-
-
- -
- -
- - -  diff --git a/Presentation.Web/app/components/org/structure/org-structure-modal-edit.view.html b/Presentation.Web/app/components/org/structure/org-structure-modal-edit.view.html index fce1947314..de7a6611f0 100644 --- a/Presentation.Web/app/components/org/structure/org-structure-modal-edit.view.html +++ b/Presentation.Web/app/components/org/structure/org-structure-modal-edit.view.html @@ -1,63 +1,81 @@ 
-