909 lines
38 KiB
C#
909 lines
38 KiB
C#
using System.Collections.ObjectModel;
|
|
using Blazored.Modal.Services;
|
|
using Blazored.Toast.Services;
|
|
using DocumentTypeRetriever;
|
|
using LCU.Library.DocumentType.Enums;
|
|
using LCU.Library.DocumentType.Extensions;
|
|
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts;
|
|
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests;
|
|
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Organizations;
|
|
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons;
|
|
using LCU.Library.Internal.DocumentIngestorModels.Enums;
|
|
using LCU.WebApps.Internal.DocumentManager.Enums;
|
|
using LCU.WebApps.Internal.DocumentManager.Models;
|
|
using LCU.WebApps.Internal.DocumentManager.Configurations;
|
|
using LCU.WebApps.Internal.DocumentManager.Services;
|
|
using LCU.WebApps.Internal.DocumentManager.Shared.Components;
|
|
using LCU.WebApps.Internal.DocumentManager.Shared.JSInterop;
|
|
using Microsoft.AspNetCore.Components;
|
|
using Microsoft.JSInterop;
|
|
using Serilog;
|
|
using DocumentAction = LCU.Library.Internal.DocumentModels.Requests.DocumentAction;
|
|
using DocumentAuditResponse = LCU.Library.Internal.DocumentModels.Responses.DocumentAuditResponse;
|
|
using DocumentMetadataResponse = LCU.Library.DocumentType.Models.Responses.External.DocumentMetadataResponse;
|
|
|
|
namespace LCU.WebApps.Internal.DocumentManager.Shared.DocumentGridView;
|
|
|
|
public interface IBusinessViewViewModel : ITablePagingViewModel<BusinessViewDocumentInformation, BusinessViewFilter>, IDocumentAuthorization
|
|
{
|
|
event EventHandler DataLoadError;
|
|
void FilterChanged(OwnershipTypes? ownership, string field, string value);
|
|
}
|
|
|
|
public class BusinessViewViewModel : IBusinessViewViewModel
|
|
{
|
|
public bool Loaded { get; private set; } = false;
|
|
public BusinessViewFilter Filter { get; } = new();
|
|
|
|
public bool FilterIsValid { get; set; } = true;
|
|
public event EventHandler? OnFilterValidityChanged = delegate { };
|
|
public void FilterChanged(OwnershipTypes? ownership, string field, string value)
|
|
{
|
|
FilterIsValid = ownership switch
|
|
{
|
|
null => true,
|
|
OwnershipTypes.AccountNumber or OwnershipTypes.MemberNumber or OwnershipTypes.OrganizationNumber or OwnershipTypes.PersonNumber
|
|
=> float.TryParse(value, out _),
|
|
OwnershipTypes.PersonName when field is nameof(Filter.OwnershipType)
|
|
=> !(string.IsNullOrWhiteSpace(value) && string.IsNullOrWhiteSpace(Filter.AdditionalOwnershipValue)),
|
|
OwnershipTypes.PersonName when field is nameof(Filter.AdditionalOwnershipValue)
|
|
=> !(string.IsNullOrWhiteSpace(Filter.OwnershipValue) && string.IsNullOrWhiteSpace(value)),
|
|
OwnershipTypes.OrganizationName
|
|
=> !string.IsNullOrWhiteSpace(value),
|
|
_ => false
|
|
};
|
|
}
|
|
|
|
public ObservableCollection<BusinessViewDocumentInformation> VisibleItems { get; } = new();
|
|
public event EventHandler DataChanged = delegate { };
|
|
public event EventHandler DataLoadError = delegate { };
|
|
|
|
public int ItemsPerPage { get; private set; } = 10;
|
|
public IReadOnlyList<int> PossibleItemsPerPage { get; } = new[] { 10, 25, 50 };
|
|
public int CurrentPage { get; private set; } = 1;
|
|
public int TotalPages => (int)Math.Ceiling((double)TotalItems / ItemsPerPage);
|
|
public int TotalItems { get; private set; }
|
|
public bool NoPriorPage => CurrentPage <= 1;
|
|
public bool NoNextPage => CurrentPage >= TotalPages;
|
|
public int VisibleItemsCount { get; private set; }
|
|
public IList<string> SelectedSortableFields => Filter.DocumentProcessingFilter.SortDefinition!.Select(f => f.Field).ToList();
|
|
|
|
private readonly string[] _sortableFields = { "CreatedDate" };
|
|
public IReadOnlyList<string> AvailableSortableFields => _sortableFields
|
|
.Except(SelectedSortableFields)
|
|
.ToList();
|
|
|
|
private delegate object GetBusinessViewDocumentInformationValue(BusinessViewDocumentInformation details);
|
|
|
|
private static readonly IReadOnlyDictionary<string, GetBusinessViewDocumentInformationValue> SortableValues =
|
|
new Dictionary<string, GetBusinessViewDocumentInformationValue>
|
|
{
|
|
{
|
|
"CreatedDate",
|
|
details => details.DocumentInformation.CreatedDate
|
|
},
|
|
{
|
|
"DocumentType",
|
|
details => details.DocumentInformation.DocumentType
|
|
},
|
|
{
|
|
"DocumentBusinessName",
|
|
details => details.DocumentInformation.DocumentBusinessName
|
|
},
|
|
{
|
|
"EntityName",
|
|
details => details.DocumentInformation.EntityName
|
|
}
|
|
};
|
|
|
|
private IDictionary<Guid, DocumentMetadataResponse> _visibleDocuments = new Dictionary<Guid, DocumentMetadataResponse>();
|
|
private readonly IModalService _modal;
|
|
private readonly IDocumentService _documentService;
|
|
private readonly IEntityService _entityService;
|
|
private readonly IDocumentTypeService _documentTypeService;
|
|
private readonly IJSDocument _jsDocument;
|
|
private readonly IDocumentTypeUploaderService _documentTypeUploaderService;
|
|
private readonly IToastService _toastService;
|
|
private readonly IEntityService _coreApiWrapperService;
|
|
private readonly IDocumentProcessingInfoService _documentProcessingInfoService;
|
|
|
|
public BusinessViewViewModel
|
|
(
|
|
IModalService modal,
|
|
IEntityService entityService,
|
|
IDocumentService documentService,
|
|
IDocumentTypeService documentTypeService,
|
|
IDocumentTypeUploaderService documentTypeUploaderService,
|
|
IEntityService coreApiWrapperService,
|
|
IToastService toastService,
|
|
IJSDocument jsDocument,
|
|
AppConfiguration configuration,
|
|
IDocumentProcessingInfoService documentProcessingInfoService
|
|
)
|
|
{
|
|
_modal = modal;
|
|
_entityService = entityService;
|
|
_documentService = documentService;
|
|
_documentTypeService = documentTypeService;
|
|
_coreApiWrapperService = coreApiWrapperService;
|
|
_toastService = toastService;
|
|
_jsDocument = jsDocument;
|
|
_documentProcessingInfoService = documentProcessingInfoService;
|
|
_documentTypeUploaderService = documentTypeUploaderService;
|
|
|
|
(
|
|
Filter.DocumentProcessingFilter.Filter.CreatedDateMinimum,
|
|
Filter.DocumentProcessingFilter.Filter.CreatedDateMaximum
|
|
) = DefaultFilterDateRange(configuration.DefaultFilters);
|
|
}
|
|
|
|
public async Task GoToPage(int page)
|
|
{
|
|
var loading = LoadingLighthouse.Show(_modal);
|
|
|
|
try
|
|
{
|
|
var documentTypes = _documentTypeService.GetDocumentTypes()
|
|
.ContinueWith(r => r.Result.ToDictionary(t => t.DocumentCode));
|
|
|
|
CurrentPage = page;
|
|
Filter.DocumentProcessingFilter.Skip = (CurrentPage - 1) * ItemsPerPage;
|
|
Filter.DocumentProcessingFilter.Take = ItemsPerPage;
|
|
_visibleDocuments = (await _documentService.GetDocuments(Filter.DocumentProcessingFilter)).ToDictionary(d => d.DocumentId);
|
|
|
|
VisibleItemsCount = _visibleDocuments.Count;
|
|
|
|
var logs = _documentService
|
|
.GetDocumentLogs(_visibleDocuments.Keys.ToArray())
|
|
.ContinueWith(response => response.Result.GroupBy(l => l.DocumentId).ToDictionary(g => g.Key));
|
|
|
|
var awaitingDocuments = _visibleDocuments.Values.Select(async document =>
|
|
{
|
|
var accountOwnerships = document.AccountNumber is {} accountNumber
|
|
? (await _entityService.GetOwnersByAccountNumber(accountNumber, document.CreatedDate)).ToList()
|
|
: await DetermineOwnerByPersonOrOrganizationNumber(document);
|
|
|
|
var primaryAccountOwnership = GetPrimaryOwner(accountOwnerships);
|
|
var entityName = GetPrimaryOwnerName(primaryAccountOwnership);
|
|
|
|
var entityHasAccess = DoesPrimaryOwnerHaveAccess(primaryAccountOwnership, document.PersonNumbers, document.OrganizationNumbers);
|
|
|
|
var accountOwners = GetAccountOwners(accountOwnerships);
|
|
|
|
var personNumbers = new ObservableCollection<string>(document.PersonNumbers ?? Array.Empty<string>());
|
|
var organizationNumbers = new ObservableCollection<string>(document.OrganizationNumbers ?? Array.Empty<string>());
|
|
|
|
var documentAccess = new ObservableCollection<DocumentAccess>();
|
|
|
|
if (primaryAccountOwnership != null)
|
|
{
|
|
documentAccess.Add(new DocumentAccess(AccessType.PrimaryOwner, entityHasAccess, entityName,
|
|
primaryAccountOwnership.ByOrgNbr == 0
|
|
? primaryAccountOwnership.PersonNumber.ToString()
|
|
: primaryAccountOwnership.ByOrgNbr.ToString()));
|
|
}
|
|
else
|
|
{
|
|
documentAccess.Add(new DocumentAccess(AccessType.PrimaryOwner, true, entityName, "0"));
|
|
}
|
|
|
|
var documentPersonNumbers = document.PersonNumbers?.Where(p => p is not null).ToArray() ?? Array.Empty<string>();
|
|
var documentOrganizationNumbers = document.OrganizationNumbers?.Where(o => o is not null).ToArray() ?? Array.Empty<string>();
|
|
|
|
foreach (var access in GetOwnerAccess(documentPersonNumbers, documentOrganizationNumbers,
|
|
accountOwners, entityName))
|
|
{
|
|
documentAccess.Add(access);
|
|
}
|
|
|
|
foreach (var access in await GetAdditionalAccess(documentPersonNumbers, documentOrganizationNumbers, accountOwners))
|
|
{
|
|
documentAccess.Add(access);
|
|
}
|
|
|
|
foreach (var access in GetRemovedAccess(documentPersonNumbers, documentOrganizationNumbers, accountOwners, entityName))
|
|
{
|
|
documentAccess.Add(access);
|
|
}
|
|
|
|
(await documentTypes).TryGetValue(document.Type ?? string.Empty, out var documentType);
|
|
|
|
var info = new DocumentInformation
|
|
(
|
|
document.DocumentId,
|
|
document.TraceId,
|
|
document.Source,
|
|
document.DataSource,
|
|
document.CreatedDate,
|
|
document.UploadDate,
|
|
document.Name,
|
|
documentType?.DocumentType.ToString() ?? "unknown",
|
|
documentType?.DocumentCode ?? "unknown",
|
|
documentType?.DocumentBusinessName ?? "unknown",
|
|
documentType?.DocumentMemberFacingName ?? "unknown",
|
|
documentType?.OnlineBankingRetentionMonths ?? 24,
|
|
documentType?.InternalRetentionMonths ?? 84,
|
|
entityName,
|
|
accountOwners,
|
|
documentAccess,
|
|
personNumbers,
|
|
organizationNumbers,
|
|
document.AccountNumber,
|
|
documentType?.IsDisabledInMemberView(document) ?? true,
|
|
document.ScanStatus,
|
|
() => Download(document)
|
|
);
|
|
|
|
return new BusinessViewDocumentInformation
|
|
(
|
|
info,
|
|
(await logs).TryGetValue(document.DocumentId, out var documentLogs)
|
|
? documentLogs
|
|
: Enumerable.Empty<DocumentAuditResponse>()
|
|
);
|
|
});
|
|
|
|
IEnumerable<BusinessViewDocumentInformation> completedDocuments = await Task.WhenAll(awaitingDocuments);
|
|
|
|
if (VisibleItemsCount == 0)
|
|
{
|
|
_toastService.ShowWarning("No documents were found with the applied filters");
|
|
}
|
|
|
|
VisibleItems.Clear();
|
|
foreach (var document in completedDocuments)
|
|
{
|
|
VisibleItems.Add(document);
|
|
}
|
|
|
|
DataChanged(this, EventArgs.Empty);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
DataLoadError(this, EventArgs.Empty);
|
|
Log.Error(exception, exception.Message);
|
|
}
|
|
|
|
loading.Close();
|
|
}
|
|
|
|
private async Task<List<AccountOwnership>> DetermineOwnerByPersonOrOrganizationNumber(DocumentMetadataResponse document)
|
|
{
|
|
var accountOwnerships = new List<AccountOwnership>();
|
|
|
|
if (EnumExtensions.IsDocumentTypeOf<PrimaryOwnerDocumentTypes>(document.Type))
|
|
{
|
|
if (document.PersonNumbers?.Count() == 1 && !string.IsNullOrWhiteSpace(document.PersonNumbers.FirstOrDefault()))
|
|
{
|
|
var person = (await _entityService.GetPersonByEntityNumber(document.PersonNumbers.FirstOrDefault()))
|
|
.FirstOrDefault();
|
|
if (person != null)
|
|
{
|
|
accountOwnerships.Add(new AccountOwnership()
|
|
{
|
|
FirstName = person.FirstName,
|
|
MiddleInitial = person.MiddleInitial,
|
|
MiddleName = person.MiddleName,
|
|
LastName = person.LastName,
|
|
Suffix = person.Suffix,
|
|
PersonNumber = person.PersonNumber,
|
|
IsPrimaryOwner = true
|
|
});
|
|
}
|
|
}
|
|
else if (document.OrganizationNumbers?.Count() == 1 &&
|
|
!string.IsNullOrWhiteSpace(document.OrganizationNumbers.FirstOrDefault()))
|
|
{
|
|
var organization =
|
|
(await _entityService.GetOrganizationByEntityNumber(document.OrganizationNumbers.FirstOrDefault()))
|
|
.FirstOrDefault();
|
|
if (organization != null)
|
|
{
|
|
accountOwnerships.Add(new AccountOwnership()
|
|
{
|
|
OrganizationName = organization.Name,
|
|
ByOrgNbr = organization.OrganizationNumber,
|
|
IsPrimaryOwner = true
|
|
});
|
|
}
|
|
}
|
|
}
|
|
else if (EnumExtensions.IsDocumentTypeOf<AccountDocumentTypes>(document.Type))
|
|
{
|
|
var ownersByAccountNumber =
|
|
await _entityService.GetOwnersByAccountNumber(document.AccountNumber.Value, document.CreatedDate);
|
|
accountOwnerships = ownersByAccountNumber?.ToList();
|
|
}
|
|
|
|
return accountOwnerships;
|
|
}
|
|
|
|
private Dictionary<string, Dictionary<string, string>> GetAccountOwners(IEnumerable<AccountOwnership> accountOwnerships)
|
|
{
|
|
var distinctAccountOwners = new Dictionary<string, Dictionary<string, string>>
|
|
{
|
|
["persons"] = new Dictionary<string, string>(),
|
|
["organizations"] = new Dictionary<string, string>()
|
|
};
|
|
|
|
if (accountOwnerships == null)
|
|
{
|
|
return distinctAccountOwners;
|
|
}
|
|
foreach (var owner in accountOwnerships)
|
|
{
|
|
if(owner.ByOrgNbr != 0)
|
|
{
|
|
var key = owner.ByOrgNbr.ToString();
|
|
var value = GetName(owner);
|
|
if (!distinctAccountOwners["organizations"].ContainsKey(key))
|
|
{
|
|
distinctAccountOwners["organizations"].Add(key, value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var key = owner.PersonNumber.ToString();
|
|
var value = GetName(owner);
|
|
if (!distinctAccountOwners["persons"].ContainsKey(key))
|
|
{
|
|
distinctAccountOwners["persons"].Add(key, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
return distinctAccountOwners;
|
|
}
|
|
|
|
private static AccountOwnership? GetPrimaryOwner(IEnumerable<AccountOwnership> accountOwnerships)
|
|
{
|
|
return accountOwnerships.FirstOrDefault(x => x.IsPrimaryOwner);
|
|
}
|
|
|
|
private string GetPrimaryOwnerName(AccountOwnership? primaryAccountOwnership)
|
|
{
|
|
if(primaryAccountOwnership != null)
|
|
{
|
|
return GetName(primaryAccountOwnership);
|
|
}
|
|
else
|
|
{
|
|
return "No primary owner found";
|
|
}
|
|
}
|
|
|
|
private List<DocumentAccess> GetOwnerAccess(string[] personNumbers, string[] organizationNumbers, Dictionary<string, Dictionary<string, string>> accounts, string entityName)
|
|
{
|
|
var access = new List<DocumentAccess>();
|
|
|
|
if(!accounts.Any())
|
|
{
|
|
return access;
|
|
}
|
|
|
|
if (personNumbers != null)
|
|
{
|
|
foreach (var account in accounts["persons"].Where(x => personNumbers.Contains(x.Key)))
|
|
{
|
|
if(!account.Value.Equals(entityName, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
access.Add(new DocumentAccess(AccessType.Owner, true, account.Value, account.Key));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (organizationNumbers != null)
|
|
{
|
|
foreach (var account in accounts["organizations"].Where(x => organizationNumbers.Contains(x.Key)))
|
|
{
|
|
if (!account.Value.Equals(entityName, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
access.Add(new DocumentAccess(AccessType.Owner, true, account.Value, account.Key));
|
|
}
|
|
}
|
|
}
|
|
|
|
return access;
|
|
}
|
|
|
|
private async Task<List<DocumentAccess>> GetAdditionalAccess(string[] personNumbers, string[] organizationNumbers, Dictionary<string, Dictionary<string, string>> accounts)
|
|
{
|
|
var access = new List<DocumentAccess>();
|
|
|
|
foreach (var memberNumber in personNumbers.Where(x => !string.IsNullOrWhiteSpace(x) && !accounts["persons"].ContainsKey(x)))
|
|
{
|
|
var personEntity = (await _entityService.GetPersonByEntityNumber(memberNumber)).FirstOrDefault();
|
|
if (personEntity != null)
|
|
{
|
|
access.Add(new DocumentAccess(AccessType.Additional, true, personEntity.NameFull, personEntity.PersonNumber.ToString()));
|
|
}
|
|
}
|
|
|
|
foreach (var memberNumber in organizationNumbers.Where(x => !string.IsNullOrWhiteSpace(x) && !accounts["organizations"].ContainsKey(x)))
|
|
{
|
|
var orgEntity = (await _entityService.GetOrganizationByEntityNumber(memberNumber)).FirstOrDefault();
|
|
if (orgEntity != null)
|
|
{
|
|
access.Add(new DocumentAccess(AccessType.Additional, true, orgEntity.Name, orgEntity.OrganizationNumber.ToString()));
|
|
}
|
|
}
|
|
|
|
return access;
|
|
}
|
|
|
|
private List<DocumentAccess> GetRemovedAccess(string[] personNumbers, string[] organizationNumbers, Dictionary<string, Dictionary<string, string>> accounts, string entityName)
|
|
{
|
|
var access = new List<DocumentAccess>();
|
|
|
|
if (!accounts["persons"].Any() && !accounts["organizations"].Any())
|
|
{
|
|
return access;
|
|
}
|
|
|
|
if (personNumbers == null)
|
|
{
|
|
personNumbers = Array.Empty<string>();
|
|
}
|
|
|
|
if (organizationNumbers == null)
|
|
{
|
|
organizationNumbers = Array.Empty<string>();
|
|
}
|
|
|
|
foreach (var account in accounts["persons"].Where(x => !personNumbers.Contains(x.Key)))
|
|
{
|
|
if (!account.Value.Equals(entityName, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
access.Add(new DocumentAccess(AccessType.Removed, false, account.Value, account.Key));
|
|
}
|
|
}
|
|
|
|
foreach (var account in accounts["organizations"].Where(x => !organizationNumbers.Contains(x.Key)))
|
|
{
|
|
if (!account.Value.Equals(entityName, StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
access.Add(new DocumentAccess(AccessType.Removed, false, account.Value, account.Key));
|
|
}
|
|
}
|
|
return access;
|
|
}
|
|
|
|
private static bool DoesPrimaryOwnerHaveAccess(AccountOwnership? primaryAccountOwnership, ICollection<string> personNumbers, ICollection<string> organizationNumbers)
|
|
{
|
|
var primaryOwnerHasAccess = false;
|
|
|
|
if (primaryAccountOwnership != null)
|
|
{
|
|
if (personNumbers != null && personNumbers.Contains(primaryAccountOwnership.PersonNumber.ToString()))
|
|
{
|
|
primaryOwnerHasAccess = true;
|
|
}
|
|
if (organizationNumbers != null && organizationNumbers.Contains(primaryAccountOwnership.ByOrgNbr.ToString()))
|
|
{
|
|
primaryOwnerHasAccess = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// No primary owner should return true so the value does not have a strike-through on the view
|
|
primaryOwnerHasAccess = true;
|
|
}
|
|
|
|
return primaryOwnerHasAccess;
|
|
}
|
|
|
|
private string GetName(AccountOwnership account)
|
|
{
|
|
if(account.ByOrgNbr == 0)
|
|
{
|
|
var name = account.FirstName + " ";
|
|
if(!String.IsNullOrEmpty(account.MiddleName))
|
|
{
|
|
name += account.MiddleName + " ";
|
|
}
|
|
else if(!String.IsNullOrEmpty(account.MiddleInitial))
|
|
{
|
|
name += account.MiddleInitial + ". ";
|
|
}
|
|
name += account.LastName;
|
|
return name;
|
|
}
|
|
|
|
return account.OrganizationName;
|
|
}
|
|
|
|
public async Task OnItemsPerPageValueChanged(ChangeEventArgs e)
|
|
{
|
|
Filter.DocumentProcessingFilter.Take = ItemsPerPage = int.Parse(e.Value!.ToString()!);
|
|
Filter.DocumentProcessingFilter.Skip = 0;
|
|
|
|
await Refresh();
|
|
}
|
|
|
|
public async Task Refresh()
|
|
{
|
|
try
|
|
{
|
|
TotalItems = (int)await _documentService.CountDocuments(Filter.DocumentProcessingFilter.Filter);
|
|
Loaded = true;
|
|
|
|
await GoToPage(1);
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
public async Task ApplyFilterAndSorting()
|
|
{
|
|
var loading = LoadingLighthouse.Show(_modal);
|
|
|
|
Filter.DocumentProcessingFilter.Skip = 0;
|
|
Filter.DocumentProcessingFilter.Filter.PersonNumbersContainsAny = null;
|
|
Filter.DocumentProcessingFilter.Filter.OrganizationNumbersContainsAny = null;
|
|
Filter.DocumentProcessingFilter.Filter.AccountNumberContainsAny = null;
|
|
var shouldRefresh = true;
|
|
|
|
if (Filter.OwnershipType != null &&
|
|
(!string.IsNullOrWhiteSpace(Filter.OwnershipValue) || !string.IsNullOrWhiteSpace(Filter.AdditionalOwnershipValue)))
|
|
{
|
|
switch (Filter.OwnershipType)
|
|
{
|
|
case OwnershipTypes.MemberNumber:
|
|
try
|
|
{
|
|
var member = await _coreApiWrapperService.GetPersonOrOrganizationNumberByMemberId((long)Convert.ToDouble(Filter.OwnershipValue));
|
|
|
|
if (member is { PersonNumber: { } personNumber })
|
|
{
|
|
Filter.DocumentProcessingFilter.Filter.PersonNumbersContainsAny = new[] { personNumber };
|
|
}
|
|
|
|
if (member is { OrganizationNumber: { } organizationNumber })
|
|
{
|
|
Filter.DocumentProcessingFilter.Filter.OrganizationNumbersContainsAny = new[] { organizationNumber };
|
|
}
|
|
|
|
break;
|
|
}
|
|
catch
|
|
{
|
|
shouldRefresh = false;
|
|
break;
|
|
}
|
|
case OwnershipTypes.AccountNumber:
|
|
Filter.DocumentProcessingFilter.Filter.AccountNumberContainsAny = new [] { Filter.OwnershipValue };
|
|
break;
|
|
case OwnershipTypes.PersonName:
|
|
var request = new PersonNameRequest() { FirstName = Filter.OwnershipValue ?? "", LastName = Filter.AdditionalOwnershipValue ?? "", MdlName = "" };
|
|
const int personLimit = 50;
|
|
|
|
try
|
|
{
|
|
var personCount = await _coreApiWrapperService.GetCountPersonsByNameLike(request);
|
|
|
|
if (personCount > personLimit)
|
|
{
|
|
_toastService.ShowWarning(
|
|
$"There would be {personCount} persons in your search.\nResults have been limited to {personLimit}.\nIf you are able, please search with a more specific name.");
|
|
}
|
|
|
|
var persons = await _coreApiWrapperService.GetPersonsByNameLike(request, personLimit);
|
|
|
|
if (!persons.Any())
|
|
{
|
|
_toastService.ShowWarning("No person(s) were found.");
|
|
shouldRefresh = false;
|
|
}
|
|
|
|
Filter.DocumentProcessingFilter.Filter.PersonNumbersContainsAny =
|
|
persons.Select(x => x.PersonNumber.ToString()).ToArray();
|
|
break;
|
|
}
|
|
catch
|
|
{
|
|
shouldRefresh = false;
|
|
break;
|
|
}
|
|
case OwnershipTypes.OrganizationName:
|
|
//50 is near the query string limit for filtering
|
|
//to raise the limit chunk the request and concatenate the results like getting document audit logs
|
|
const int organizationLimit = 50;
|
|
|
|
try
|
|
{
|
|
var checkLimit = await _coreApiWrapperService.CountOrganizationNumbersByName(Filter.OwnershipValue)
|
|
.ContinueWith(async count =>
|
|
{
|
|
if (count.Result > organizationLimit)
|
|
{
|
|
_toastService.ShowWarning(
|
|
$"There would be {await count} organizations in your search.\nResults have been limited to {organizationLimit}.\nIf you are able, please search with a more specific name.");
|
|
}
|
|
});
|
|
|
|
var organizations = await _coreApiWrapperService.GetOrganizationByOrganizationName(Filter.OwnershipValue, organizationLimit);
|
|
|
|
await checkLimit;
|
|
if (!organizations.Any())
|
|
{
|
|
_toastService.ShowWarning("No organization(s) were found.");
|
|
shouldRefresh = false;
|
|
}
|
|
|
|
Filter.DocumentProcessingFilter.Filter.OrganizationNumbersContainsAny =
|
|
organizations.Select(x => x.OrganizationNumber.ToString()).ToArray();
|
|
|
|
break;
|
|
}
|
|
catch
|
|
{
|
|
shouldRefresh = false;
|
|
break;
|
|
}
|
|
case OwnershipTypes.OrganizationNumber:
|
|
Filter.DocumentProcessingFilter.Filter.OrganizationNumbersContainsAny = new[] { Filter.OwnershipValue };
|
|
break;
|
|
case OwnershipTypes.PersonNumber:
|
|
Filter.DocumentProcessingFilter.Filter.PersonNumbersContainsAny = new[] { Filter.OwnershipValue };
|
|
break;
|
|
default:
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
loading.Close();
|
|
|
|
if(shouldRefresh) await Refresh();
|
|
}
|
|
|
|
public async Task ClearFilterAndSorting()
|
|
{
|
|
Filter.OwnershipType = null;
|
|
Filter.OwnershipValue = null;
|
|
Filter.DocumentProcessingFilter = new DocumentInformationFilteredSearch
|
|
{
|
|
Filter = new DocumentInformationFilter(),
|
|
SortDefinition = new List<SortableField>()
|
|
};
|
|
|
|
await Refresh();
|
|
}
|
|
|
|
public async Task SortFieldsSelected(IList<string> fields)
|
|
{
|
|
Filter.DocumentProcessingFilter.SortDefinition = fields
|
|
.Select((fieldName, position) =>
|
|
{
|
|
var field = Filter.DocumentProcessingFilter.SortDefinition!
|
|
.FirstOrDefault(f => f.Field == fieldName)
|
|
?? new SortableField { Field = fieldName };
|
|
field.Position = position;
|
|
|
|
return field;
|
|
})
|
|
.ToList();
|
|
|
|
await ApplyFilterAndSorting();
|
|
}
|
|
|
|
public async Task SortFieldRemoved(string field)
|
|
{
|
|
foreach (var sortField in Filter.DocumentProcessingFilter.SortDefinition!.Where(f => f.Field == field))
|
|
{
|
|
Filter.DocumentProcessingFilter.SortDefinition!.Remove(sortField);
|
|
}
|
|
|
|
await ApplyFilterAndSorting();
|
|
}
|
|
|
|
public Task SetFieldDescending(string field) => SortField(field, true);
|
|
public Task SetFieldAscending(string field) => SortField(field, false);
|
|
private async Task SortField(string field, bool descending)
|
|
{
|
|
Filter.DocumentProcessingFilter.SortDefinition!.Single(f => f.Field == field).IsDescending = descending;
|
|
|
|
await ApplyFilterAndSorting();
|
|
}
|
|
|
|
public bool IsFieldDescending(string field) => Filter.DocumentProcessingFilter.SortDefinition!.Single(f => f.Field == field).IsDescending;
|
|
|
|
private async Task Download(DocumentMetadataResponse document)
|
|
{
|
|
try
|
|
{
|
|
if (document.DocumentBlobId is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var content = (await _documentService.StreamDocumentContent(document.DocumentBlobId ?? Guid.Empty)).Replace("\"", string.Empty);
|
|
var byteContent = Convert.FromBase64String(content);
|
|
using var contentStream = new DotNetStreamReference
|
|
(
|
|
new MemoryStream(byteContent)
|
|
);
|
|
|
|
await _documentService.ExternalActionPerformed(document.DocumentId, DocumentAction.Download, "Business View");
|
|
await _jsDocument.DownloadDocument($"{FileReader.GetExtensionByBytes(byteContent, document.Name)}", contentStream);
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
public void UpdateAuthorizationLists(DocumentInformation document, EntityTypes selectedEntityType, string dnaEntityNameResult, string dnaEntityIdResult)
|
|
{
|
|
var removed = document.DocumentAccess.FirstOrDefault(x => x.AccessType == AccessType.Removed && x.EntityName.Equals(dnaEntityNameResult));
|
|
if (removed != null)
|
|
{
|
|
document.DocumentAccess.Remove(removed);
|
|
}
|
|
|
|
if (document.EntityName.Equals(dnaEntityNameResult))
|
|
{
|
|
var primaryOwner = document.DocumentAccess.Where(x => x.EntityName.Equals(dnaEntityNameResult)).FirstOrDefault();
|
|
if (primaryOwner != null)
|
|
{
|
|
document.DocumentAccess.Remove(primaryOwner);
|
|
}
|
|
document.DocumentAccess.Add(new DocumentAccess(AccessType.PrimaryOwner, true, dnaEntityNameResult, dnaEntityIdResult));
|
|
}
|
|
else if (selectedEntityType == EntityTypes.Person && document.AccountOwners["persons"].ContainsKey(dnaEntityIdResult) ||
|
|
selectedEntityType == EntityTypes.Organization && document.AccountOwners["organizations"].ContainsKey(dnaEntityIdResult))
|
|
{
|
|
document.DocumentAccess.Add(new DocumentAccess(AccessType.Owner, true, dnaEntityNameResult, dnaEntityIdResult));
|
|
}
|
|
else
|
|
{
|
|
document.DocumentAccess.Add(new DocumentAccess(AccessType.Additional, true, dnaEntityNameResult, dnaEntityIdResult));
|
|
}
|
|
}
|
|
|
|
public void PrepareForPrimaryOwnerDocumentRequest(DocumentInformation document, EntityTypes selectedEntityType, string dnaEntityNameResult, string dnaEntityIdResult)
|
|
{
|
|
List<DocumentAccess> accesses = new List<DocumentAccess>();
|
|
|
|
foreach (var account in document.AccountOwners["persons"])
|
|
{
|
|
if (document.EntityName.Equals(account.Value))
|
|
{
|
|
accesses.Add(new DocumentAccess(AccessType.PrimaryOwner, false, account.Value, account.Key));
|
|
}
|
|
else
|
|
{
|
|
accesses.Add(new DocumentAccess(AccessType.Removed, false, account.Value, account.Key));
|
|
}
|
|
}
|
|
|
|
foreach (var account in document.AccountOwners["organizations"])
|
|
{
|
|
if (document.EntityName.Equals(account.Value))
|
|
{
|
|
accesses.Add(new DocumentAccess(AccessType.PrimaryOwner, false, account.Value, account.Key));
|
|
}
|
|
else
|
|
{
|
|
accesses.Add(new DocumentAccess(AccessType.Removed, false, account.Value, account.Key));
|
|
}
|
|
}
|
|
|
|
document.DocumentAccess.Clear();
|
|
document.PersonNumbers.Clear();
|
|
document.OrganizationNumbers.Clear();
|
|
|
|
if (selectedEntityType == EntityTypes.Person)
|
|
{
|
|
document.PersonNumbers.Add(dnaEntityIdResult);
|
|
}
|
|
else
|
|
{
|
|
document.OrganizationNumbers.Add(dnaEntityIdResult);
|
|
}
|
|
|
|
foreach (var access in accesses)
|
|
{
|
|
document.DocumentAccess.Add(access);
|
|
}
|
|
}
|
|
|
|
public async Task DocumentMetadataUpdate(DocumentInformation document, EntityTypes selectedEntityType, string dnaEntityIdResult)
|
|
=> await _documentTypeUploaderService.DocumentMetadataUpdate(document, selectedEntityType, dnaEntityIdResult);
|
|
|
|
public void RemoveAuthorizationFromDocument(DocumentInformation document, string dnaEntityNameResult, string dnaEntityIdResult)
|
|
{
|
|
var primaryowner = document.DocumentAccess.Where(x => x.AccessType == AccessType.PrimaryOwner && x.EntityName.Equals(dnaEntityNameResult)).FirstOrDefault();
|
|
if (primaryowner != null)
|
|
{
|
|
document.DocumentAccess.Remove(primaryowner);
|
|
document.DocumentAccess.Add(new DocumentAccess(AccessType.PrimaryOwner, false, dnaEntityNameResult, dnaEntityIdResult));
|
|
}
|
|
|
|
var owner = document.DocumentAccess.Where(x => x.AccessType == AccessType.Owner && x.EntityName.Equals(dnaEntityNameResult)).FirstOrDefault();
|
|
if (owner != null)
|
|
{
|
|
document.DocumentAccess.Remove(owner);
|
|
document.DocumentAccess.Add(new DocumentAccess(AccessType.Removed, false, dnaEntityNameResult, dnaEntityIdResult));
|
|
}
|
|
|
|
var additional = document.DocumentAccess.Where(x => x.AccessType == AccessType.Additional && x.EntityName.Equals(dnaEntityNameResult)).FirstOrDefault();
|
|
if (additional != null)
|
|
{
|
|
document.DocumentAccess.Remove(additional);
|
|
}
|
|
}
|
|
|
|
public async Task<Person?> GetPersonByPersonNumber(string DnaEntityIdSearch)
|
|
{
|
|
try
|
|
{
|
|
return (await _entityService.GetPersonByEntityNumber(DnaEntityIdSearch)).FirstOrDefault();
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Log.Error(exception, exception.Message);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public async Task<Organization?> GetOrganizationByOrganizationNumber(string DnaEntityIdSearch)
|
|
{
|
|
try
|
|
{
|
|
return (await _entityService.GetOrganizationByEntityNumber(DnaEntityIdSearch)).FirstOrDefault();
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Log.Error(exception, exception.Message);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static (DateTime CreationDateStart, DateTime CreationDateEnd) DefaultFilterDateRange(DefaultFilters configuration)
|
|
=> (
|
|
DateTime.Now.Date.AddDays(configuration.CreationDateStartOffsetDays),
|
|
DateTime.Now.Date.AddDays(configuration.CreationDateEndOffsetDays).AddDays(1).AddTicks(-1)
|
|
);
|
|
}
|
|
|
|
public static class FileReader
|
|
{
|
|
private static readonly byte[] Bmp = { 66, 77 };
|
|
private static readonly byte[] Doc = { 208, 207, 17, 224, 161, 177, 26, 225 };
|
|
private static readonly byte[] ExeDll = { 77, 90 };
|
|
private static readonly byte[] Gif = { 71, 73, 70, 56 };
|
|
private static readonly byte[] Ico = { 0, 0, 1, 0 };
|
|
private static readonly byte[] Jpg = { 255, 216, 255 };
|
|
private static readonly byte[] Mp3 = { 255, 251, 48 };
|
|
private static readonly byte[] Pdf = { 37, 80, 68, 70, 45, 49, 46 };
|
|
private static readonly byte[] Png = { 137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82 };
|
|
private static readonly byte[] Rar = { 82, 97, 114, 33, 26, 7, 0 };
|
|
private static readonly byte[] Swf = { 70, 87, 83 };
|
|
private static readonly byte[] Tiff = { 73, 73, 42, 0 };
|
|
private static readonly byte[] Ttf = { 0, 1, 0, 0, 0 };
|
|
private static readonly byte[] Avi = { 82, 73, 70, 70 };
|
|
private static readonly byte[] Wma = { 48, 38, 178, 117, 142, 102, 207, 17, 166, 217, 0, 170, 0, 98, 206, 108 };
|
|
private static readonly byte[] DocX = { 80, 75, 3, 4 };
|
|
|
|
public static string GetExtensionByBytes(byte[] file, string fileName)
|
|
{
|
|
if (!string.IsNullOrWhiteSpace(Path.GetExtension(fileName))) return fileName;
|
|
|
|
if (file.Take(2).SequenceEqual(Bmp)) return $"{fileName}.bmp";
|
|
if (file.Take(2).SequenceEqual(ExeDll)) return $"{fileName}.exe";
|
|
if (file.Take(3).SequenceEqual(Jpg)) return $"{fileName}.jpg";
|
|
if (file.Take(3).SequenceEqual(Mp3)) return $"{fileName}.mp3";
|
|
if (file.Take(3).SequenceEqual(Swf)) return $"{fileName}.swf";
|
|
if (file.Take(4).SequenceEqual(Avi)) return $"{fileName}.avi";
|
|
if (file.Take(4).SequenceEqual(DocX)) return $"{fileName}.docx";
|
|
if (file.Take(4).SequenceEqual(Gif)) return $"{fileName}.gif";
|
|
if (file.Take(4).SequenceEqual(Ico)) return $"{fileName}.ico";
|
|
if (file.Take(4).SequenceEqual(Tiff)) return $"{fileName}.tiff";
|
|
if (file.Take(5).SequenceEqual(Ttf)) return $"{fileName}.ttf";
|
|
if (file.Take(7).SequenceEqual(Pdf)) return $"{fileName}.pdf";
|
|
if (file.Take(7).SequenceEqual(Rar)) return $"{fileName}.rar";
|
|
if (file.Take(8).SequenceEqual(Doc)) return $"{fileName}.doc";
|
|
if (file.Take(16).SequenceEqual(Png)) return $"{fileName}.png";
|
|
if (file.Take(16).SequenceEqual(Wma)) return $"{fileName}.wma";
|
|
return fileName;
|
|
}
|
|
}
|