diff --git a/src/api/Areas/Dashboard/Controllers/FileSystemItemController.cs b/src/api/Areas/Dashboard/Controllers/FileSystemItemController.cs index c6307ab4..ca441d0d 100644 --- a/src/api/Areas/Dashboard/Controllers/FileSystemItemController.cs +++ b/src/api/Areas/Dashboard/Controllers/FileSystemItemController.cs @@ -129,7 +129,7 @@ public IActionResult GetForId(string id) [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "File System Item" })] - [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 1200)] + // [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 1200)] public IActionResult FindHistory() { var uri = new Uri(this.Request.GetDisplayUrl()); diff --git a/src/api/Areas/Dashboard/Controllers/OperatingSystemItemController.cs b/src/api/Areas/Dashboard/Controllers/OperatingSystemItemController.cs index f7b185fc..47e57201 100644 --- a/src/api/Areas/Dashboard/Controllers/OperatingSystemItemController.cs +++ b/src/api/Areas/Dashboard/Controllers/OperatingSystemItemController.cs @@ -70,7 +70,7 @@ public OperatingSystemItemController( [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "Operating System Item" })] - [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] + // [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] public IActionResult Find() { var uri = new Uri(this.Request.GetDisplayUrl()); @@ -113,7 +113,7 @@ public IActionResult Find() [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "Operating System Item" })] - [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] + // [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] public IActionResult FindList() { var uri = new Uri(this.Request.GetDisplayUrl()); diff --git a/src/api/Areas/Dashboard/Controllers/OrganizationController.cs b/src/api/Areas/Dashboard/Controllers/OrganizationController.cs index fc09f3c5..5e9e1ba4 100644 --- a/src/api/Areas/Dashboard/Controllers/OrganizationController.cs +++ b/src/api/Areas/Dashboard/Controllers/OrganizationController.cs @@ -67,7 +67,7 @@ public OrganizationController( [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "Organization" })] - [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] + // [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] public IActionResult Find() { var uri = new Uri(this.Request.GetDisplayUrl()); @@ -110,7 +110,7 @@ public IActionResult Find() [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "Organization" })] - [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] + // [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] public IActionResult FindList() { var uri = new Uri(this.Request.GetDisplayUrl()); diff --git a/src/api/Areas/Dashboard/Controllers/ServerItemController.cs b/src/api/Areas/Dashboard/Controllers/ServerItemController.cs index 498d7a1d..5957fb58 100644 --- a/src/api/Areas/Dashboard/Controllers/ServerItemController.cs +++ b/src/api/Areas/Dashboard/Controllers/ServerItemController.cs @@ -74,7 +74,7 @@ public ServerItemController( [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "Server Item" })] - [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] + // [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] public IActionResult Find() { var uri = new Uri(this.Request.GetDisplayUrl()); @@ -117,7 +117,7 @@ public IActionResult Find() [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "Server Item" })] - [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] + // [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] public IActionResult FindList() { var uri = new Uri(this.Request.GetDisplayUrl()); @@ -190,7 +190,7 @@ public IActionResult GetForId(string serviceNowKey, bool includeFileSystemItems [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "Server Item" })] - [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 1200)] + // [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 1200)] public IActionResult FindHistory() { var uri = new Uri(this.Request.GetDisplayUrl()); diff --git a/src/api/Areas/Dashboard/Controllers/TenantController.cs b/src/api/Areas/Dashboard/Controllers/TenantController.cs index c1487650..66a84cae 100644 --- a/src/api/Areas/Dashboard/Controllers/TenantController.cs +++ b/src/api/Areas/Dashboard/Controllers/TenantController.cs @@ -66,7 +66,7 @@ public TenantController( [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "Tenant" })] - [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] + // [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] public IActionResult Find() { var uri = new Uri(this.Request.GetDisplayUrl()); @@ -109,7 +109,7 @@ public IActionResult Find() [Produces(MediaTypeNames.Application.Json)] [ProducesResponseType(typeof(IEnumerable), (int)HttpStatusCode.OK)] [SwaggerOperation(Tags = new[] { "Tenant" })] - [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] + // [ResponseCache(VaryByQueryKeys = new[] { "*" }, Location = ResponseCacheLocation.Client, Duration = 60)] public IActionResult FindList() { var uri = new Uri(this.Request.GetDisplayUrl()); diff --git a/src/data-service/DataService.cs b/src/data-service/DataService.cs index 228e0a03..bcf55868 100644 --- a/src/data-service/DataService.cs +++ b/src/data-service/DataService.cs @@ -339,8 +339,14 @@ private async Task ProcessConfigurationItemsAsync(Models.DataSyncModel option) // Need to update with the latest status. if (_serverItems.TryGetValue(serviceNowKey, out Hsb.ServerItemModel? serverItemHSB)) { - await this.HsbApi.DeleteServerItemAsync(serverItemHSB); - _serverItems.Remove(serverItemHSB.ServiceNowKey); + serverItemHSB.InstallStatus = Int32.Parse(serverItemSN.Data.InstallStatus ?? "0"); + serverItemHSB = await this.HsbApi.UpdateServerItemAsync(serverItemHSB); + if (serverItemHSB == null) + { + this.Logger.LogError("Server Item was not returned from HSB: {id}", serviceNowKey); + throw new InvalidOperationException($"Server Item was not returned from HSB: {serviceNowKey}"); + } + _serverItems[serverItemHSB.ServiceNowKey] = serverItemHSB; } return null; @@ -443,8 +449,8 @@ private async Task ProcessConfigurationItemsAsync(Models.DataSyncModel option) } else { - // Delete the file system as it is no longer installed. - await this.HsbApi.DeleteFileSystemItemAsync(fileSystemItem); + fileSystemItem.InstallStatus = Int32.Parse(fileSystemItemSN.Data.InstallStatus ?? "0"); + await this.HsbApi.UpdateFileSystemItemAsync(fileSystemItem); return null; } } @@ -458,8 +464,8 @@ private async Task ProcessConfigurationItemsAsync(Models.DataSyncModel option) } else { - // Delete the file system as it is no longer required. - await this.HsbApi.DeleteFileSystemItemAsync(fileSystemItem); + fileSystemItem.InstallStatus = 0; + await this.HsbApi.UpdateFileSystemItemAsync(fileSystemItem); return null; } } @@ -512,8 +518,9 @@ private async Task ProcessConfigurationItemsAsync(Models.DataSyncModel option) // Service Now has changed the primary key for some reason. this.Logger.LogDebug("Replacing File System Item: '{old}:{new}'", fileSystemItem.ServiceNowKey, configurationItemSN.Data.Id); - // Delete the current one and replace it with the new one. - await this.HsbApi.DeleteFileSystemItemAsync(fileSystemItem); + // Update the current one and replace it with the new one. + fileSystemItem.InstallStatus = 0; + await this.HsbApi.UpdateFileSystemItemAsync(fileSystemItem); fileSystemItem = await this.HsbApi.AddFileSystemItemAsync(new Hsb.FileSystemItemModel(serverItem.ServiceNowKey, fileSystemItemSN, configurationItemSN)); } else if (fileSystemItem.UpdatedOn.AddHours(this.Options.AllowUpdateAfterXHours).ToUniversalTime() <= DateTime.UtcNow) @@ -862,7 +869,9 @@ private async Task ServerItemCleanupProcessAsync() var serverItemSN = await this.ServiceNowApi.GetTableItemAsync(serverItem.ClassName, serverItem.ServiceNowKey); if (serverItemSN?.Data == null) { - await this.HsbApi.DeleteServerItemAsync(serverItem); + // Service Now did not return the server, we will change the install status to 0. + serverItem.InstallStatus = 0; + await this.HsbApi.UpdateServerItemAsync(serverItem); } else { @@ -888,7 +897,8 @@ private async Task ServerItemCleanupProcessAsync() { if (ex.StatusCode == System.Net.HttpStatusCode.NotFound) { - await this.HsbApi.DeleteServerItemAsync(serverItem); + serverItem.InstallStatus = 0; + await this.HsbApi.UpdateServerItemAsync(serverItem); } this.Logger.LogError(ex, "Failed to fetch server item: {key} - {data}", serverItem.ServiceNowKey, ex.Data["Body"]); } diff --git a/src/libs/dal/Migrations/1.0.3/Down/PostDown/01-FindFileSystemHistoryItemsByMonth.sql b/src/libs/dal/Migrations/1.0.3/Down/PostDown/01-FindFileSystemHistoryItemsByMonth.sql new file mode 100644 index 00000000..9d8a241e --- /dev/null +++ b/src/libs/dal/Migrations/1.0.3/Down/PostDown/01-FindFileSystemHistoryItemsByMonth.sql @@ -0,0 +1,58 @@ +CREATE OR REPLACE FUNCTION "FindFileSystemHistoryItemsByMonth"( + "startDate" TIMESTAMPTZ + , "endDate" TIMESTAMPTZ DEFAULT NULL + , "tenantId" INT DEFAULT NULL + , "organizationId" INT DEFAULT NULL + , "operatingSystemItemId" INT DEFAULT NULL + , "serverServiceNowKey" VARCHAR(200) DEFAULT NULL +) +RETURNS SETOF public."FileSystemHistoryItem" +LANGUAGE plpgsql +AS $$ +BEGIN + RETURN QUERY + SELECT DISTINCT + "Id" + , "ServiceNowKey" + , "RawData" + , "RawDataCI" + , "Name" + , "Label" + , "Category" + , "Subcategory" + , "StorageType" + , "MediaType" + , "VolumeId" + , "ClassName" + , "Capacity" + , "DiskSpace" + , "Size" + , "SizeBytes" + , "UsedSizeBytes" + , "AvailableSpace" + , "FreeSpace" + , "FreeSpaceBytes" + , "CreatedOn" + , "CreatedBy" + , "UpdatedOn" + , "UpdatedBy" + , "Version" + , "ServerItemServiceNowKey" + , "InstallStatus" + FROM ( + SELECT fshi.* + , ROW_NUMBER() OVER (PARTITION BY fshi."ServiceNowKey", EXTRACT(YEAR FROM fshi."CreatedOn"), EXTRACT(MONTH FROM fshi."CreatedOn") ORDER BY fshi."CreatedOn") AS "rn" + FROM public."FileSystemHistoryItem" AS fshi + JOIN public."FileSystemItem" AS fsi ON fshi."ServiceNowKey" = fsi."ServiceNowKey" + JOIN public."ServerItem" AS si ON fsi."ServerItemServiceNowKey" = si."ServiceNowKey" + WHERE fshi."InstallStatus" = 1 + AND fshi."CreatedOn" >= $1 + AND ($2 IS NULL OR fshi."CreatedOn" <= $2) + AND ($3 IS NULL OR si."TenantId" = $3) + AND ($4 IS NULL OR si."OrganizationId" = $4) + AND ($5 IS NULL OR si."OperatingSystemItemId" = $5) + AND ($6 IS NULL OR fshi."ServerItemServiceNowKey" = $6) + ) AS "sub" + WHERE "rn" = 1 + ORDER BY "ServiceNowKey", "CreatedOn"; +END;$$ diff --git a/src/libs/dal/Migrations/1.0.3/Down/PostDown/01-FindFileSystemHistoryItemsByMonthForUser.sql b/src/libs/dal/Migrations/1.0.3/Down/PostDown/01-FindFileSystemHistoryItemsByMonthForUser.sql new file mode 100644 index 00000000..ca7266a7 --- /dev/null +++ b/src/libs/dal/Migrations/1.0.3/Down/PostDown/01-FindFileSystemHistoryItemsByMonthForUser.sql @@ -0,0 +1,61 @@ +CREATE OR REPLACE FUNCTION "FindFileSystemHistoryItemsByMonthForUser"( + "userId" INT + , "startDate" TIMESTAMPTZ + , "endDate" TIMESTAMPTZ DEFAULT NULL + , "tenantId" INT DEFAULT NULL + , "organizationId" INT DEFAULT NULL + , "operatingSystemItemId" INT DEFAULT NULL + , "serverServiceNowKey" VARCHAR(200) DEFAULT NULL +) +RETURNS SETOF public."FileSystemHistoryItem" +LANGUAGE plpgsql +AS $$ +BEGIN + RETURN QUERY + SELECT DISTINCT + "Id" + , "ServiceNowKey" + , "RawData" + , "RawDataCI" + , "Name" + , "Label" + , "Category" + , "Subcategory" + , "StorageType" + , "MediaType" + , "VolumeId" + , "ClassName" + , "Capacity" + , "DiskSpace" + , "Size" + , "SizeBytes" + , "UsedSizeBytes" + , "AvailableSpace" + , "FreeSpace" + , "FreeSpaceBytes" + , "CreatedOn" + , "CreatedBy" + , "UpdatedOn" + , "UpdatedBy" + , "Version" + , "ServerItemServiceNowKey" + , "InstallStatus" + FROM ( + SELECT fshi.* + , ROW_NUMBER() OVER (PARTITION BY fshi."ServiceNowKey", EXTRACT(YEAR FROM fshi."CreatedOn"), EXTRACT(MONTH FROM fshi."CreatedOn") ORDER BY fshi."CreatedOn") AS "rn" + FROM public."FileSystemHistoryItem" AS fshi + JOIN public."FileSystemItem" AS fsi ON fshi."ServiceNowKey" = fsi."ServiceNowKey" + JOIN public."ServerItem" AS si ON fsi."ServerItemServiceNowKey" = si."ServiceNowKey" + WHERE fshi."InstallStatus" = 1 + AND fshi."CreatedOn" >= $2 + AND ($3 IS NULL OR fshi."CreatedOn" <= $3) + AND ($4 IS NULL OR si."TenantId" = $4) + AND ($5 IS NULL OR si."OrganizationId" = $5) + AND ($6 IS NULL OR si."OperatingSystemItemId" = $6) + AND ($7 IS NULL OR fshi."ServerItemServiceNowKey" = $7) + AND (si."TenantId" IN (SELECT "TenantId" FROM public."UserTenant" WHERE "UserId" = $1) + OR si."OrganizationId" IN (SELECT "OrganizationId" FROM public."UserOrganization" WHERE "UserId" = $1)) + ) AS "sub" + WHERE "rn" = 1 + ORDER BY "ServiceNowKey", "CreatedOn"; +END;$$ diff --git a/src/libs/dal/Migrations/1.0.3/Down/PostDown/01-FindServerHistoryItemsByMonth.sql b/src/libs/dal/Migrations/1.0.3/Down/PostDown/01-FindServerHistoryItemsByMonth.sql new file mode 100644 index 00000000..ce62b9fa --- /dev/null +++ b/src/libs/dal/Migrations/1.0.3/Down/PostDown/01-FindServerHistoryItemsByMonth.sql @@ -0,0 +1,57 @@ +CREATE OR REPLACE FUNCTION "FindServerHistoryItemsByMonth"( + "startDate" TIMESTAMPTZ + , "endDate" TIMESTAMPTZ DEFAULT NULL + , "tenantId" INT DEFAULT NULL + , "organizationId" INT DEFAULT NULL + , "operatingSystemItemId" INT DEFAULT NULL + , "serviceNowKey" VARCHAR(200) DEFAULT NULL +) +RETURNS SETOF public."ServerHistoryItem" +LANGUAGE plpgsql +AS $$ +BEGIN + RETURN QUERY + SELECT DISTINCT + "Id" + , "TenantId" + , "OrganizationId" + , "OperatingSystemItemId" + , "ServiceNowKey" + , "HistoryKey" + , "RawData" + , "RawDataCI" + , "ClassName" + , "Name" + , "Category" + , "Subcategory" + , "DnsDomain" + , "Platform" + , "IPAddress" + , "FQDN" + , "DiskSpace" + , "Capacity" + , "AvailableSpace" + , "CreatedOn" + , "CreatedBy" + , "UpdatedOn" + , "UpdatedBy" + , "Version" + , "InstallStatus" + FROM ( + SELECT * + , ROW_NUMBER() OVER (PARTITION BY "ServiceNowKey", EXTRACT(YEAR FROM "CreatedOn"), EXTRACT(MONTH FROM "CreatedOn") ORDER BY "CreatedOn") AS "rn" + FROM public."ServerHistoryItem" + WHERE "InstallStatus" = 1 + AND "CreatedOn" >= $1 + AND ($2 IS NULL OR "CreatedOn" <= $2) + AND ($3 IS NULL OR "TenantId" = $3) + AND ($4 IS NULL OR "OrganizationId" = $4) + AND ($5 IS NULL OR "OperatingSystemItemId" = $5) + AND ($6 IS NULL OR "ServiceNowKey" = $6) + ) AS "sub" + WHERE "rn" = 1 + ORDER BY "ServiceNowKey", "CreatedOn"; +END;$$ + +-- Use by calling +-- select * from public."FindServerHistoryItemsByMonth"('2023-12-01'); diff --git a/src/libs/dal/Migrations/1.0.3/Down/PostDown/01-FindServerHistoryItemsByMonthForUser.sql b/src/libs/dal/Migrations/1.0.3/Down/PostDown/01-FindServerHistoryItemsByMonthForUser.sql new file mode 100644 index 00000000..db292a24 --- /dev/null +++ b/src/libs/dal/Migrations/1.0.3/Down/PostDown/01-FindServerHistoryItemsByMonthForUser.sql @@ -0,0 +1,61 @@ +CREATE OR REPLACE FUNCTION "FindServerHistoryItemsByMonthForUser"( + "userId" INT + , "startDate" TIMESTAMPTZ + , "endDate" TIMESTAMPTZ DEFAULT NULL + , "tenantId" INT DEFAULT NULL + , "organizationId" INT DEFAULT NULL + , "operatingSystemItemId" INT DEFAULT NULL + , "serviceNowKey" VARCHAR(200) DEFAULT NULL +) +RETURNS SETOF public."ServerHistoryItem" +LANGUAGE plpgsql +AS $$ +BEGIN + RETURN QUERY + SELECT DISTINCT + "Id" + , "TenantId" + , "OrganizationId" + , "OperatingSystemItemId" + , "ServiceNowKey" + , "HistoryKey" + , "RawData" + , "RawDataCI" + , "ClassName" + , "Name" + , "Category" + , "Subcategory" + , "DnsDomain" + , "Platform" + , "IPAddress" + , "FQDN" + , "DiskSpace" + , "Capacity" + , "AvailableSpace" + , "CreatedOn" + , "CreatedBy" + , "UpdatedOn" + , "UpdatedBy" + , "Version" + , "InstallStatus" + FROM ( + SELECT shi.* + , ROW_NUMBER() OVER (PARTITION BY shi."ServiceNowKey", EXTRACT(YEAR FROM shi."CreatedOn"), EXTRACT(MONTH FROM shi."CreatedOn") ORDER BY shi."CreatedOn") AS "rn" + FROM public."ServerHistoryItem" shi + JOIN public."ServerItem" si ON shi."ServiceNowKey" = si."ServiceNowKey" + WHERE shi."InstallStatus" = 1 + AND shi."CreatedOn" >= $2 + AND ($3 IS NULL OR shi."CreatedOn" <= $3) + AND ($4 IS NULL OR shi."TenantId" = $4) + AND ($5 IS NULL OR shi."OrganizationId" = $5) + AND ($6 IS NULL OR shi."OperatingSystemItemId" = $6) + AND ($7 IS NULL OR shi."ServiceNowKey" = $7) + AND (si."TenantId" IN (SELECT "TenantId" FROM public."UserTenant" WHERE "UserId" = $1) + OR si."OrganizationId" IN (SELECT "OrganizationId" FROM public."UserOrganization" WHERE "UserId" = $1)) + ) AS "sub" + WHERE "rn" = 1 + ORDER BY "ServiceNowKey", "CreatedOn"; +END;$$ + +-- Use by calling +-- select * from public."FindServerHistoryItemsByMonthForUser"(1, '2023-12-01'); diff --git a/src/libs/dal/Migrations/1.0.3/Up/PostUp/01-FindFileSystemHistoryItemsByMonth.sql b/src/libs/dal/Migrations/1.0.3/Up/PostUp/01-FindFileSystemHistoryItemsByMonth.sql new file mode 100644 index 00000000..e96d99d1 --- /dev/null +++ b/src/libs/dal/Migrations/1.0.3/Up/PostUp/01-FindFileSystemHistoryItemsByMonth.sql @@ -0,0 +1,75 @@ +CREATE OR REPLACE FUNCTION "FindFileSystemHistoryItemsByMonth"( + "startDate" TIMESTAMPTZ + , "endDate" TIMESTAMPTZ DEFAULT NULL + , "tenantId" INT DEFAULT NULL + , "organizationId" INT DEFAULT NULL + , "operatingSystemItemId" INT DEFAULT NULL + , "serverServiceNowKey" VARCHAR(200) DEFAULT NULL +) +RETURNS SETOF public."FileSystemHistoryItem" +LANGUAGE plpgsql +AS $$ +DECLARE + end_date_default TIMESTAMPTZ; + last_month_start TIMESTAMPTZ; +BEGIN + end_date_default := (SELECT COALESCE($2, NOW())); + last_month_start := (SELECT (DATE_TRUNC('month', end_date_default))::TIMESTAMPTZ); + RETURN QUERY + SELECT DISTINCT + "Id" + , "ServiceNowKey" + , "RawData" + , "RawDataCI" + , "Name" + , "Label" + , "Category" + , "Subcategory" + , "StorageType" + , "MediaType" + , "VolumeId" + , "ClassName" + , "Capacity" + , "DiskSpace" + , "Size" + , "SizeBytes" + , "UsedSizeBytes" + , "AvailableSpace" + , "FreeSpace" + , "FreeSpaceBytes" + , "CreatedOn" + , "CreatedBy" + , "UpdatedOn" + , "UpdatedBy" + , "Version" + , "ServerItemServiceNowKey" + , "InstallStatus" + FROM ( + SELECT fshi.* + , ROW_NUMBER() OVER (PARTITION BY fshi."ServiceNowKey", EXTRACT(YEAR FROM fshi."CreatedOn"), EXTRACT(MONTH FROM fshi."CreatedOn") ORDER BY fshi."CreatedOn" DESC) AS "rn" + FROM public."FileSystemHistoryItem" AS fshi + JOIN public."FileSystemItem" AS fsi ON fshi."ServiceNowKey" = fsi."ServiceNowKey" + JOIN public."ServerItem" AS si ON fsi."ServerItemServiceNowKey" = si."ServiceNowKey" + WHERE fshi."CreatedOn" >= $1 + AND fshi."CreatedOn" < last_month_start + AND ($3 IS NULL OR si."TenantId" = $3) + AND ($4 IS NULL OR si."OrganizationId" = $4) + AND ($5 IS NULL OR si."OperatingSystemItemId" = $5) + AND ($6 IS NULL OR fshi."ServerItemServiceNowKey" = $6) + UNION + SELECT fshi.* + , ROW_NUMBER() OVER (PARTITION BY fshi."ServiceNowKey", EXTRACT(YEAR FROM fshi."CreatedOn"), EXTRACT(MONTH FROM fshi."CreatedOn") ORDER BY fshi."CreatedOn" DESC) AS "rn" + FROM public."FileSystemHistoryItem" AS fshi + JOIN public."FileSystemItem" AS fsi ON fshi."ServiceNowKey" = fsi."ServiceNowKey" + JOIN public."ServerItem" AS si ON fsi."ServerItemServiceNowKey" = si."ServiceNowKey" + WHERE fshi."InstallStatus" = 1 + AND fshi."CreatedOn" >= last_month_start + AND ($2 IS NULL OR fshi."CreatedOn" <= $2) + AND ($3 IS NULL OR si."TenantId" = $3) + AND ($4 IS NULL OR si."OrganizationId" = $4) + AND ($5 IS NULL OR si."OperatingSystemItemId" = $5) + AND ($6 IS NULL OR fshi."ServerItemServiceNowKey" = $6) + ) AS "sub" + WHERE "rn" = 1 + ORDER BY "ServiceNowKey", "CreatedOn"; +END;$$ diff --git a/src/libs/dal/Migrations/1.0.3/Up/PostUp/01-FindFileSystemHistoryItemsByMonthForUser.sql b/src/libs/dal/Migrations/1.0.3/Up/PostUp/01-FindFileSystemHistoryItemsByMonthForUser.sql new file mode 100644 index 00000000..be659e51 --- /dev/null +++ b/src/libs/dal/Migrations/1.0.3/Up/PostUp/01-FindFileSystemHistoryItemsByMonthForUser.sql @@ -0,0 +1,80 @@ +CREATE OR REPLACE FUNCTION "FindFileSystemHistoryItemsByMonthForUser"( + "userId" INT + , "startDate" TIMESTAMPTZ + , "endDate" TIMESTAMPTZ DEFAULT NULL + , "tenantId" INT DEFAULT NULL + , "organizationId" INT DEFAULT NULL + , "operatingSystemItemId" INT DEFAULT NULL + , "serverServiceNowKey" VARCHAR(200) DEFAULT NULL +) +RETURNS SETOF public."FileSystemHistoryItem" +LANGUAGE plpgsql +AS $$ +DECLARE + end_date_default TIMESTAMPTZ; + last_month_start TIMESTAMPTZ; +BEGIN + end_date_default := (SELECT COALESCE($3, NOW())); + last_month_start := (SELECT (DATE_TRUNC('month', end_date_default))::TIMESTAMPTZ); + RETURN QUERY + SELECT DISTINCT + "Id" + , "ServiceNowKey" + , "RawData" + , "RawDataCI" + , "Name" + , "Label" + , "Category" + , "Subcategory" + , "StorageType" + , "MediaType" + , "VolumeId" + , "ClassName" + , "Capacity" + , "DiskSpace" + , "Size" + , "SizeBytes" + , "UsedSizeBytes" + , "AvailableSpace" + , "FreeSpace" + , "FreeSpaceBytes" + , "CreatedOn" + , "CreatedBy" + , "UpdatedOn" + , "UpdatedBy" + , "Version" + , "ServerItemServiceNowKey" + , "InstallStatus" + FROM ( + SELECT fshi.* + , ROW_NUMBER() OVER (PARTITION BY fshi."ServiceNowKey", EXTRACT(YEAR FROM fshi."CreatedOn"), EXTRACT(MONTH FROM fshi."CreatedOn") ORDER BY fshi."CreatedOn" DESC) AS "rn" + FROM public."FileSystemHistoryItem" AS fshi + JOIN public."FileSystemItem" AS fsi ON fshi."ServiceNowKey" = fsi."ServiceNowKey" + JOIN public."ServerItem" AS si ON fsi."ServerItemServiceNowKey" = si."ServiceNowKey" + WHERE fshi."CreatedOn" >= $2 + AND fshi."CreatedOn" < last_month_start + AND ($4 IS NULL OR si."TenantId" = $4) + AND ($5 IS NULL OR si."OrganizationId" = $5) + AND ($6 IS NULL OR si."OperatingSystemItemId" = $6) + AND ($7 IS NULL OR fshi."ServerItemServiceNowKey" = $7) + AND (si."TenantId" IN (SELECT "TenantId" FROM public."UserTenant" WHERE "UserId" = $1) + OR si."OrganizationId" IN (SELECT "OrganizationId" FROM public."UserOrganization" WHERE "UserId" = $1)) + UNION + SELECT fshi.* + , ROW_NUMBER() OVER (PARTITION BY fshi."ServiceNowKey", EXTRACT(YEAR FROM fshi."CreatedOn"), EXTRACT(MONTH FROM fshi."CreatedOn") ORDER BY fshi."CreatedOn" DESC) AS "rn" + FROM public."FileSystemHistoryItem" AS fshi + JOIN public."FileSystemItem" AS fsi ON fshi."ServiceNowKey" = fsi."ServiceNowKey" + JOIN public."ServerItem" AS si ON fsi."ServerItemServiceNowKey" = si."ServiceNowKey" + WHERE fshi."InstallStatus" = 1 + AND fshi."CreatedOn" >= last_month_start + AND ($3 IS NULL OR fshi."CreatedOn" <= $3) + AND ($4 IS NULL OR si."TenantId" = $4) + AND ($5 IS NULL OR si."OrganizationId" = $5) + AND ($6 IS NULL OR si."OperatingSystemItemId" = $6) + AND ($7 IS NULL OR fshi."ServerItemServiceNowKey" = $7) + AND (si."TenantId" IN (SELECT "TenantId" FROM public."UserTenant" WHERE "UserId" = $1) + OR si."OrganizationId" IN (SELECT "OrganizationId" FROM public."UserOrganization" WHERE "UserId" = $1)) + ) AS "sub" + WHERE "rn" = 1 + ORDER BY "ServiceNowKey", "CreatedOn"; +END;$$ diff --git a/src/libs/dal/Migrations/1.0.3/Up/PostUp/01-FindServerHistoryItemsByMonth.sql b/src/libs/dal/Migrations/1.0.3/Up/PostUp/01-FindServerHistoryItemsByMonth.sql new file mode 100644 index 00000000..80d7f09d --- /dev/null +++ b/src/libs/dal/Migrations/1.0.3/Up/PostUp/01-FindServerHistoryItemsByMonth.sql @@ -0,0 +1,72 @@ +CREATE OR REPLACE FUNCTION "FindServerHistoryItemsByMonth"( + "startDate" TIMESTAMPTZ + , "endDate" TIMESTAMPTZ DEFAULT NULL + , "tenantId" INT DEFAULT NULL + , "organizationId" INT DEFAULT NULL + , "operatingSystemItemId" INT DEFAULT NULL + , "serviceNowKey" VARCHAR(200) DEFAULT NULL +) +RETURNS SETOF public."ServerHistoryItem" +LANGUAGE plpgsql +AS $$ +DECLARE + end_date_default TIMESTAMPTZ; + last_month_start TIMESTAMPTZ; +BEGIN + end_date_default := (SELECT COALESCE($2, NOW())); + last_month_start := (SELECT (DATE_TRUNC('month', end_date_default))::TIMESTAMPTZ); + RETURN QUERY + SELECT DISTINCT + "Id" + , "TenantId" + , "OrganizationId" + , "OperatingSystemItemId" + , "ServiceNowKey" + , "HistoryKey" + , "RawData" + , "RawDataCI" + , "ClassName" + , "Name" + , "Category" + , "Subcategory" + , "DnsDomain" + , "Platform" + , "IPAddress" + , "FQDN" + , "DiskSpace" + , "Capacity" + , "AvailableSpace" + , "CreatedOn" + , "CreatedBy" + , "UpdatedOn" + , "UpdatedBy" + , "Version" + , "InstallStatus" + FROM ( + SELECT * + , ROW_NUMBER() OVER (PARTITION BY "ServiceNowKey", EXTRACT(YEAR FROM "CreatedOn"), EXTRACT(MONTH FROM "CreatedOn") ORDER BY "CreatedOn" DESC) AS "rn" + FROM public."ServerHistoryItem" + WHERE "CreatedOn" >= $1 + AND "CreatedOn" < last_month_start + AND ($3 IS NULL OR "TenantId" = $3) + AND ($4 IS NULL OR "OrganizationId" = $4) + AND ($5 IS NULL OR "OperatingSystemItemId" = $5) + AND ($6 IS NULL OR "ServiceNowKey" = $6) + UNION + SELECT * + , ROW_NUMBER() OVER (PARTITION BY "ServiceNowKey", EXTRACT(YEAR FROM "CreatedOn"), EXTRACT(MONTH FROM "CreatedOn") ORDER BY "CreatedOn" DESC) AS "rn" + FROM public."ServerHistoryItem" + WHERE "InstallStatus" = 1 + AND "CreatedOn" >= last_month_start + AND ($2 IS NULL OR "CreatedOn" <= $2) + AND ($3 IS NULL OR "TenantId" = $3) + AND ($4 IS NULL OR "OrganizationId" = $4) + AND ($5 IS NULL OR "OperatingSystemItemId" = $5) + AND ($6 IS NULL OR "ServiceNowKey" = $6) + ) AS "sub" + WHERE "rn" = 1 + ORDER BY "ServiceNowKey", "CreatedOn"; +END;$$ + +-- Use by calling +-- select * from public."FindServerHistoryItemsByMonth"('2023-12-01'); diff --git a/src/libs/dal/Migrations/1.0.3/Up/PostUp/01-FindServerHistoryItemsByMonthForUser.sql b/src/libs/dal/Migrations/1.0.3/Up/PostUp/01-FindServerHistoryItemsByMonthForUser.sql new file mode 100644 index 00000000..9b31eb65 --- /dev/null +++ b/src/libs/dal/Migrations/1.0.3/Up/PostUp/01-FindServerHistoryItemsByMonthForUser.sql @@ -0,0 +1,79 @@ +CREATE OR REPLACE FUNCTION "FindServerHistoryItemsByMonthForUser"( + "userId" INT + , "startDate" TIMESTAMPTZ + , "endDate" TIMESTAMPTZ DEFAULT NULL + , "tenantId" INT DEFAULT NULL + , "organizationId" INT DEFAULT NULL + , "operatingSystemItemId" INT DEFAULT NULL + , "serviceNowKey" VARCHAR(200) DEFAULT NULL +) +RETURNS SETOF public."ServerHistoryItem" +LANGUAGE plpgsql +AS $$ +DECLARE + end_date_default TIMESTAMPTZ; + last_month_start TIMESTAMPTZ; +BEGIN + end_date_default := (SELECT COALESCE($3, NOW())); + last_month_start := (SELECT (DATE_TRUNC('month', end_date_default))::TIMESTAMPTZ); + RETURN QUERY + SELECT DISTINCT + "Id" + , "TenantId" + , "OrganizationId" + , "OperatingSystemItemId" + , "ServiceNowKey" + , "HistoryKey" + , "RawData" + , "RawDataCI" + , "ClassName" + , "Name" + , "Category" + , "Subcategory" + , "DnsDomain" + , "Platform" + , "IPAddress" + , "FQDN" + , "DiskSpace" + , "Capacity" + , "AvailableSpace" + , "CreatedOn" + , "CreatedBy" + , "UpdatedOn" + , "UpdatedBy" + , "Version" + , "InstallStatus" + FROM ( + SELECT shi.* + , ROW_NUMBER() OVER (PARTITION BY shi."ServiceNowKey", EXTRACT(YEAR FROM shi."CreatedOn"), EXTRACT(MONTH FROM shi."CreatedOn") ORDER BY shi."CreatedOn" DESC) AS "rn" + FROM public."ServerHistoryItem" shi + JOIN public."ServerItem" si ON shi."ServiceNowKey" = si."ServiceNowKey" + WHERE shi."CreatedOn" >= $2 + AND shi."CreatedOn" < last_month_start + AND ($4 IS NULL OR shi."TenantId" = $4) + AND ($5 IS NULL OR shi."OrganizationId" = $5) + AND ($6 IS NULL OR shi."OperatingSystemItemId" = $6) + AND ($7 IS NULL OR shi."ServiceNowKey" = $7) + AND (si."TenantId" IN (SELECT "TenantId" FROM public."UserTenant" WHERE "UserId" = $1) + OR si."OrganizationId" IN (SELECT "OrganizationId" FROM public."UserOrganization" WHERE "UserId" = $1)) + UNION + SELECT shi.* + , ROW_NUMBER() OVER (PARTITION BY shi."ServiceNowKey", EXTRACT(YEAR FROM shi."CreatedOn"), EXTRACT(MONTH FROM shi."CreatedOn") ORDER BY shi."CreatedOn" DESC) AS "rn" + FROM public."ServerHistoryItem" shi + JOIN public."ServerItem" si ON shi."ServiceNowKey" = si."ServiceNowKey" + WHERE shi."InstallStatus" = 1 + AND shi."CreatedOn" >= last_month_start + AND ($3 IS NULL OR shi."CreatedOn" <= $3) + AND ($4 IS NULL OR shi."TenantId" = $4) + AND ($5 IS NULL OR shi."OrganizationId" = $5) + AND ($6 IS NULL OR shi."OperatingSystemItemId" = $6) + AND ($7 IS NULL OR shi."ServiceNowKey" = $7) + AND (si."TenantId" IN (SELECT "TenantId" FROM public."UserTenant" WHERE "UserId" = $1) + OR si."OrganizationId" IN (SELECT "OrganizationId" FROM public."UserOrganization" WHERE "UserId" = $1)) + ) AS "sub" + WHERE "rn" = 1 + ORDER BY "ServiceNowKey", "CreatedOn"; +END;$$ + +-- Use by calling +-- select * from public."FindServerHistoryItemsByMonthForUser"(1, '2023-12-01'); diff --git a/src/libs/dal/Migrations/20240327151737_1.0.3.Designer.cs b/src/libs/dal/Migrations/20240327151737_1.0.3.Designer.cs new file mode 100644 index 00000000..b3d2bec3 --- /dev/null +++ b/src/libs/dal/Migrations/20240327151737_1.0.3.Designer.cs @@ -0,0 +1,1617 @@ +// +using System; +using System.Text.Json; +using HSB.DAL; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace HSB.DAL.Migrations +{ + [DbContext(typeof(HSBContext))] + [Migration("20240327151737_1.0.3")] + partial class _103 + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.14") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("HSB.Entities.DataSync", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Offset") + .HasColumnType("integer"); + + b.Property("Query") + .IsRequired() + .HasColumnType("text"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "IsEnabled" }, "IX_DataSync"); + + b.HasIndex(new[] { "Name" }, "IX_DataSync_Name") + .IsUnique(); + + b.ToTable("DataSync", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.FileSystemHistoryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvailableSpace") + .HasColumnType("integer"); + + b.Property("Capacity") + .HasColumnType("integer"); + + b.Property("Category") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("ClassName") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("DiskSpace") + .HasColumnType("real"); + + b.Property("FreeSpace") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasDefaultValueSql("''"); + + b.Property("FreeSpaceBytes") + .HasColumnType("bigint"); + + b.Property("InstallStatus") + .HasColumnType("integer"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("MediaType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RawData") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("jsonb") + .HasDefaultValueSql("'{}'::jsonb"); + + b.Property("RawDataCI") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("jsonb") + .HasDefaultValueSql("'{}'::jsonb"); + + b.Property("ServerItemServiceNowKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ServiceNowKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Size") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasDefaultValueSql("''"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("StorageType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("Subcategory") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("UsedSizeBytes") + .HasColumnType("bigint"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.Property("VolumeId") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.HasKey("Id"); + + b.HasIndex("ServiceNowKey"); + + b.HasIndex(new[] { "CreatedOn" }, "IX_FileSystemHistoryItem_CreatedOn"); + + b.HasIndex(new[] { "InstallStatus", "ServiceNowKey", "ServerItemServiceNowKey" }, "IX_FileSystemHistoryItem_InstallStatus_ServiceNowKey_ServerItemServiceNowKey"); + + b.ToTable("FileSystemHistoryItem", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.FileSystemItem", b => + { + b.Property("ServiceNowKey") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("AvailableSpace") + .HasColumnType("integer"); + + b.Property("Capacity") + .HasColumnType("integer"); + + b.Property("Category") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("ClassName") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("DiskSpace") + .HasColumnType("real"); + + b.Property("FreeSpace") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasDefaultValueSql("''"); + + b.Property("FreeSpaceBytes") + .HasColumnType("bigint"); + + b.Property("InstallStatus") + .HasColumnType("integer"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("MediaType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RawData") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("jsonb") + .HasDefaultValueSql("'{}'::jsonb"); + + b.Property("RawDataCI") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("jsonb") + .HasDefaultValueSql("'{}'::jsonb"); + + b.Property("ServerItemServiceNowKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Size") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasDefaultValueSql("''"); + + b.Property("SizeBytes") + .HasColumnType("bigint"); + + b.Property("StorageType") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("Subcategory") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("UsedSizeBytes") + .HasColumnType("bigint"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.Property("VolumeId") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.HasKey("ServiceNowKey"); + + b.HasIndex("ServerItemServiceNowKey"); + + b.HasIndex(new[] { "InstallStatus", "ServerItemServiceNowKey" }, "IX_FileSystemItem_InstallStatus_ServerItemServiceNowKey"); + + b.ToTable("FileSystemItem", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.Group", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("Key") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("uuid_generate_v1()"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "IsEnabled" }, "IX_group"); + + b.HasIndex(new[] { "Key" }, "IX_group_key") + .IsUnique(); + + b.HasIndex(new[] { "Name" }, "IX_group_name") + .IsUnique(); + + b.ToTable("Group", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.GroupRole", b => + { + b.Property("GroupId") + .HasColumnType("integer"); + + b.Property("RoleId") + .HasColumnType("integer"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("GroupId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("GroupRole", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.OperatingSystemItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RawData") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("jsonb") + .HasDefaultValueSql("'{}'::jsonb"); + + b.Property("ServiceNowKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "Name" }, "IX_OperatingSystemItem_Name"); + + b.HasIndex(new[] { "ServiceNowKey" }, "IX_OperatingSystemItem_ServiceNowKey") + .IsUnique(); + + b.ToTable("OperatingSystemItem", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.Organization", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ParentId") + .HasColumnType("integer"); + + b.Property("RawData") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("jsonb") + .HasDefaultValueSql("'{}'::jsonb"); + + b.Property("ServiceNowKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("Id"); + + b.HasIndex("ParentId"); + + b.HasIndex(new[] { "Code" }, "IX_Organization_Code") + .IsUnique(); + + b.HasIndex(new[] { "Name" }, "IX_Organization_Name") + .IsUnique(); + + b.HasIndex(new[] { "ServiceNowKey" }, "IX_Organization_ServiceNowKey") + .IsUnique(); + + b.ToTable("Organization", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.Role", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("Key") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasDefaultValueSql("uuid_generate_v1()"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "IsEnabled" }, "IX_role"); + + b.HasIndex(new[] { "Key" }, "IX_role_key") + .IsUnique(); + + b.HasIndex(new[] { "Name" }, "IX_role_name") + .IsUnique(); + + b.ToTable("Role", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.ServerHistoryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvailableSpace") + .HasColumnType("real"); + + b.Property("Capacity") + .HasColumnType("real"); + + b.Property("Category") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("ClassName") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("DiskSpace") + .HasColumnType("real"); + + b.Property("DnsDomain") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("FQDN") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("HistoryKey") + .HasColumnType("uuid"); + + b.Property("IPAddress") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasDefaultValueSql("''"); + + b.Property("InstallStatus") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OperatingSystemItemId") + .HasColumnType("integer"); + + b.Property("OrganizationId") + .HasColumnType("integer"); + + b.Property("Platform") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("RawData") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("jsonb") + .HasDefaultValueSql("'{}'::jsonb"); + + b.Property("RawDataCI") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("jsonb") + .HasDefaultValueSql("'{}'::jsonb"); + + b.Property("ServiceNowKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Subcategory") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("TenantId") + .HasColumnType("integer"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("Id"); + + b.HasIndex("OperatingSystemItemId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("ServiceNowKey"); + + b.HasIndex("TenantId"); + + b.HasIndex(new[] { "CreatedOn" }, "IX_ServerHistoryItem_CreatedOn"); + + b.HasIndex(new[] { "HistoryKey" }, "IX_ServerHistoryItem_HistoryKey"); + + b.HasIndex(new[] { "InstallStatus", "ServiceNowKey" }, "IX_ServerHistoryItem_InstallStatus_ServiceNowKey"); + + b.ToTable("ServerHistoryItem", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.ServerItem", b => + { + b.Property("ServiceNowKey") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("AvailableSpace") + .HasColumnType("real"); + + b.Property("Capacity") + .HasColumnType("real"); + + b.Property("Category") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("ClassName") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("DiskSpace") + .HasColumnType("real"); + + b.Property("DnsDomain") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("FQDN") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("HistoryKey") + .HasColumnType("uuid"); + + b.Property("IPAddress") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasDefaultValueSql("''"); + + b.Property("InstallStatus") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("OperatingSystemItemId") + .HasColumnType("integer"); + + b.Property("OrganizationId") + .HasColumnType("integer"); + + b.Property("Platform") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("RawData") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("jsonb") + .HasDefaultValueSql("'{}'::jsonb"); + + b.Property("RawDataCI") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("jsonb") + .HasDefaultValueSql("'{}'::jsonb"); + + b.Property("Subcategory") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasDefaultValueSql("''"); + + b.Property("TenantId") + .HasColumnType("integer"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("ServiceNowKey"); + + b.HasIndex("OperatingSystemItemId"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("TenantId"); + + b.HasIndex(new[] { "InstallStatus", "UpdatedOn" }, "IX_ServerItem_InstallStatus_UpdatedOn"); + + b.ToTable("ServerItem", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.Tenant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Code") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RawData") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("jsonb") + .HasDefaultValueSql("'{}'::jsonb"); + + b.Property("ServiceNowKey") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SortOrder") + .HasColumnType("integer"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("Id"); + + b.HasIndex(new[] { "Code" }, "IX_Tenant_Code") + .IsUnique(); + + b.HasIndex(new[] { "Name" }, "IX_Tenant_Name") + .IsUnique(); + + b.HasIndex(new[] { "ServiceNowKey" }, "IX_Tenant_ServiceNowKey") + .IsUnique(); + + b.ToTable("Tenant", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.TenantOrganization", b => + { + b.Property("TenantId") + .HasColumnType("integer"); + + b.Property("OrganizationId") + .HasColumnType("integer"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("TenantId", "OrganizationId"); + + b.HasIndex("OrganizationId"); + + b.ToTable("TenantOrganization", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("DisplayName") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasDefaultValueSql("''"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("EmailVerified") + .HasColumnType("boolean"); + + b.Property("EmailVerifiedOn") + .HasColumnType("timestamp with time zone"); + + b.Property("FirstName") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasDefaultValueSql("''"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("Key") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValueSql("uuid_generate_v1()"); + + b.Property("LastLoginOn") + .HasColumnType("timestamp with time zone"); + + b.Property("LastName") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasDefaultValueSql("''"); + + b.Property("MiddleName") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasDefaultValueSql("''"); + + b.Property("Note") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValueSql("''"); + + b.Property("Phone") + .IsRequired() + .ValueGeneratedOnAdd() + .HasMaxLength(15) + .HasColumnType("character varying(15)") + .HasDefaultValueSql("''"); + + b.Property("Preferences") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("jsonb") + .HasDefaultValueSql("'{}'::jsonb"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("Id"); + + b.HasIndex("Email", "Phone", "LastName", "FirstName"); + + b.HasIndex(new[] { "DisplayName" }, "IX_user_display_name") + .IsUnique(); + + b.HasIndex(new[] { "Key" }, "IX_user_key") + .IsUnique(); + + b.HasIndex(new[] { "Username" }, "IX_user_username") + .IsUnique(); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.UserGroup", b => + { + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("GroupId") + .HasColumnType("integer"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("UserId", "GroupId"); + + b.HasIndex("GroupId"); + + b.ToTable("UserGroup", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.UserOrganization", b => + { + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("OrganizationId") + .HasColumnType("integer"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("UserId", "OrganizationId"); + + b.HasIndex("OrganizationId"); + + b.ToTable("UserOrganization", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.UserTenant", b => + { + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("integer"); + + b.Property("CreatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("CreatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("UpdatedBy") + .IsRequired() + .HasMaxLength(250) + .HasColumnType("character varying(250)"); + + b.Property("UpdatedOn") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp with time zone") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValueSql("0"); + + b.HasKey("UserId", "TenantId"); + + b.HasIndex("TenantId"); + + b.ToTable("UserTenant", (string)null); + }); + + modelBuilder.Entity("HSB.Entities.FileSystemHistoryItem", b => + { + b.HasOne("HSB.Entities.FileSystemItem", "FileSystemItem") + .WithMany("History") + .HasForeignKey("ServiceNowKey") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FileSystemItem"); + }); + + modelBuilder.Entity("HSB.Entities.FileSystemItem", b => + { + b.HasOne("HSB.Entities.ServerItem", "ServerItem") + .WithMany("FileSystemItems") + .HasForeignKey("ServerItemServiceNowKey") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ServerItem"); + }); + + modelBuilder.Entity("HSB.Entities.GroupRole", b => + { + b.HasOne("HSB.Entities.Group", "Group") + .WithMany("RolesManyToMany") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HSB.Entities.Role", "Role") + .WithMany("GroupsManyToMany") + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Group"); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("HSB.Entities.Organization", b => + { + b.HasOne("HSB.Entities.Organization", "Parent") + .WithMany("Children") + .HasForeignKey("ParentId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Parent"); + }); + + modelBuilder.Entity("HSB.Entities.ServerHistoryItem", b => + { + b.HasOne("HSB.Entities.OperatingSystemItem", "OperatingSystemItem") + .WithMany() + .HasForeignKey("OperatingSystemItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("HSB.Entities.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HSB.Entities.ServerItem", "ServerItem") + .WithMany("History") + .HasForeignKey("ServiceNowKey") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HSB.Entities.Tenant", "Tenant") + .WithMany() + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("OperatingSystemItem"); + + b.Navigation("Organization"); + + b.Navigation("ServerItem"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("HSB.Entities.ServerItem", b => + { + b.HasOne("HSB.Entities.OperatingSystemItem", "OperatingSystemItem") + .WithMany("ServerItems") + .HasForeignKey("OperatingSystemItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("HSB.Entities.Organization", "Organization") + .WithMany("ServerItems") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HSB.Entities.Tenant", "Tenant") + .WithMany("ServerItems") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("OperatingSystemItem"); + + b.Navigation("Organization"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("HSB.Entities.TenantOrganization", b => + { + b.HasOne("HSB.Entities.Organization", "Organization") + .WithMany("TenantsManyToMany") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HSB.Entities.Tenant", "Tenant") + .WithMany("OrganizationsManyToMany") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("Tenant"); + }); + + modelBuilder.Entity("HSB.Entities.UserGroup", b => + { + b.HasOne("HSB.Entities.Group", "Group") + .WithMany("UsersManyToMany") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HSB.Entities.User", "User") + .WithMany("GroupsManyToMany") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Group"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("HSB.Entities.UserOrganization", b => + { + b.HasOne("HSB.Entities.Organization", "Organization") + .WithMany("UsersManyToMany") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HSB.Entities.User", "User") + .WithMany("OrganizationsManyToMany") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("HSB.Entities.UserTenant", b => + { + b.HasOne("HSB.Entities.Tenant", "Tenant") + .WithMany("UsersManyToMany") + .HasForeignKey("TenantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HSB.Entities.User", "User") + .WithMany("TenantsManyToMany") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Tenant"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("HSB.Entities.FileSystemItem", b => + { + b.Navigation("History"); + }); + + modelBuilder.Entity("HSB.Entities.Group", b => + { + b.Navigation("RolesManyToMany"); + + b.Navigation("UsersManyToMany"); + }); + + modelBuilder.Entity("HSB.Entities.OperatingSystemItem", b => + { + b.Navigation("ServerItems"); + }); + + modelBuilder.Entity("HSB.Entities.Organization", b => + { + b.Navigation("Children"); + + b.Navigation("ServerItems"); + + b.Navigation("TenantsManyToMany"); + + b.Navigation("UsersManyToMany"); + }); + + modelBuilder.Entity("HSB.Entities.Role", b => + { + b.Navigation("GroupsManyToMany"); + }); + + modelBuilder.Entity("HSB.Entities.ServerItem", b => + { + b.Navigation("FileSystemItems"); + + b.Navigation("History"); + }); + + modelBuilder.Entity("HSB.Entities.Tenant", b => + { + b.Navigation("OrganizationsManyToMany"); + + b.Navigation("ServerItems"); + + b.Navigation("UsersManyToMany"); + }); + + modelBuilder.Entity("HSB.Entities.User", b => + { + b.Navigation("GroupsManyToMany"); + + b.Navigation("OrganizationsManyToMany"); + + b.Navigation("TenantsManyToMany"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/libs/dal/Migrations/20240327151737_1.0.3.cs b/src/libs/dal/Migrations/20240327151737_1.0.3.cs new file mode 100644 index 00000000..261598d0 --- /dev/null +++ b/src/libs/dal/Migrations/20240327151737_1.0.3.cs @@ -0,0 +1,27 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using HSB.DAL; + +#nullable disable + +namespace HSB.DAL.Migrations +{ + /// + public partial class _103 : PostgresSeedMigration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + PreUp(migrationBuilder); + + PostUp(migrationBuilder); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + PreDown(migrationBuilder); + + PostDown(migrationBuilder); + } + } +} diff --git a/src/libs/dal/Services/FileSystemItemService.cs b/src/libs/dal/Services/FileSystemItemService.cs index c4d15410..4fcc4ac2 100644 --- a/src/libs/dal/Services/FileSystemItemService.cs +++ b/src/libs/dal/Services/FileSystemItemService.cs @@ -23,6 +23,7 @@ public IEnumerable Find(FileSystemItemFilter filter) var query = (from fsi in this.Context.FileSystemItems join si in this.Context.ServerItems on fsi.ServerItemServiceNowKey equals si.ServiceNowKey select fsi) + .Where(fsi => fsi.InstallStatus == 1) .Where(filter.GeneratePredicate()) .Distinct(); @@ -58,6 +59,7 @@ join t in this.Context.Tenants on ut.TenantId equals t.Id join si in this.Context.ServerItems on fsi.ServerItemServiceNowKey equals si.ServiceNowKey where userTenants.Contains(si.TenantId!.Value) || userOrganizationQuery.Contains(si.OrganizationId) select fsi) + .Where(fsi => fsi.InstallStatus == 1) .Where(filter.GeneratePredicate()) .Distinct(); diff --git a/src/libs/dal/Services/ServerItemService.cs b/src/libs/dal/Services/ServerItemService.cs index 02b9093b..03016d92 100644 --- a/src/libs/dal/Services/ServerItemService.cs +++ b/src/libs/dal/Services/ServerItemService.cs @@ -31,6 +31,7 @@ public IEnumerable Find(ServerItemFilter filter, bool includeRelated .Include(si => si.OperatingSystemItem); query = query + .Where(si => si.InstallStatus == 1) .Where(filter.GeneratePredicate()) .Distinct(); @@ -63,6 +64,7 @@ join t in this.Context.Tenants on ut.TenantId equals t.Id var query = (from si in this.Context.ServerItems where si.TenantId != null + && si.InstallStatus == 1 && (userTenants.Contains(si.TenantId!.Value) || userOrganizationQuery.Contains(si.OrganizationId)) select si); @@ -93,6 +95,7 @@ join t in this.Context.Tenants on ut.TenantId equals t.Id public IEnumerable FindList(ServerItemFilter filter) { var query = this.Context.ServerItems + .Where(si => si.InstallStatus == 1) .Where(filter.GeneratePredicate()) .Distinct(); @@ -126,6 +129,7 @@ join t in this.Context.Tenants on ut.TenantId equals t.Id var query = (from si in this.Context.ServerItems where si.TenantId != null + && si.InstallStatus == 1 && (userTenants.Contains(si.TenantId!.Value) || userOrganizationQuery.Contains(si.OrganizationId)) select si) .Where(filter.GeneratePredicate()) @@ -213,7 +217,7 @@ public EntityEntry Update(ServerItem entity, bool updateTotals) if (updateTotals) { // Grab all file system items for this server so that space can be calculated. - var volumes = this.Context.FileSystemItems.AsNoTracking().Where(fsi => fsi.ServerItemServiceNowKey == entity.ServiceNowKey).ToArray(); + var volumes = this.Context.FileSystemItems.AsNoTracking().Where(fsi => fsi.ServerItemServiceNowKey == entity.ServiceNowKey && fsi.InstallStatus == 1).ToArray(); entity.Capacity = volumes.Sum(v => v.SizeBytes); entity.AvailableSpace = volumes.Sum(v => v.FreeSpaceBytes); this.Context.Entry(entity).State = EntityState.Modified; @@ -230,7 +234,8 @@ public EntityEntry Update(ServerItem entity, bool updateTotals) // Move original to history if created more than 12 hours ago. var original = this.Context.ServerItems.AsNoTracking().FirstOrDefault(si => si.ServiceNowKey == entity.ServiceNowKey); - if (original != null && original.CreatedOn.ToUniversalTime().AddHours(12) <= DateTimeOffset.UtcNow.ToUniversalTime()) + var currentHistory = this.Context.ServerHistoryItems.AsNoTracking().FirstOrDefault(shi => shi.HistoryKey == entity.HistoryKey); + if (original != null && (currentHistory == null || original.CreatedOn.ToUniversalTime().AddHours(12) <= DateTimeOffset.UtcNow.ToUniversalTime())) { // This key provides a way to link the current server item record with the one in history. var key = Guid.NewGuid();