diff --git a/apps/dh/api-dh/source/DataHub.WebApi.Tests/Snapshots/SchemaTests.ChangeTest.verified.graphql b/apps/dh/api-dh/source/DataHub.WebApi.Tests/Snapshots/SchemaTests.ChangeTest.verified.graphql index 8007e19eb7..8f9031c103 100644 --- a/apps/dh/api-dh/source/DataHub.WebApi.Tests/Snapshots/SchemaTests.ChangeTest.verified.graphql +++ b/apps/dh/api-dh/source/DataHub.WebApi.Tests/Snapshots/SchemaTests.ChangeTest.verified.graphql @@ -111,6 +111,36 @@ type ApiErrorDescriptor { args: JSON! } +type ArchivedMessage { + sender: Actor + receiver: Actor + documentType: DocumentType! + documentUrl: String + businessTransaction: BusinessTransaction! + id: String! + messageId: String + createdAt: DateTime! + businessReason: String +} + +"A connection to a list of items." +type ArchivedMessagesConnection { + "Information to aid in pagination." + pageInfo: PageInfo! + "A list of edges." + edges: [ArchivedMessagesEdge!] + "A flattened list of the nodes." + nodes: [ArchivedMessage!] +} + +"An edge in a connection." +type ArchivedMessagesEdge { + "A cursor for use in pagination." + cursor: String! + "The item at the end of the edge." + node: ArchivedMessage! +} + type AssociatedActors { email: String! actors: [UUID!]! @@ -274,25 +304,30 @@ type GetUserProfileResponse { type GridAreaDto { priceAreaCode: PriceAreaCode! displayName: String! + status: GridAreaStatus! includedInCalculation: Boolean! id: UUID! code: String! name: String! + type: GridAreaType! validFrom: DateTime! validTo: DateTime } type GridAreaOverviewItemDto { + priceAreaCode: PriceAreaCode! + displayName: String! + status: GridAreaStatus! id: UUID! code: String! name: String! - priceAreaCode: String! validFrom: DateTime! validTo: DateTime actorNumber: String actorName: String organizationName: String fullFlexDate: DateTime + type: GridAreaType! } "Imbalance price" @@ -492,6 +527,7 @@ type Query { gridAreas: [GridAreaDto!]! imbalancePricesOverview: ImbalancePricesOverview! imbalancePricesForMonth(year: Int! month: Int! areaCode: PriceAreaCode!): [ImbalancePriceDaily!]! + archivedMessages(created: DateRange! messageId: String senderNumber: String receiverNumber: String documentTypes: [DocumentType!] businessReasons: [BusinessReason!] filter: String "Returns the first _n_ elements from the list." first: Int "Returns the elements in the list that come after the specified cursor." after: String "Returns the last _n_ elements from the list." last: Int "Returns the elements in the list that come before the specified cursor." before: String order: [ArchivedMessageSortInput!]): ArchivedMessagesConnection organizationAuditLogs(organizationId: UUID!): [OrganizationAuditedChangeAuditLogDto!]! organizationById(id: UUID!): Organization! organizations: [Organization!]! @@ -733,6 +769,14 @@ input AddressDtoInput { country: String! } +input ArchivedMessageSortInput { + messageId: SortEnumType + documentType: SortEnumType + sender: SortEnumType + receiver: SortEnumType + createdAt: SortEnumType +} + input CalculationQueryInput { gridAreaCodes: [String!] states: [CalculationOrchestrationState!] @@ -884,6 +928,8 @@ input RequestSettlementReportInput { useApi: Boolean! energySupplier: String csvLanguage: String + requestAsActorId: String + requestAsMarketRole: SettlementReportMarketRole } input ResetTwoFactorAuthenticationInput { @@ -1025,6 +1071,102 @@ enum BalanceResponsibleSortProperty { RECEIVED_DATE } +enum BusinessReason { + D02 + D03 + D04 + D05 + D06 + D07 + D09 + D10 + D11 + D12 + D13 + D14 + D15 + D16 + D17 + D18 + D19 + D20 + D21 + D22 + D23 + D24 + D25 + D26 + D27 + D28 + D29 + D30 + D31 + D32 + D33 + D34 + D35 + D36 + D37 + D38 + D39 + D40 + D41 + D43 + D44 + D45 + D46 + D47 + E01 + E02 + E03 + E05 + E06 + E0G + E20 + E23 + E30 + E32 + E34 + E53 + E56 + E65 + E66 + E67 + E75 + E79 + E80 + E84 +} + +enum BusinessTransaction { + RSM001 + RSM003 + RSM004 + RSM005 + RSM006 + RSM009 + RSM012 + RSM014 + RSM015 + RSM016 + RSM017 + RSM018 + RSM019 + RSM020 + RSM021 + RSM022 + RSM024 + RSM025 + RSM027 + RSM028 + RSM030 + RSM031 + RSM032 + RSM033 + RSM034 + RSM035 +} + enum CalculationExecutionType { EXTERNAL INTERNAL @@ -1093,6 +1235,63 @@ enum DocumentStatus { BIZ_TALK_ACCEPTED } +enum DocumentType { + CONFIRM_REQUEST_CHANGE_OF_SUPPLIER + REJECT_REQUEST_CHANGE_OF_SUPPLIER + REQUEST_CHANGE_OF_SUPPLIER + CONFIRM_REQUEST_REALLOCATE_CHANGE_OF_SUPPLIER + REJECT_REQUEST_REALLOCATE_CHANGE_OF_SUPPLIER + REQUEST_REALLOCATE_CHANGE_OF_SUPPLIER + GENERIC_NOTIFICATION + CONFIRM_REQUEST_END_OF_SUPPLY + REJECT_REQUEST_END_OF_SUPPLY + REQUEST_END_OF_SUPPLY + REJECT_REQUEST_ACCOUNTING_POINT_CHARACTERISTICS + REQUEST_ACCOUNTING_POINT_CHARACTERISTICS + ACKNOWLEDGEMENT + NOTIFY_VALIDATED_MEASURE_DATA + NOTIFY_AGGREGATED_MEASURE_DATA + REJECT_REQUEST_VALIDATED_MEASURE_DATA + REQUEST_VALIDATED_MEASURE_DATA + REJECT_REQUEST_AGGREGATED_MEASURE_DATA + REQUEST_AGGREGATED_MEASURE_DATA + B2_C_REQUEST_AGGREGATED_MEASURE_DATA + REJECT_REQUEST_WHOLESALE_SETTLEMENT + REQUEST_WHOLESALE_SETTLEMENT + B2_C_REQUEST_WHOLESALE_SETTLEMENT + REJECT_REQUEST_FOR_REMINDERS + REMINDER_OF_MISSING_MEASURE_DATA + REQUEST_FOR_REMINDERS + NOTIFY_WHOLESALE_SERVICES + CONFIRM_REQUEST_SERVICE + REJECT_REQUEST_SERVICE + REQUEST_SERVICE + CONFIRM_REQUEST_CHANGE_ACCOUNTING_POINT_CHARACTERISTICS + REJECT_REQUEST_CHANGE_ACCOUNTING_POINT_CHARACTERISTICS + REQUEST_CHANGE_ACCOUNTING_POINT_CHARACTERISTICS + ACCOUNTING_POINT_CHARACTERISTICS + CONFIRM_REQUEST_CANCELLATION + REJECT_REQUEST_CANCELLATION + REQUEST_CANCELLATION + NOTIFY_CANCELLATION + CONFIRM_REQUEST_CHANGE_CUSTOMER_CHARACTERISTICS + REJECT_REQUEST_CHANGE_CUSTOMER_CHARACTERISTICS + REQUEST_CHANGE_CUSTOMER_CHARACTERISTICS + CHARACTERISTICS_OF_A_CUSTOMER_AT_AN_AP + CONFIRM_REQUEST_CHANGE_BILLING_MASTER_DATA + REJECT_REQUEST_CHANGE_BILLING_MASTER_DATA + REQUEST_CHANGE_BILLING_MASTER_DATA + NOTIFY_BILLING_MASTER_DATA + REJECT_REQUEST_BILLING_MASTER_DATA + REQUEST_BILLING_MASTER_DATA + CONFIRM_REQUEST_CHANGE_OF_PRICELIST + REJECT_REQUEST_CHANGE_OF_PRICELIST + REQUEST_CHANGE_OF_PRICELIST + NOTIFY_PRICELIST + REJECT_REQUEST_PRICELIST + REQUEST_PRICELIST +} + enum ESettStageComponent { INGESTION CONVERTER @@ -1140,6 +1339,24 @@ enum ExchangeEventSortProperty { LATEST_DISPATCHED } +enum GridAreaStatus { + Created + Active + Expired + Archived +} + +enum GridAreaType { + NotSet + Transmission + Distribution + Other + Test + GridLossDK + GridLossAbroad + Aboard +} + enum ImbalancePriceStatus { NO_DATA IN_COMPLETE @@ -1238,6 +1455,14 @@ enum RequestCalculationDataType { ALL_ENERGY } +enum SettlementReportMarketRole { + OTHER + GRID_ACCESS_PROVIDER + ENERGY_SUPPLIER + SYSTEM_OPERATOR + DATA_HUB_ADMINISTRATOR +} + enum SettlementReportStatusType { IN_PROGRESS ERROR diff --git a/apps/dh/api-dh/source/DataHub.WebApi/Clients/MarketParticipant/V1/MarketParticipantClient.cs b/apps/dh/api-dh/source/DataHub.WebApi/Clients/MarketParticipant/V1/MarketParticipantClient.cs index 9dad1a70ca..49159b618c 100644 --- a/apps/dh/api-dh/source/DataHub.WebApi/Clients/MarketParticipant/V1/MarketParticipantClient.cs +++ b/apps/dh/api-dh/source/DataHub.WebApi/Clients/MarketParticipant/V1/MarketParticipantClient.cs @@ -216,15 +216,6 @@ public partial interface IMarketParticipantClient_V1 /// A server side error occurred. System.Threading.Tasks.Task> BalanceResponsibilityRelationsAsync(System.Guid actorId, System.Threading.CancellationToken cancellationToken, string? api_version = null); - /// OK - /// A server side error occurred. - System.Threading.Tasks.Task GridAreaPostAsync(CreateGridAreaDto? body, string? api_version = null); - - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// OK - /// A server side error occurred. - System.Threading.Tasks.Task GridAreaPostAsync(CreateGridAreaDto? body, System.Threading.CancellationToken cancellationToken, string? api_version = null); - /// OK /// A server side error occurred. System.Threading.Tasks.Task> GridAreaGetAsync(string? api_version = null); @@ -234,15 +225,6 @@ public partial interface IMarketParticipantClient_V1 /// A server side error occurred. System.Threading.Tasks.Task> GridAreaGetAsync(System.Threading.CancellationToken cancellationToken, string? api_version = null); - /// OK - /// A server side error occurred. - System.Threading.Tasks.Task GridAreaPutAsync(System.Guid gridAreaId, ChangeGridAreaDto? body, string? api_version = null); - - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// OK - /// A server side error occurred. - System.Threading.Tasks.Task GridAreaPutAsync(System.Guid gridAreaId, ChangeGridAreaDto? body, System.Threading.CancellationToken cancellationToken, string? api_version = null); - /// OK /// A server side error occurred. System.Threading.Tasks.Task GridAreaGetAsync(System.Guid gridAreaId, string? api_version = null); @@ -2560,94 +2542,6 @@ public virtual async System.Threading.Tasks.Task AuditIdentity } } - /// OK - /// A server side error occurred. - public virtual System.Threading.Tasks.Task GridAreaPostAsync(CreateGridAreaDto? body, string? api_version = null) - { - return GridAreaPostAsync(body, System.Threading.CancellationToken.None, api_version); - } - - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// OK - /// A server side error occurred. - public virtual async System.Threading.Tasks.Task GridAreaPostAsync(CreateGridAreaDto? body, System.Threading.CancellationToken cancellationToken, string? api_version = null) - { - var client_ = _httpClient; - var disposeClient_ = false; - try - { - using (var request_ = new System.Net.Http.HttpRequestMessage()) - { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value); - var content_ = new System.Net.Http.StringContent(json_); - content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); - request_.Content = content_; - request_.Method = new System.Net.Http.HttpMethod("POST"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("text/plain")); - - var urlBuilder_ = new System.Text.StringBuilder(); - if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); - // Operation Path: "GridArea" - urlBuilder_.Append("GridArea"); - urlBuilder_.Append('?'); - if (api_version != null) - { - urlBuilder_.Append(System.Uri.EscapeDataString("api-version")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(api_version, System.Globalization.CultureInfo.InvariantCulture))).Append('&'); - } - urlBuilder_.Length--; - - PrepareRequest(client_, request_, urlBuilder_); - - var url_ = urlBuilder_.ToString(); - request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); - - PrepareRequest(client_, request_, url_); - - var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - var disposeResponse_ = true; - try - { - var headers_ = new System.Collections.Generic.Dictionary>(); - foreach (var item_ in response_.Headers) - headers_[item_.Key] = item_.Value; - if (response_.Content != null && response_.Content.Headers != null) - { - foreach (var item_ in response_.Content.Headers) - headers_[item_.Key] = item_.Value; - } - - ProcessResponse(client_, response_); - - var status_ = (int)response_.StatusCode; - if (status_ == 200) - { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; - } - else - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); - } - } - finally - { - if (disposeResponse_) - response_.Dispose(); - } - } - } - finally - { - if (disposeClient_) - client_.Dispose(); - } - } - /// OK /// A server side error occurred. public virtual System.Threading.Tasks.Task> GridAreaGetAsync(string? api_version = null) @@ -2732,92 +2626,6 @@ public virtual async System.Threading.Tasks.Task AuditIdentity } } - /// OK - /// A server side error occurred. - public virtual System.Threading.Tasks.Task GridAreaPutAsync(System.Guid gridAreaId, ChangeGridAreaDto? body, string? api_version = null) - { - return GridAreaPutAsync(gridAreaId, body, System.Threading.CancellationToken.None, api_version); - } - - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// OK - /// A server side error occurred. - public virtual async System.Threading.Tasks.Task GridAreaPutAsync(System.Guid gridAreaId, ChangeGridAreaDto? body, System.Threading.CancellationToken cancellationToken, string? api_version = null) - { - if (gridAreaId == null) - throw new System.ArgumentNullException("gridAreaId"); - - var client_ = _httpClient; - var disposeClient_ = false; - try - { - using (var request_ = new System.Net.Http.HttpRequestMessage()) - { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(body, _settings.Value); - var content_ = new System.Net.Http.StringContent(json_); - content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); - request_.Content = content_; - request_.Method = new System.Net.Http.HttpMethod("PUT"); - - var urlBuilder_ = new System.Text.StringBuilder(); - if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); - // Operation Path: "GridArea/{gridAreaId}" - urlBuilder_.Append("GridArea/"); - urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(gridAreaId, System.Globalization.CultureInfo.InvariantCulture))); - urlBuilder_.Append('?'); - if (api_version != null) - { - urlBuilder_.Append(System.Uri.EscapeDataString("api-version")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(api_version, System.Globalization.CultureInfo.InvariantCulture))).Append('&'); - } - urlBuilder_.Length--; - - PrepareRequest(client_, request_, urlBuilder_); - - var url_ = urlBuilder_.ToString(); - request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); - - PrepareRequest(client_, request_, url_); - - var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - var disposeResponse_ = true; - try - { - var headers_ = new System.Collections.Generic.Dictionary>(); - foreach (var item_ in response_.Headers) - headers_[item_.Key] = item_.Value; - if (response_.Content != null && response_.Content.Headers != null) - { - foreach (var item_ in response_.Content.Headers) - headers_[item_.Key] = item_.Value; - } - - ProcessResponse(client_, response_); - - var status_ = (int)response_.StatusCode; - if (status_ == 200) - { - return; - } - else - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); - } - } - finally - { - if (disposeResponse_) - response_.Dispose(); - } - } - } - finally - { - if (disposeClient_) - client_.Dispose(); - } - } - /// OK /// A server side error occurred. public virtual System.Threading.Tasks.Task GridAreaGetAsync(System.Guid gridAreaId, string? api_version = null) @@ -7326,14 +7134,6 @@ public partial class ChangeActorDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] - public partial class ChangeGridAreaDto - { - [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string Name { get; set; } = default!; - - } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ChangeOrganizationDto { @@ -7418,20 +7218,6 @@ public partial class CreateActorDto } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] - public partial class CreateGridAreaDto - { - [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string Name { get; set; } = default!; - - [Newtonsoft.Json.JsonProperty("code", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string Code { get; set; } = default!; - - [Newtonsoft.Json.JsonProperty("priceAreaCode", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string PriceAreaCode { get; set; } = default!; - - } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] public partial class CreateOrganizationDto { @@ -7713,6 +7499,9 @@ public partial class GridAreaDto [Newtonsoft.Json.JsonProperty("priceAreaCode", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string PriceAreaCode { get; set; } = default!; + [Newtonsoft.Json.JsonProperty("type", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public GridAreaType Type { get; set; } = default!; + [Newtonsoft.Json.JsonProperty("validFrom", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public System.DateTimeOffset ValidFrom { get; set; } = default!; @@ -7754,6 +7543,31 @@ public partial class GridAreaOverviewItemDto [Newtonsoft.Json.JsonProperty("fullFlexDate", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public System.DateTimeOffset? FullFlexDate { get; set; } = default!; + [Newtonsoft.Json.JsonProperty("type", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public GridAreaType Type { get; set; } = default!; + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + public enum GridAreaType + { + + NotSet = 0, + + Transmission = 1, + + Distribution = 2, + + Other = 3, + + Test = 4, + + GridLossDK = 5, + + GridLossAbroad = 6, + + Aboard = 7, + } [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.3.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] diff --git a/apps/dh/api-dh/source/DataHub.WebApi/Clients/MarketParticipant/V1/swagger.json b/apps/dh/api-dh/source/DataHub.WebApi/Clients/MarketParticipant/V1/swagger.json index 050f218ccc..144f4ebbb6 100644 --- a/apps/dh/api-dh/source/DataHub.WebApi/Clients/MarketParticipant/V1/swagger.json +++ b/apps/dh/api-dh/source/DataHub.WebApi/Clients/MarketParticipant/V1/swagger.json @@ -1148,77 +1148,6 @@ } }, "/GridArea": { - "post": { - "tags": [ - "GridArea" - ], - "operationId": "GridAreaPOST", - "parameters": [ - { - "name": "api-version", - "in": "query", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/CreateGridAreaDto" - } - ] - } - }, - "text/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/CreateGridAreaDto" - } - ] - } - }, - "application/*+json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/CreateGridAreaDto" - } - ] - } - } - } - }, - "responses": { - "200": { - "description": "OK", - "content": { - "text/plain": { - "schema": { - "type": "string", - "format": "uuid" - } - }, - "application/json": { - "schema": { - "type": "string", - "format": "uuid" - } - }, - "text/json": { - "schema": { - "type": "string", - "format": "uuid" - } - } - } - } - } - }, "get": { "tags": [ "GridArea" @@ -1267,71 +1196,11 @@ } }, "/GridArea/{gridAreaId}": { - "put": { - "tags": [ - "GridArea" - ], - "operationId": "GridAreaPUT", - "parameters": [ - { - "name": "gridAreaId", - "in": "path", - "required": true, - "schema": { - "type": "string", - "format": "uuid" - } - }, - { - "name": "api-version", - "in": "query", - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ChangeGridAreaDto" - } - ] - } - }, - "text/json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ChangeGridAreaDto" - } - ] - } - }, - "application/*+json": { - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/ChangeGridAreaDto" - } - ] - } - } - } - }, - "responses": { - "200": { - "description": "OK" - } - } - }, "get": { "tags": [ "GridArea" ], - "operationId": "GridAreaGET", + "operationId": "GridArea", "parameters": [ { "name": "gridAreaId", @@ -4165,15 +4034,6 @@ } } }, - "ChangeGridAreaDto": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - } - } - }, "ChangeOrganizationDto": { "type": "object", "additionalProperties": false, @@ -4297,21 +4157,6 @@ } } }, - "CreateGridAreaDto": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "code": { - "type": "string" - }, - "priceAreaCode": { - "type": "string" - } - } - }, "CreateOrganizationDto": { "type": "object", "additionalProperties": false, @@ -4720,6 +4565,23 @@ "priceAreaCode": { "type": "string" }, + "type": { + "x-enumNames": [ + "NotSet", + "Transmission", + "Distribution", + "Other", + "Test", + "GridLossDK", + "GridLossAbroad", + "Aboard" + ], + "allOf": [ + { + "$ref": "#/components/schemas/GridAreaType" + } + ] + }, "validFrom": { "type": "string", "format": "date-time" @@ -4773,9 +4635,50 @@ "type": "string", "format": "date-time", "nullable": true + }, + "type": { + "x-enumNames": [ + "NotSet", + "Transmission", + "Distribution", + "Other", + "Test", + "GridLossDK", + "GridLossAbroad", + "Aboard" + ], + "allOf": [ + { + "$ref": "#/components/schemas/GridAreaType" + } + ] } } }, + "GridAreaType": { + "type": "integer", + "format": "int32", + "x-enumNames": [ + "NotSet", + "Transmission", + "Distribution", + "Other", + "Test", + "GridLossDK", + "GridLossAbroad", + "Aboard" + ], + "enum": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7 + ] + }, "InvitationUserDetailsDto": { "type": "object", "additionalProperties": false, diff --git a/apps/dh/api-dh/source/DataHub.WebApi/Clients/Wholesale/SettlementReports/Dto/SettlementReportMarketRole.cs b/apps/dh/api-dh/source/DataHub.WebApi/Clients/Wholesale/SettlementReports/Dto/SettlementReportMarketRole.cs new file mode 100644 index 0000000000..dc96692954 --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/Clients/Wholesale/SettlementReports/Dto/SettlementReportMarketRole.cs @@ -0,0 +1,24 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Energinet.DataHub.WebApi.Clients.Wholesale.SettlementReports.Dto; + +public enum SettlementReportMarketRole +{ + Other, + GridAccessProvider, + EnergySupplier, + SystemOperator, + DataHubAdministrator, +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/Clients/Wholesale/SettlementReports/Dto/SettlementReportRequestDto.cs b/apps/dh/api-dh/source/DataHub.WebApi/Clients/Wholesale/SettlementReports/Dto/SettlementReportRequestDto.cs index 51b583250c..ac85d8ef1b 100644 --- a/apps/dh/api-dh/source/DataHub.WebApi/Clients/Wholesale/SettlementReports/Dto/SettlementReportRequestDto.cs +++ b/apps/dh/api-dh/source/DataHub.WebApi/Clients/Wholesale/SettlementReports/Dto/SettlementReportRequestDto.cs @@ -20,4 +20,6 @@ public sealed record SettlementReportRequestDto( bool IncludeBasisData, bool IncludeMonthlyAmount, bool UseAPI, - SettlementReportRequestFilterDto Filter); + SettlementReportRequestFilterDto Filter, + string? ActorNumberOverride, + SettlementReportMarketRole? MarketRoleOverride); diff --git a/apps/dh/api-dh/source/DataHub.WebApi/Controllers/MessageArchiveController.cs b/apps/dh/api-dh/source/DataHub.WebApi/Controllers/MessageArchiveController.cs index 630a936fbc..3384ec2a04 100644 --- a/apps/dh/api-dh/source/DataHub.WebApi/Controllers/MessageArchiveController.cs +++ b/apps/dh/api-dh/source/DataHub.WebApi/Controllers/MessageArchiveController.cs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.Net.Mime; using Energinet.DataHub.WebApi.Clients.EDI; using Microsoft.AspNetCore.Mvc; @@ -60,4 +61,13 @@ public async Task> GetDocumentAsync(string id, Cancellation var document = await _archivedMessagesSearch.GetDocumentAsync(Guid.Parse(id), cancellationToken); return Ok(document); } + + [HttpGet] + [Route("Document")] + [Produces(MediaTypeNames.Text.Plain)] + public async Task> GetDocumentByIdAsync(string id, CancellationToken cancellationToken) + { + var document = await _archivedMessagesSearch.GetDocumentAsync(Guid.Parse(id), cancellationToken); + return Ok(document); + } } diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/DataLoaders/ActorByNumberBatchDataLoader.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/DataLoaders/ActorByNumberBatchDataLoader.cs new file mode 100644 index 0000000000..e000e54540 --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/DataLoaders/ActorByNumberBatchDataLoader.cs @@ -0,0 +1,40 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Energinet.DataHub.WebApi.Clients.MarketParticipant.v1; + +namespace Energinet.DataHub.WebApi.GraphQL.DataLoaders; + +public class ActorByNumberBatchDataLoader : BatchDataLoader +{ + private readonly IMarketParticipantClient_V1 _client; + + public ActorByNumberBatchDataLoader( + IMarketParticipantClient_V1 client, + IBatchScheduler batchScheduler, + DataLoaderOptions? options = null) + : base(batchScheduler, options) => + _client = client; + + protected override async Task> LoadBatchAsync( + IReadOnlyList keys, + CancellationToken cancellationToken) + { + return (await _client + .ActorGetAsync(cancellationToken)) + .Where(x => keys.Contains(x.ActorNumber.Value)) + .DistinctBy(x => x.ActorNumber.Value) // TODO: This is not the correct way + .ToDictionary(x => x.ActorNumber.Value); + } +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Enums/BusinessReason.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Enums/BusinessReason.cs new file mode 100644 index 0000000000..0e7277bc02 --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Enums/BusinessReason.cs @@ -0,0 +1,83 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Energinet.DataHub.WebApi.GraphQL.Enums; + +public enum BusinessReason +{ + D02, // Preparation for imbalance settlement + D03, // Temporary + D04, // 1st settlement + D05, // 2nd settlement + D06, // Continuous meter reading from profiled metering points + D07, // Rollback Change-of-supplier + D09, // Latest available value + D10, // Meter reading, profiled consumption + D11, // Incorrect process + D12, // Cancel meter reading request + D13, // Change of supply to supplier of last resort + D14, // Close down metering point + D15, // Connect meteringpoint + D16, // Merge of Grids + D17, // Update masterdata settlement + D18, // Update charge information + D19, // Meter Reading + D20, // Electrical heating + D21, // Move-in due to other reason + D22, // Service request + D23, // Not used + D24, // Missing flex meter reading + D25, // Missing non-profiled time series + D26, // Missing flex time series + D27, // Missing profiled reading + D28, // Proposal contact information + D29, // Secondary move-in + D30, // Switch with short notice + D31, // Transfer metering point + D32, // Correction settlement + D33, // Incorrect move + D34, // End supply due to reallocate + D35, // Continue supply due to rejected reallocate + D36, // Continue supply of customer + D37, // Cancel service request + D38, // End of supply with short notice + D39, // Production Obligation + D40, // Removed parent relation on meteringpoint + D41, // No disconnection of meteringpoint + D43, // Historical information about consumption + D44, // Process cancelled by requesting party + D45, // Process cancelled by ITX + D46, // Date of Supplier change caused by End of supply + D47, // Reminder + E01, // Move + E02, // New metering point + E03, // Change of balance supplier + E05, // Cancellation + E06, // Unrequested change of balance supplier + E0G, // Data alignment for master data metering point + E20, // End of supply + E23, // Periodic metering + E30, // Historical data + E32, // Update master data metering point + E34, // Update master data consumer + E53, // Meter reading on demand + E56, // Change of Balance Responsible Party + E65, // Customer move-in + E66, // Customer move-out + E67, // Placement of Meter + E75, // Change of metering method + E79, // Change Connection Status + E80, // Change of estimated annual volume + E84, // Update master data meter +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Enums/BusinessTransaction.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Enums/BusinessTransaction.cs new file mode 100644 index 0000000000..e9c7ff2545 --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Enums/BusinessTransaction.cs @@ -0,0 +1,45 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Energinet.DataHub.WebApi.GraphQL.Enums; + +public enum BusinessTransaction +{ + RSM001, + RSM003, + RSM004, + RSM005, + RSM006, + RSM009, + RSM012, + RSM014, + RSM015, + RSM016, + RSM017, + RSM018, + RSM019, + RSM020, + RSM021, + RSM022, + RSM024, + RSM025, + RSM027, + RSM028, + RSM030, + RSM031, + RSM032, + RSM033, + RSM034, + RSM035, +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Enums/DocumentType.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Enums/DocumentType.cs new file mode 100644 index 0000000000..795c492c2b --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Enums/DocumentType.cs @@ -0,0 +1,73 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Energinet.DataHub.WebApi.GraphQL.Enums; + +public enum DocumentType +{ + ConfirmRequestChangeOfSupplier, + RejectRequestChangeOfSupplier, + RequestChangeOfSupplier, + ConfirmRequestReallocateChangeOfSupplier, + RejectRequestReallocateChangeOfSupplier, + RequestReallocateChangeOfSupplier, + GenericNotification, + ConfirmRequestEndOfSupply, + RejectRequestEndOfSupply, + RequestEndOfSupply, + RejectRequestAccountingPointCharacteristics, + RequestAccountingPointCharacteristics, + Acknowledgement, + NotifyValidatedMeasureData, + NotifyAggregatedMeasureData, + RejectRequestValidatedMeasureData, + RequestValidatedMeasureData, + RejectRequestAggregatedMeasureData, + RequestAggregatedMeasureData, + B2CRequestAggregatedMeasureData, + RejectRequestWholesaleSettlement, + RequestWholesaleSettlement, + B2CRequestWholesaleSettlement, + RejectRequestForReminders, + ReminderOfMissingMeasureData, + RequestForReminders, + NotifyWholesaleServices, + ConfirmRequestService, + RejectRequestService, + RequestService, + ConfirmRequestChangeAccountingPointCharacteristics, + RejectRequestChangeAccountingPointCharacteristics, + RequestChangeAccountingPointCharacteristics, + AccountingPointCharacteristics, + ConfirmRequestCancellation, + RejectRequestCancellation, + RequestCancellation, + NotifyCancellation, + ConfirmRequestChangeCustomerCharacteristics, + RejectRequestChangeCustomerCharacteristics, + RequestChangeCustomerCharacteristics, + CharacteristicsOfACustomerAtAnAP, + ConfirmRequestChangeBillingMasterData, + RejectRequestChangeBillingMasterData, + RequestChangeBillingMasterData, + NotifyBillingMasterData, + RejectRequestBillingMasterData, + RequestBillingMasterData, + ConfirmRequestChangeOfPricelist, + RejectRequestChangeOfPricelist, + RequestChangeOfPricelist, + NotifyPricelist, + RejectRequestPricelist, + RequestPricelist, +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Enums/GridAreaStatus.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Enums/GridAreaStatus.cs new file mode 100644 index 0000000000..afbe89bbf6 --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Enums/GridAreaStatus.cs @@ -0,0 +1,23 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace Energinet.DataHub.WebApi.GraphQL.Enums; + +public enum GridAreaStatus +{ + Created, + Active, + Expired, + Archived, +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Mutation/SettlementReportMutation.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Mutation/SettlementReportMutation.cs index 76bf859872..6ee7b7f35b 100644 --- a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Mutation/SettlementReportMutation.cs +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Mutation/SettlementReportMutation.cs @@ -41,7 +41,9 @@ await client.RequestAsync( requestSettlementReportInput.IncludeBasisData, requestSettlementReportInput.IncludeMonthlySums, requestSettlementReportInput.UseApi, - requestFilter), + requestFilter, + requestSettlementReportInput.RequestAsActorId, + requestSettlementReportInput.RequestAsMarketRole), default); return true; diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Query/MessageArchiveQuery.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Query/MessageArchiveQuery.cs new file mode 100644 index 0000000000..7d84401f18 --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Query/MessageArchiveQuery.cs @@ -0,0 +1,57 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Energinet.DataHub.Edi.B2CWebApp.Clients.v1; +using Energinet.DataHub.WebApi.GraphQL.Enums; +using Microsoft.IdentityModel.Tokens; +using NodaTime; + +namespace Energinet.DataHub.WebApi.GraphQL.Query; + +public partial class Query +{ + [UsePaging] + [UseSorting] + public async Task> GetArchivedMessagesAsync( + Interval created, + string? messageId, + string? senderNumber, + string? receiverNumber, + DocumentType[]? documentTypes, + BusinessReason[]? businessReasons, + string? filter, + [Service] IEdiB2CWebAppClient_V1 client) + { + var search = !string.IsNullOrWhiteSpace(filter) + ? new SearchArchivedMessagesCriteria() { MessageId = filter, IncludeRelatedMessages = true } + : new SearchArchivedMessagesCriteria() + { + CreatedDuringPeriod = new MessageCreationPeriod() + { + Start = created.Start.ToDateTimeOffset(), + End = created.End.ToDateTimeOffset(), + }, + SenderNumber = string.IsNullOrEmpty(senderNumber) ? null : messageId, + ReceiverNumber = string.IsNullOrEmpty(receiverNumber) ? null : messageId, + DocumentTypes = documentTypes.IsNullOrEmpty() + ? null + : documentTypes?.Select(x => x.ToString()).ToArray(), + BusinessReasons = businessReasons.IsNullOrEmpty() + ? null + : businessReasons?.Select(x => x.ToString()).ToArray(), + }; + + return await client.ArchivedMessageSearchAsync("1.0", search); + } +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Resolvers/GridAreaResolver.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Resolvers/GridAreaResolver.cs new file mode 100644 index 0000000000..1cbc5f7c95 --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Resolvers/GridAreaResolver.cs @@ -0,0 +1,62 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Energinet.DataHub.WebApi.Clients.MarketParticipant.v1; +using Energinet.DataHub.WebApi.GraphQL.Enums; + +namespace Energinet.DataHub.WebApi.GraphQL.Resolvers; + +public class GridAreaResolvers +{ + public GridAreaStatus CalculateGridAreaStatus([Parent] IGridArea gridarea) + { + var validFrom = gridarea.ValidFrom; + var validTo = gridarea.ValidTo; + + if (validFrom > DateTimeOffset.UtcNow) + { + return GridAreaStatus.Created; + } + + if (validTo < DateTimeOffset.UtcNow) + { + return GridAreaStatus.Expired; + } + + if (validFrom <= DateTimeOffset.UtcNow && validTo >= DateTimeOffset.UtcNow) + { + return GridAreaStatus.Active; + } + + if (validFrom <= DateTimeOffset.UtcNow && validTo == null) + { + return GridAreaStatus.Active; + } + + return GridAreaStatus.Archived; + } + + public PriceAreaCode ParsePriceAreaCode([Parent] IGridArea gridarea) + { + return Enum.Parse(gridarea.PriceAreaCode); + } + + public string DisplayName([Parent] IGridArea gridarea) => + gridarea switch + { + null => string.Empty, + var gridArea when string.IsNullOrWhiteSpace(gridArea.Name) => gridArea.Code, + var gridArea => $"{gridArea.Code} • {gridArea.Name}", + }; +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Resolvers/MarketParticipantResolvers.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Resolvers/MarketParticipantResolvers.cs index 7f672c4f7b..e9331c4101 100644 --- a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Resolvers/MarketParticipantResolvers.cs +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Resolvers/MarketParticipantResolvers.cs @@ -14,6 +14,7 @@ using Energinet.DataHub.WebApi.Clients.MarketParticipant.v1; using Energinet.DataHub.WebApi.GraphQL.DataLoaders; +using Energinet.DataHub.WebApi.GraphQL.Enums; using Energinet.DataHub.WebApi.GraphQL.Types.Actor; using Energinet.DataHub.WebApi.GraphQL.Types.Process; using Energinet.DataHub.WebApi.GraphQL.Types.User; diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Resolvers/MessageArchiveResolvers.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Resolvers/MessageArchiveResolvers.cs new file mode 100644 index 0000000000..c3eb3c295b --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Resolvers/MessageArchiveResolvers.cs @@ -0,0 +1,32 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Energinet.DataHub.Edi.B2CWebApp.Clients.v1; +using Energinet.DataHub.WebApi.Clients.ESettExchange.v1; +using Energinet.DataHub.WebApi.Clients.MarketParticipant.v1; +using Energinet.DataHub.WebApi.GraphQL.DataLoaders; + +namespace Energinet.DataHub.WebApi.GraphQL.Resolvers; + +public class MessageArchiveResolvers +{ + public string? GetDocument( + [Parent] ArchivedMessageResult result, + [Service] IHttpContextAccessor httpContextAccessor, + [Service] LinkGenerator linkGenerator) => linkGenerator.GetUriByAction( + httpContextAccessor.HttpContext!, + "GetDocumentById", + "MessageArchive", + new { id = result.Id }); +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaDto.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaDto.cs new file mode 100644 index 0000000000..bc0feb856a --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaDto.cs @@ -0,0 +1,20 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma warning disable SA1300 // Element should begin with upper-case letter +namespace Energinet.DataHub.WebApi.Clients.MarketParticipant.v1; +#pragma warning restore SA1300 // Element should begin with upper-case letter + +public partial class GridAreaDto : IGridArea +{ } diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaDtoType.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaDtoType.cs new file mode 100644 index 0000000000..dcf1200bee --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaDtoType.cs @@ -0,0 +1,44 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Energinet.DataHub.WebApi.Clients.MarketParticipant.v1; +using Energinet.DataHub.WebApi.GraphQL.Resolvers; + +namespace Energinet.DataHub.WebApi.GraphQL.Types.GridArea; + +public class GridAreaDtoType : ObjectType +{ + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.Name("GridAreaDto"); + + descriptor + .Field(f => f.PriceAreaCode) + .Name("priceAreaCode") + .ResolveWith(c => c.ParsePriceAreaCode(default!)); + + descriptor + .Field("displayName") + .Type>() + .ResolveWith(c => c.DisplayName(default!)); + + descriptor + .Field("status") + .ResolveWith(c => c.CalculateGridAreaStatus(default!)); + + descriptor + .Field("includedInCalculation") + .Resolve(context => new[] { GridAreaType.Test, GridAreaType.Distribution, GridAreaType.GridLossDK }.Contains(context.Parent().Type)); + } +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaEnumType.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaEnumType.cs new file mode 100644 index 0000000000..533e8f0d6a --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaEnumType.cs @@ -0,0 +1,26 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Energinet.DataHub.WebApi.Clients.MarketParticipant.v1; +using Energinet.DataHub.WebApi.GraphQL.Extensions; + +namespace Energinet.DataHub.WebApi.GraphQL.Types.GridArea; + +public class GridAreaEnumType : EnumType +{ + protected override void Configure(IEnumTypeDescriptor descriptor) + { + descriptor.AsIsCase(); + } +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaOverviewItemDto.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaOverviewItemDto.cs new file mode 100644 index 0000000000..58f372eed2 --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaOverviewItemDto.cs @@ -0,0 +1,20 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma warning disable SA1300 // Element should begin with upper-case letter +namespace Energinet.DataHub.WebApi.Clients.MarketParticipant.v1; +#pragma warning restore SA1300 // Element should begin with upper-case letter + +public partial class GridAreaOverviewItemDto : IGridArea +{ } diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaOverviewItemDtoType.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaOverviewItemDtoType.cs new file mode 100644 index 0000000000..163e4e69fd --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaOverviewItemDtoType.cs @@ -0,0 +1,38 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Energinet.DataHub.WebApi.Clients.MarketParticipant.v1; +using Energinet.DataHub.WebApi.GraphQL.Resolvers; + +namespace Energinet.DataHub.WebApi.GraphQL.Types.GridArea; + +public class GridAreaOverviewItemDtoType : ObjectType +{ + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor + .Field(f => f.PriceAreaCode) + .Name("priceAreaCode") + .ResolveWith(c => c.ParsePriceAreaCode(default!)); + + descriptor + .Field("displayName") + .Type>() + .ResolveWith(c => c.DisplayName(default!)); + + descriptor + .Field("status") + .ResolveWith(c => c.CalculateGridAreaStatus(default!)); + } +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaStatusType.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaStatusType.cs new file mode 100644 index 0000000000..3cd193a903 --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/GridAreaStatusType.cs @@ -0,0 +1,26 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Energinet.DataHub.WebApi.GraphQL.Enums; +using Energinet.DataHub.WebApi.GraphQL.Extensions; + +namespace Energinet.DataHub.WebApi.GraphQL.Types.GridArea; + +public class GridAreaStatusType : EnumType +{ + protected override void Configure(IEnumTypeDescriptor descriptor) + { + descriptor.AsIsCase(); + } +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/IGridArea.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/IGridArea.cs new file mode 100644 index 0000000000..b5f4bf3d9d --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridArea/IGridArea.cs @@ -0,0 +1,48 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#pragma warning disable SA1300 // Element should begin with upper-case letter +namespace Energinet.DataHub.WebApi.Clients.MarketParticipant.v1; +#pragma warning restore SA1300 // Element should begin with upper-case letter + +/// +/// Represents a grid area. +/// +public interface IGridArea +{ + /// + /// The grid area code. + /// + public string PriceAreaCode { get; } + + /// + /// The grid area name. + /// + public string Name { get; } + + /// + /// The grid area code. + /// + public string Code { get; } + + /// + /// The grid area Validfrom. + /// + public DateTimeOffset ValidFrom { get; } + + /// + /// The grid area Validto. + /// + public DateTimeOffset? ValidTo { get; } +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridAreaType.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridAreaType.cs deleted file mode 100644 index 5a60475ae6..0000000000 --- a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/GridAreaType.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2020 Energinet DataHub A/S -// -// Licensed under the Apache License, Version 2.0 (the "License2"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using Energinet.DataHub.WebApi.Clients.MarketParticipant.v1; -using Energinet.DataHub.WebApi.GraphQL.Enums; - -namespace Energinet.DataHub.WebApi.GraphQL.Types; - -public class GridAreaType : ObjectType -{ - // This list should be replaced with data from the MarketParticipant API once available - private readonly List _includedInCalculation = [ - "003", "007", "016", "031", "042", "051", "084", "085", "131", "141", "151", "154", "233", - "244", "245", "331", "341", "342", "344", "347", "348", "351", "357", "370", "371", "381", - "384", "385", "396", "531", "532", "533", "543", "584", "740", "757", "791", "853", "854", - "860", "911", "950", "951", "952", "953", "954", "960", "962", "990"]; - - protected override void Configure(IObjectTypeDescriptor descriptor) - { - descriptor.Name("GridAreaDto"); - - descriptor - .Field(f => f.PriceAreaCode) - .Name("priceAreaCode") - .Resolve(context => - Enum.Parse(context.Parent().PriceAreaCode)); - - descriptor - .Field("displayName") - .Type>() - .Resolve(context => context.Parent() switch - { - null => string.Empty, - var gridArea when string.IsNullOrWhiteSpace(gridArea.Name) => gridArea.Code, - var gridArea => $"{gridArea.Code} • {gridArea.Name}", - }); - - descriptor - .Field("includedInCalculation") - .Resolve(context => _includedInCalculation.Contains(context.Parent().Code)); - } -} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/MessageArchive/ArchivedMessageSortType.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/MessageArchive/ArchivedMessageSortType.cs new file mode 100644 index 0000000000..11ac54c355 --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/MessageArchive/ArchivedMessageSortType.cs @@ -0,0 +1,32 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Energinet.DataHub.Edi.B2CWebApp.Clients.v1; +using HotChocolate.Data.Sorting; + +namespace Energinet.DataHub.WebApi.GraphQL.Types.MessageArchive; + +public class ArchivedMessageSortType : SortInputType +{ + protected override void Configure(ISortInputTypeDescriptor descriptor) + { + descriptor.Name("ArchivedMessageSortInput"); + descriptor.BindFieldsExplicitly(); + descriptor.Field(f => f.MessageId); + descriptor.Field(f => f.DocumentType); + descriptor.Field(f => f.SenderNumber).Name("sender"); + descriptor.Field(f => f.ReceiverNumber).Name("receiver"); + descriptor.Field(f => f.CreatedAt); + } +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/MessageArchive/ArchivedMessageType.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/MessageArchive/ArchivedMessageType.cs new file mode 100644 index 0000000000..b5592401db --- /dev/null +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/MessageArchive/ArchivedMessageType.cs @@ -0,0 +1,113 @@ +// Copyright 2020 Energinet DataHub A/S +// +// Licensed under the Apache License, Version 2.0 (the "License2"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Energinet.DataHub.Edi.B2CWebApp.Clients.v1; +using Energinet.DataHub.WebApi.GraphQL.DataLoaders; +using Energinet.DataHub.WebApi.GraphQL.Enums; +using Energinet.DataHub.WebApi.GraphQL.Resolvers; +using Energinet.DataHub.WebApi.GraphQL.Types.Actor; + +namespace Energinet.DataHub.WebApi.GraphQL.Types.MessageArchive; + +public class ArchivedMessageType : ObjectType +{ + protected override void Configure(IObjectTypeDescriptor descriptor) + { + descriptor.Name("ArchivedMessage"); + + descriptor + .Field(f => f.SenderNumber) + .Name("sender") + .Type() + .Resolve(context => context.DataLoader().LoadAsync( + context.Parent().SenderNumber, + context.RequestAborted)); + + descriptor + .Field(f => f.ReceiverNumber) + .Name("receiver") + .Type() + .Resolve(context => context.DataLoader().LoadAsync( + context.Parent().ReceiverNumber, + context.RequestAborted)); + + descriptor + .Field(f => f.DocumentType) + .Resolve(context => Enum.Parse(context.Parent().DocumentType)); + + descriptor.Field("documentUrl") + .ResolveWith(c => c.GetDocument(default!, default!, default!)); + + descriptor + .Field("businessTransaction") + .Resolve(context => + Enum.Parse(context.Parent().DocumentType) switch + { + DocumentType.ConfirmRequestChangeOfSupplier => BusinessTransaction.RSM001, + DocumentType.RejectRequestChangeOfSupplier => BusinessTransaction.RSM001, + DocumentType.RequestChangeOfSupplier => BusinessTransaction.RSM001, + DocumentType.ConfirmRequestReallocateChangeOfSupplier => BusinessTransaction.RSM003, + DocumentType.RejectRequestReallocateChangeOfSupplier => BusinessTransaction.RSM003, + DocumentType.RequestReallocateChangeOfSupplier => BusinessTransaction.RSM003, + DocumentType.GenericNotification => BusinessTransaction.RSM004, + DocumentType.ConfirmRequestEndOfSupply => BusinessTransaction.RSM005, + DocumentType.RejectRequestEndOfSupply => BusinessTransaction.RSM005, + DocumentType.RequestEndOfSupply => BusinessTransaction.RSM005, + DocumentType.RejectRequestAccountingPointCharacteristics => BusinessTransaction.RSM006, + DocumentType.RequestAccountingPointCharacteristics => BusinessTransaction.RSM006, + DocumentType.Acknowledgement => BusinessTransaction.RSM009, + DocumentType.NotifyValidatedMeasureData => BusinessTransaction.RSM012, + DocumentType.NotifyAggregatedMeasureData => BusinessTransaction.RSM014, + DocumentType.RejectRequestValidatedMeasureData => BusinessTransaction.RSM015, + DocumentType.RequestValidatedMeasureData => BusinessTransaction.RSM015, + DocumentType.RejectRequestAggregatedMeasureData => BusinessTransaction.RSM016, + DocumentType.RequestAggregatedMeasureData => BusinessTransaction.RSM016, + DocumentType.B2CRequestAggregatedMeasureData => BusinessTransaction.RSM016, + DocumentType.RejectRequestWholesaleSettlement => BusinessTransaction.RSM017, + DocumentType.RequestWholesaleSettlement => BusinessTransaction.RSM017, + DocumentType.B2CRequestWholesaleSettlement => BusinessTransaction.RSM017, + DocumentType.RejectRequestForReminders => BusinessTransaction.RSM018, + DocumentType.ReminderOfMissingMeasureData => BusinessTransaction.RSM018, + DocumentType.RequestForReminders => BusinessTransaction.RSM018, + DocumentType.NotifyWholesaleServices => BusinessTransaction.RSM019, + DocumentType.ConfirmRequestService => BusinessTransaction.RSM020, + DocumentType.RejectRequestService => BusinessTransaction.RSM020, + DocumentType.RequestService => BusinessTransaction.RSM020, + DocumentType.ConfirmRequestChangeAccountingPointCharacteristics => BusinessTransaction.RSM021, + DocumentType.RejectRequestChangeAccountingPointCharacteristics => BusinessTransaction.RSM021, + DocumentType.RequestChangeAccountingPointCharacteristics => BusinessTransaction.RSM021, + DocumentType.AccountingPointCharacteristics => BusinessTransaction.RSM022, + DocumentType.ConfirmRequestCancellation => BusinessTransaction.RSM024, + DocumentType.RejectRequestCancellation => BusinessTransaction.RSM024, + DocumentType.RequestCancellation => BusinessTransaction.RSM024, + DocumentType.NotifyCancellation => BusinessTransaction.RSM025, + DocumentType.ConfirmRequestChangeCustomerCharacteristics => BusinessTransaction.RSM027, + DocumentType.RejectRequestChangeCustomerCharacteristics => BusinessTransaction.RSM027, + DocumentType.RequestChangeCustomerCharacteristics => BusinessTransaction.RSM027, + DocumentType.CharacteristicsOfACustomerAtAnAP => BusinessTransaction.RSM028, + DocumentType.ConfirmRequestChangeBillingMasterData => BusinessTransaction.RSM030, + DocumentType.RejectRequestChangeBillingMasterData => BusinessTransaction.RSM030, + DocumentType.RequestChangeBillingMasterData => BusinessTransaction.RSM030, + DocumentType.NotifyBillingMasterData => BusinessTransaction.RSM031, + DocumentType.RejectRequestBillingMasterData => BusinessTransaction.RSM032, + DocumentType.RequestBillingMasterData => BusinessTransaction.RSM032, + DocumentType.ConfirmRequestChangeOfPricelist => BusinessTransaction.RSM033, + DocumentType.RejectRequestChangeOfPricelist => BusinessTransaction.RSM033, + DocumentType.RequestChangeOfPricelist => BusinessTransaction.RSM033, + DocumentType.NotifyPricelist => BusinessTransaction.RSM034, + DocumentType.RejectRequestPricelist => BusinessTransaction.RSM035, + DocumentType.RequestPricelist => BusinessTransaction.RSM035, + }); + } +} diff --git a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/SettlementReports/RequestSettlementReportInput.cs b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/SettlementReports/RequestSettlementReportInput.cs index 0f126b71d3..c9989b59de 100644 --- a/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/SettlementReports/RequestSettlementReportInput.cs +++ b/apps/dh/api-dh/source/DataHub.WebApi/GraphQL/Types/SettlementReports/RequestSettlementReportInput.cs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using Energinet.DataHub.WebApi.Clients.Wholesale.SettlementReports.Dto; using NodaTime; namespace Energinet.DataHub.WebApi.GraphQL.Types.SettlementReports; @@ -26,4 +27,6 @@ public record RequestSettlementReportInput( bool IncludeBasisData, bool UseApi, string? EnergySupplier, - string? CsvLanguage); + string? CsvLanguage, + string? RequestAsActorId, + SettlementReportMarketRole? RequestAsMarketRole); diff --git a/apps/dh/api-dh/source/DataHub.WebApi/Program.cs b/apps/dh/api-dh/source/DataHub.WebApi/Program.cs index 56a02a0657..11eb8c8715 100644 --- a/apps/dh/api-dh/source/DataHub.WebApi/Program.cs +++ b/apps/dh/api-dh/source/DataHub.WebApi/Program.cs @@ -20,7 +20,6 @@ using Energinet.DataHub.WebApi; using Energinet.DataHub.WebApi.Registration; using Microsoft.AspNetCore.HttpOverrides; -using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; using OpenTelemetry.Trace; diff --git a/libs/dh/admin/data-access-graphql/project.json b/libs/dh/admin/data-access-graphql/project.json index 25c303f1b6..36573da9be 100644 --- a/libs/dh/admin/data-access-graphql/project.json +++ b/libs/dh/admin/data-access-graphql/project.json @@ -5,6 +5,7 @@ "sourceRoot": "libs/dh/admin/data-access-graphql", "prefix": "dh", "tags": ["product:dh", "domain:admin", "type:data-access"], + "implicitDependencies": ["api-dh"], "targets": { "lint": { "executor": "@nx/eslint:lint" diff --git a/libs/dh/esett/data-access-graphql/project.json b/libs/dh/esett/data-access-graphql/project.json index 1fdf2c82b4..346792b414 100644 --- a/libs/dh/esett/data-access-graphql/project.json +++ b/libs/dh/esett/data-access-graphql/project.json @@ -5,6 +5,7 @@ "sourceRoot": "libs/dh/esett/data-access-graphql", "prefix": "dh", "tags": ["product:dh", "domain:esett", "type:data-access"], + "implicitDependencies": ["api-dh"], "targets": { "lint": { "executor": "@nx/eslint:lint" diff --git a/libs/dh/globalization/assets-localization/src/assets/i18n/da.json b/libs/dh/globalization/assets-localization/src/assets/i18n/da.json index c3344b0693..7d027d2c38 100644 --- a/libs/dh/globalization/assets-localization/src/assets/i18n/da.json +++ b/libs/dh/globalization/assets-localization/src/assets/i18n/da.json @@ -50,6 +50,21 @@ "title": "Ingen resultater fundet", "message": "Prøv at ændre dine søgeindstillinger" }, + "data": { + "default": { + "title": "Start søgning", + "text": "Dine resultater vil fremgå her" + }, + "error": { + "title": "Ups! Der opstod en fejl", + "text": "Der opstod desværre en fejl, da vi skulle hente de nødvendige oplysninger", + "button": "Prøv igen" + }, + "empty": { + "title": "Ingen resultater fundet", + "text": "Prøv at ændre dine søgeindstillinger" + } + }, "navigation": { "next": "Næste", "previous": "Forrige" @@ -128,7 +143,10 @@ } }, "messageArchive": { - "unknowenError": "Ukendt fejl", + "topBarTitle": "Fremsøg forretningsbesked", + "new": "Ny søgning", + "results": "Resultater", + "searchById": "Søg på ID", "drawer": { "message": "Besked", "sender": "Afsender", @@ -140,6 +158,98 @@ "document": { "loadFailed": "Kunne ikke hente dokumentet" }, + "columns": { + "messageId": "Besked ID", + "documentType": "Dokumenttype", + "sender": "Afsender", + "receiver": "Modtager", + "createdAt": "Dato og tid" + }, + "start": { + "title": "Ny søgning", + "placeholder": "Indtast eller vælg", + "documentType": "Dokumenttype", + "businessReason": "Forretningsårsag", + "sender": "Afsender", + "receiver": "Modtager", + "start": "Starttidspunkt", + "end": "Sluttidspunkt", + "cancel": "Ryd søgning", + "confirm": "Søg" + }, + "details": { + "created": "Sendt", + "messageId": "Besked ID", + "sender": "Afsender", + "receiver": "Modtager", + "download": "Download" + }, + "businessReason": { + "D02": "Forberedelse til balanceafregning", + "D03": "Midlertidig", + "D04": "1. afregning", + "D05": "2. afregning", + "D06": "Kontinuerlig måleraflæsning fra profilmålepunkter", + "D07": "Tilbageførsel af leverandørskifte", + "D09": "Seneste tilgængelige værdi", + "D10": "Måleraflæsning, indberettet forbrug", + "D11": "Forkert proces", + "D12": "Annuller måleraflæsningsanmodning", + "D13": "Skift af leverandør til sidstnævnte udbyder", + "D14": "Luk målepunkt ned", + "D15": "Tilslut målepunkt", + "D16": "Sammensmeltning af net", + "D17": "Opdater afregningsdata", + "D18": "Opdater takstoplysninger", + "D19": "Måleraflæsning", + "D20": "Elektrisk opvarmning", + "D21": "Indflytning af anden årsag", + "D22": "Serviceanmodning", + "D23": "Ikke brugt", + "D24": "Manglende flex-måleraflæsning", + "D25": "Manglende ikke-profilen tidsserie", + "D26": "Manglende flex-tidsserie", + "D27": "Manglende profillæsning", + "D28": "Forslag kontaktinformation", + "D29": "Sekundær indflytning", + "D30": "Skift med kort varsel", + "D31": "Overfør målepunkt", + "D32": "Korrektionsafregning", + "D33": "Forkert flytning", + "D34": "Afslut forsyning pga. omfordeling", + "D35": "Fortsæt forsyning pga. afvist omfordeling", + "D36": "Fortsæt kundens forsyning", + "D37": "Annuller serviceanmodning", + "D38": "Afslut forsyning med kort varsel", + "D39": "Produktionsforpligtelse", + "D40": "Fjernede forældre relation på målepunkt", + "D41": "Ingen afbrydelse af målepunkt", + "D43": "Historiske oplysninger om forbrug", + "D44": "Proces annulleret af anmodende part", + "D45": "Proces annulleret af ITX", + "D46": "Dato for leverandørskifte forårsaget af afslutning af forsyning", + "D47": "Påmindelse", + "E01": "Flytte", + "E02": "Nyt målepunkt", + "E03": "Skift af balanceleverandør", + "E05": "Annullering", + "E06": "Ikke-anmodet skift af balanceleverandør", + "E0G": "Datajustering for stamdata målepunkt", + "E20": "Afslutning af forsyning", + "E23": "Periodisk aflæsning", + "E30": "Historiske data", + "E32": "Opdater stamdata målepunkt", + "E34": "Opdater stamdata forbruger", + "E53": "Måleraflæsning på forespørgsel", + "E56": "Skift af balanceresponsabel part", + "E65": "Kunde indflytning", + "E66": "Kunde fraflytning", + "E67": "Placering af måler", + "E75": "Skift af afmålingsmetode", + "E79": "Skift af tilslutningsstatus", + "E80": "Ændring af estimeret årligt volumen", + "E84": "Opdater stamdata måler" + }, "search": { "topBarTitle": "Fremsøg forretningsbesked", "documentType": "Dokumenttype", @@ -675,11 +785,30 @@ "columns": { "code": "Netområde", "actor": "Netvirksomhed", - "organization": "Organisation" + "organization": "Organisation", + "status": "Status", + "type": "Type" }, "priceAreaCodes": { "Dk1": "DK1", "Dk2": "DK2" + }, + "areaTypePlaceholder": "Vælg type", + "status": { + "Created": "Oprettet", + "Active": "Aktiv", + "Expired": "Udløbet", + "Archived": "Arkiveret" + }, + "types": { + "NotSet": "Ikke angivet", + "Transmission": "Transmission", + "Distribution": "Distribution", + "Other": "Andet", + "Test": "Test", + "GridLossDK": "Nettab DK", + "GridLossAbroad": "Nettab udland", + "Aboard": "Udland" } } }, @@ -1155,6 +1284,7 @@ }, "requestReportModal": { "title": "{{ wholesale.settlementReports.requestSettlementReport }}", + "requestAs": "Anmod som", "calculationType": "Beregningstype", "includeBasisData": "Inkluder datagrundlag", "allowLargeTextFiles": "Tillad store filer", @@ -1167,6 +1297,7 @@ "combineResultsInOneFile": "Kombiner resultater i en fil", "cancel": "Fortryd", "confirm": "{{ wholesale.settlementReports.requestSettlementReport }}", + "continue": "Næste", "startDateIsBeforeMinDate": "Startdatoen kan ikke være ældre end 3,6 år + løbende måned", "requestSuccess": "Afregningsrapport bestilt.", "requestError": "Noget gik galt. Afregningsrapporten blev ikke bestilt. Prøv igen." diff --git a/libs/dh/globalization/assets-localization/src/assets/i18n/en.json b/libs/dh/globalization/assets-localization/src/assets/i18n/en.json index 3204d2d2fe..0457dd9780 100644 --- a/libs/dh/globalization/assets-localization/src/assets/i18n/en.json +++ b/libs/dh/globalization/assets-localization/src/assets/i18n/en.json @@ -50,6 +50,21 @@ "title": "No results found", "message": "Try changing the search criteria" }, + "data": { + "default": { + "title": "Start search", + "text": "Your results will appear here" + }, + "error": { + "title": "An unexpected error occured", + "text": "Unfortunately, an error occurred while retrieving the necessary information", + "button": "Try again" + }, + "empty": { + "title": "No results found", + "text": "Try changing the search criteria" + } + }, "navigation": { "next": "Next", "previous": "Previous" @@ -128,7 +143,10 @@ } }, "messageArchive": { - "unknowenError": "Unknown error", + "topBarTitle": "Search in request and response messages", + "new": "New search", + "results": "Results", + "searchById": "Search by ID", "drawer": { "message": "Message", "receiver": "Receiver", @@ -140,6 +158,98 @@ "document": { "loadFailed": "Failed to load document" }, + "columns": { + "messageId": "Message ID", + "documentType": "Document type", + "sender": "Sender", + "receiver": "Receiver", + "createdAt": "Date and time" + }, + "start": { + "title": "New search", + "placeholder": "Type or choose", + "documentType": "Document type", + "businessReason": "Business reason", + "sender": "Sender", + "receiver": "Receiver", + "start": "Start time", + "end": "End time", + "cancel": "Clear search", + "confirm": "Search" + }, + "details": { + "created": "Sent", + "messageId": "Message ID", + "receiver": "Receiver", + "sender": "Sender", + "download": "Download" + }, + "businessReason": { + "D02": "Preparation for imbalance settlement", + "D03": "Temporary", + "D04": "1st settlement", + "D05": "2nd settlement", + "D06": "Continuous meter reading from profiled metering points", + "D07": "Rollback Change-of-supplier", + "D09": "Latest available value", + "D10": "Meter reading, filed consumption", + "D11": "Incorrect process", + "D12": "Cancel meter reading request", + "D13": "Change of supply to supplier of last resort", + "D14": "Close down metering point", + "D15": "Connect meteringpoint", + "D16": "Merge of Grids", + "D17": "Update masterdata settlement", + "D18": "Update charge information", + "D19": "Meter Reading", + "D20": "Electrical heating", + "D21": "Move-in due to other reason", + "D22": "Service request", + "D23": "Not used", + "D24": "Missing flex meter reading", + "D25": "Missing non-profiled time series", + "D26": "Missing flex time series", + "D27": "Missing profiled reading", + "D28": "Proposal contact information", + "D29": "Secondary move-in", + "D30": "Switch with short notice", + "D31": "Transfer metering point", + "D32": "Correction settlement", + "D33": "Incorrect move", + "D34": "End supply due to reallocate", + "D35": "Continue supply due to rejected reallocate", + "D36": "Continue supply of customer", + "D37": "Cancel service request", + "D38": "End of supply with short notice", + "D39": "Production Obligation", + "D40": "Removed parent relation on meteringpoint", + "D41": "No disconnection of meteringpoint", + "D43": "Historical information about consumption", + "D44": "Process cancelled by requesting party", + "D45": "Process cancelled by ITX", + "D46": "Date of Supplier change caused by End of supply", + "D47": "Reminder", + "E01": "Move", + "E02": "New metering point", + "E03": "Change of balance supplier", + "E05": "Cancellation", + "E06": "Unrequested change of balance supplier", + "E0G": "Data alignment for master data metering point", + "E20": "End of supply", + "E23": "Periodic metering", + "E30": "Historical data", + "E32": "Update master data metering point", + "E34": "Update master data consumer", + "E53": "Meter reading on demand", + "E56": "Change of Balance Responsible Party", + "E65": "Customer move-in", + "E66": "Customer move-out", + "E67": "Placement of Meter", + "E75": "Change of metering method", + "E79": "Change Connection Status", + "E80": "Change of estimated annual volume", + "E84": "Update master data meter" + }, "search": { "topBarTitle": "Search in request and response messages", "documentType": "Document type", @@ -676,11 +786,30 @@ "columns": { "code": "Grid area", "actor": "Grid access provider", - "organization": "Organisation" + "organization": "Organisation", + "status": "Status", + "type": "Type" }, "priceAreaCodes": { "Dk1": "DK1", "Dk2": "DK2" + }, + "areaTypePlaceholder": "Choose type", + "status": { + "Created": "Created", + "Active": "Active", + "Expired": "Expired", + "Archived": "Archived" + }, + "types": { + "NotSet": "Not specified", + "Transmission": "Transmission", + "Distribution": "Distribution", + "Other": "Other", + "Test": "Test", + "GridLossDK": "Grid loss DK", + "GridLossAbroad": "Grid loss abroad", + "Aboard": "Abroad" } } }, @@ -1156,6 +1285,7 @@ }, "requestReportModal": { "title": "{{ wholesale.settlementReports.requestSettlementReport }}", + "requestAs": "Request as", "calculationType": "Calculation type", "includeBasisData": "Include basis data", "allowLargeTextFiles": "Allow large files", @@ -1167,6 +1297,7 @@ "gridAreaHint": "{{ count }} selected", "combineResultsInOneFile": "Combine results in one file", "cancel": "Cancel", + "continue": "Next", "confirm": "{{ wholesale.settlementReports.requestSettlementReport }}", "startDateIsBeforeMinDate": "Start date cannot be older than 3,6 years + the current month", "requestSuccess": "Settlement report has been requested.", diff --git a/libs/dh/globalization/configuration-watt-translation/src/lib/dh-watt-translation.providers.ts b/libs/dh/globalization/configuration-watt-translation/src/lib/dh-watt-translation.providers.ts index 546f6a1c49..52e88eef0e 100644 --- a/libs/dh/globalization/configuration-watt-translation/src/lib/dh-watt-translation.providers.ts +++ b/libs/dh/globalization/configuration-watt-translation/src/lib/dh-watt-translation.providers.ts @@ -50,12 +50,14 @@ export class DhDataIntlService extends WattDataIntlService { constructor(transloco: TranslocoService) { super(); - transloco.selectTranslateObject('shared').subscribe((translations) => { + transloco.selectTranslateObject('shared.data').subscribe((translations) => { this.search = translations.search; this.emptyTitle = translations.empty.title; - this.emptyMessage = translations.empty.message; + this.emptyText = translations.empty.text; this.errorTitle = translations.error.title; - this.errorMessage = translations.error.message; + this.errorText = translations.error.text; + this.defaultTitle = translations.default.title; + this.defaultText = translations.default.text; this.changes.next(); }); } diff --git a/libs/dh/imbalance-prices/data-access-graphql/project.json b/libs/dh/imbalance-prices/data-access-graphql/project.json index 6880042358..bcb2573523 100644 --- a/libs/dh/imbalance-prices/data-access-graphql/project.json +++ b/libs/dh/imbalance-prices/data-access-graphql/project.json @@ -5,6 +5,7 @@ "sourceRoot": "libs/dh/imbalance-prices/data-access-graphql", "prefix": "dh", "tags": ["product:dh", "domain:imbalance-prices", "type:data-access"], + "implicitDependencies": ["api-dh"], "targets": { "lint": { "executor": "@nx/eslint:lint" diff --git a/libs/dh/market-participant/actors/data-access-graphql/project.json b/libs/dh/market-participant/actors/data-access-graphql/project.json index 0e56a37c6f..a2a064b082 100644 --- a/libs/dh/market-participant/actors/data-access-graphql/project.json +++ b/libs/dh/market-participant/actors/data-access-graphql/project.json @@ -5,6 +5,7 @@ "sourceRoot": "libs/dh/market-participant/actors/data-access-graphql", "prefix": "dh", "tags": ["product:dh", "domain:market-participant", "type:data-access"], + "implicitDependencies": ["api-dh"], "targets": { "lint": { "executor": "@nx/eslint:lint" diff --git a/libs/dh/market-participant/data-access-graphql/project.json b/libs/dh/market-participant/data-access-graphql/project.json index 8fdd7bbbdb..dfb5a248f7 100644 --- a/libs/dh/market-participant/data-access-graphql/project.json +++ b/libs/dh/market-participant/data-access-graphql/project.json @@ -5,6 +5,7 @@ "sourceRoot": "libs/dh/market-participant/data-access-graphql", "prefix": "dh", "tags": ["product:dh", "domain:market-participant", "type:data-access"], + "implicitDependencies": ["api-dh"], "targets": { "lint": { "executor": "@nx/eslint:lint" diff --git a/libs/dh/market-participant/data-access-graphql/query/get-grid-area-overview.graphql b/libs/dh/market-participant/data-access-graphql/query/get-grid-area-overview.graphql index dc95984a5a..0c3ac55db9 100644 --- a/libs/dh/market-participant/data-access-graphql/query/get-grid-area-overview.graphql +++ b/libs/dh/market-participant/data-access-graphql/query/get-grid-area-overview.graphql @@ -9,6 +9,8 @@ query GetGridAreaOverview { actorNumber actorName organizationName + type fullFlexDate + status } } diff --git a/libs/dh/market-participant/grid-areas/overview/src/lib/dh-grid-area-status-badge.component.ts b/libs/dh/market-participant/grid-areas/overview/src/lib/dh-grid-area-status-badge.component.ts new file mode 100644 index 0000000000..e6d20d3848 --- /dev/null +++ b/libs/dh/market-participant/grid-areas/overview/src/lib/dh-grid-area-status-badge.component.ts @@ -0,0 +1,53 @@ +/** + * @license + * Copyright 2020 Energinet DataHub A/S + * + * Licensed under the Apache License, Version 2.0 (the "License2"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ChangeDetectionStrategy, Component, input } from '@angular/core'; +import { TranslocoDirective } from '@ngneat/transloco'; + +import { WattBadgeComponent } from '@energinet-datahub/watt/badge'; +import { GridAreaStatus } from '@energinet-datahub/dh/shared/domain/graphql'; +import { DhEmDashFallbackPipe } from '@energinet-datahub/dh/shared/ui-util'; + +@Component({ + standalone: true, + selector: 'dh-gridarea-status-badge', + template: ` + + @switch (status()) { + @case ('Created') { + {{ t('Created') }} + } + @case ('Active') { + {{ t('Active') }} + } + @case ('Expired') { + {{ t('Expired') }} + } + @case ('Archived') { + {{ t('Archived') }} + } + @default { + {{ status() | dhEmDashFallback }} + } + } + + `, + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [TranslocoDirective, WattBadgeComponent, DhEmDashFallbackPipe], +}) +export class DhGridAreaStatusBadgeComponent { + status = input.required(); +} diff --git a/libs/dh/market-participant/grid-areas/overview/src/lib/dh-market-participant-gridarea-overview.component.html b/libs/dh/market-participant/grid-areas/overview/src/lib/dh-market-participant-gridarea-overview.component.html index 8dd5618fd4..ee84a94691 100644 --- a/libs/dh/market-participant/grid-areas/overview/src/lib/dh-market-participant-gridarea-overview.component.html +++ b/libs/dh/market-participant/grid-areas/overview/src/lib/dh-market-participant-gridarea-overview.component.html @@ -15,8 +15,8 @@ limitations under the License. --> - - + +

{{ t("topBarTitle") }}

{{ dataSource.data.length }} @@ -29,22 +29,54 @@

{{ t("topBarTitle") }}

}}
+ + + + > + + {{ gridArea.code }} + + + + {{ gridArea.actor }} + + + + {{ gridArea.organization }} + + + + {{ t("types." + gridArea.type) }} + + + + + + @if (!isLoading() && (hasError() || dataSource.data.length === 0)) { - + + + } diff --git a/libs/dh/market-participant/grid-areas/overview/src/lib/dh-market-participant-gridarea-overview.component.ts b/libs/dh/market-participant/grid-areas/overview/src/lib/dh-market-participant-gridarea-overview.component.ts index d84e3ee1bf..1fd1846e5d 100644 --- a/libs/dh/market-participant/grid-areas/overview/src/lib/dh-market-participant-gridarea-overview.component.ts +++ b/libs/dh/market-participant/grid-areas/overview/src/lib/dh-market-participant-gridarea-overview.component.ts @@ -14,28 +14,43 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, effect, input } from '@angular/core'; +import { FormsModule } from '@angular/forms'; +import { Component, effect, input, signal } from '@angular/core'; import { TranslocoDirective, TranslocoPipe, translate } from '@ngneat/transloco'; -import { WATT_CARD } from '@energinet-datahub/watt/card'; -import { WattSearchComponent } from '@energinet-datahub/watt/search'; -import { WattButtonComponent } from '@energinet-datahub/watt/button'; import { VaterFlexComponent, VaterSpacerComponent, VaterStackComponent, VaterUtilityDirective, } from '@energinet-datahub/watt/vater'; + import { WATT_TABLE, WattTableColumnDef, WattTableDataSource } from '@energinet-datahub/watt/table'; -import { DhEmDashFallbackPipe, exportToCSV } from '@energinet-datahub/dh/shared/ui-util'; + +import { + DhDropdownTranslatorDirective, + DhEmDashFallbackPipe, + dhEnumToWattDropdownOptions, + exportToCSV, +} from '@energinet-datahub/dh/shared/ui-util'; + +import { WATT_CARD } from '@energinet-datahub/watt/card'; import { WattDatePipe } from '@energinet-datahub/watt/date'; +import { WattSearchComponent } from '@energinet-datahub/watt/search'; +import { WattButtonComponent } from '@energinet-datahub/watt/button'; +import { WattDropdownComponent } from '@energinet-datahub/watt/dropdown'; import { WattPaginatorComponent } from '@energinet-datahub/watt/paginator'; import { WattEmptyStateComponent } from '@energinet-datahub/watt/empty-state'; +import { GridAreaStatus, GridAreaType } from '@energinet-datahub/dh/shared/domain/graphql'; + +import { DhGridAreaStatusBadgeComponent } from './dh-grid-area-status-badge.component'; export interface GridAreaOverviewRow { code: string; actor: string; organization: string; + status: GridAreaStatus; + type: GridAreaType; } @Component({ @@ -58,23 +73,28 @@ export interface GridAreaOverviewRow { `, ], imports: [ - TranslocoDirective, + FormsModule, + TranslocoPipe, + TranslocoDirective, WATT_CARD, WATT_TABLE, + WattDatePipe, + WattButtonComponent, + WattSearchComponent, + WattDropdownComponent, WattPaginatorComponent, + WattEmptyStateComponent, + VaterFlexComponent, - VaterSpacerComponent, VaterStackComponent, + VaterSpacerComponent, VaterUtilityDirective, - WattEmptyStateComponent, - WattSearchComponent, - WattButtonComponent, - WattButtonComponent, - WattDatePipe, DhEmDashFallbackPipe, + DhDropdownTranslatorDirective, + DhGridAreaStatusBadgeComponent, ], }) export class DhMarketParticipantGridAreaOverviewComponent { @@ -82,17 +102,25 @@ export class DhMarketParticipantGridAreaOverviewComponent { code: { accessor: 'code' }, actor: { accessor: 'actor' }, organization: { accessor: 'organization' }, + type: { accessor: 'type' }, + status: { accessor: 'status' }, }; gridAreas = input([]); isLoading = input(false); hasError = input(false); + gridAreaTypeOptions = dhEnumToWattDropdownOptions(GridAreaType, 'asc', [GridAreaType.NotSet]); + + selectedGridAreaType = signal(null); + readonly dataSource = new WattTableDataSource(); constructor() { effect(() => { - this.dataSource.data = this.gridAreas(); + this.dataSource.data = this.gridAreas()?.filter( + (x) => x.type === this.selectedGridAreaType() || this.selectedGridAreaType() === null + ); }); } @@ -109,16 +137,23 @@ export class DhMarketParticipantGridAreaOverviewComponent { const columnsPath = 'marketParticipant.gridAreas.columns'; + const statusPath = 'marketParticipant.gridAreas.status'; + const typesPath = 'marketParticipant.gridAreas.types'; + const headers = [ `"${translate(columnsPath + '.code')}"`, `"${translate(columnsPath + '.actor')}"`, `"${translate(columnsPath + '.organization')}"`, + `"${translate(columnsPath + '.type')}"`, + `"${translate(columnsPath + '.status')}"`, ]; const lines = dataSorted.map((gridArea) => [ `"${gridArea.code}"`, `"${gridArea.actor}"`, `"${gridArea.organization}"`, + `"${translate(typesPath + '.' + gridArea.type)}"`, + `"${translate(statusPath + '.' + gridArea.status)}"`, ]); exportToCSV({ headers, lines, fileName: 'grid-areas' }); diff --git a/libs/dh/market-participant/grid-areas/shell/src/lib/dh-grid-areas-shell.component.html b/libs/dh/market-participant/grid-areas/shell/src/lib/dh-grid-areas-shell.component.html index 0f91cf10a8..871be31aed 100644 --- a/libs/dh/market-participant/grid-areas/shell/src/lib/dh-grid-areas-shell.component.html +++ b/libs/dh/market-participant/grid-areas/shell/src/lib/dh-grid-areas-shell.component.html @@ -14,8 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. --> + diff --git a/libs/dh/market-participant/grid-areas/shell/src/lib/dh-grid-areas-shell.component.ts b/libs/dh/market-participant/grid-areas/shell/src/lib/dh-grid-areas-shell.component.ts index 4daf0701b8..fa2f2451d9 100644 --- a/libs/dh/market-participant/grid-areas/shell/src/lib/dh-grid-areas-shell.component.ts +++ b/libs/dh/market-participant/grid-areas/shell/src/lib/dh-grid-areas-shell.component.ts @@ -14,45 +14,43 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, inject } from '@angular/core'; +import { Component, computed } from '@angular/core'; + import { - DhMarketParticipantGridAreaOverviewComponent, GridAreaOverviewRow, + DhMarketParticipantGridAreaOverviewComponent, } from '@energinet-datahub/dh/market-participant/grid-areas/overview'; -import { Apollo } from 'apollo-angular'; + +import { query } from '@energinet-datahub/dh/shared/util-apollo'; import { GetGridAreaOverviewDocument } from '@energinet-datahub/dh/shared/domain/graphql'; -import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'dh-grid-areas-shell', + styles: ` + :host { + display: block; + } + `, templateUrl: './dh-grid-areas-shell.component.html', standalone: true, imports: [DhMarketParticipantGridAreaOverviewComponent], }) export class DhGridAreasShellComponent { private readonly gln = new RegExp('^[0-9]+$'); - private readonly apollo = inject(Apollo); - - getActorsQuery$ = this.apollo.watchQuery({ - query: GetGridAreaOverviewDocument, - }); - - isLoading = false; - hasError = false; - rows: GridAreaOverviewRow[] = []; + getActorsQuery = query(GetGridAreaOverviewDocument); - constructor() { - this.getActorsQuery$.valueChanges.pipe(takeUntilDestroyed()).subscribe((result) => { - this.hasError = !!result.error || !!result.errors?.length; - this.isLoading = result.loading; - this.rows = - result.data?.gridAreaOverview?.map((x) => ({ - code: x.code, - actor: x.actorNumber - ? `${x.actorName} • ${this.gln.test(x.actorNumber) ? 'GLN' : 'EIC'} ${x.actorNumber}` - : '', - organization: x.organizationName ?? '', - })) ?? []; - }); - } + isLoading = this.getActorsQuery.loading; + hasError = computed(() => Boolean(this.getActorsQuery.error())); + rows = computed( + () => + this.getActorsQuery.data()?.gridAreaOverview.map((x) => ({ + code: x.code, + actor: x.actorNumber + ? `${x.actorName} • ${this.gln.test(x.actorNumber) ? 'GLN' : 'EIC'} ${x.actorNumber}` + : '', + organization: x.organizationName ?? '', + status: x.status, + type: x.type, + })) ?? [] + ); } diff --git a/libs/dh/message-archive/data-access-graphql/.eslintrc.json b/libs/dh/message-archive/data-access-graphql/.eslintrc.json new file mode 100644 index 0000000000..acdf1d4b4b --- /dev/null +++ b/libs/dh/message-archive/data-access-graphql/.eslintrc.json @@ -0,0 +1,4 @@ +{ + "extends": ["../../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"] +} diff --git a/libs/dh/message-archive/data-access-graphql/project.json b/libs/dh/message-archive/data-access-graphql/project.json new file mode 100644 index 0000000000..bc8496a23a --- /dev/null +++ b/libs/dh/message-archive/data-access-graphql/project.json @@ -0,0 +1,14 @@ +{ + "name": "dh-message-archive-data-access-graphql", + "$schema": "../../../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/dh/message-archive/data-access-graphql", + "prefix": "dh", + "tags": ["product:dh", "domain:message-archive", "type:data-access"], + "implicitDependencies": ["api-dh"], + "targets": { + "lint": { + "executor": "@nx/eslint:lint" + } + } +} diff --git a/libs/dh/message-archive/data-access-graphql/query/get-archived-messages.graphql b/libs/dh/message-archive/data-access-graphql/query/get-archived-messages.graphql new file mode 100644 index 0000000000..ad207f6b38 --- /dev/null +++ b/libs/dh/message-archive/data-access-graphql/query/get-archived-messages.graphql @@ -0,0 +1,52 @@ +query GetArchivedMessages( + $created: DateRange! + $senderNumber: String + $receiverNumber: String + $documentTypes: [DocumentType!] + $businessReasons: [BusinessReason!] + $first: Int + $last: Int + $after: String + $before: String + $order: [ArchivedMessageSortInput!] + $filter: String +) { + archivedMessages( + created: $created + senderNumber: $senderNumber + receiverNumber: $receiverNumber + documentTypes: $documentTypes + businessReasons: $businessReasons + first: $first + last: $last + after: $after + before: $before + order: $order + filter: $filter + ) { + totalCount + pageInfo { + startCursor + endCursor + } + nodes { + id + messageId + documentType + documentUrl + sender { + id + displayName + glnOrEicNumber + } + receiver { + id + displayName + glnOrEicNumber + } + createdAt + businessReason + businessTransaction + } + } +} diff --git a/libs/dh/message-archive/domain/src/index.ts b/libs/dh/message-archive/domain/src/index.ts index 841840fd69..9d188707bc 100644 --- a/libs/dh/message-archive/domain/src/index.ts +++ b/libs/dh/message-archive/domain/src/index.ts @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +export * from './lib/archivedMessage'; export * from './lib/businessReasons'; export * from './lib/documentTypes'; export * from './lib/roleTypes'; diff --git a/libs/dh/message-archive/domain/src/lib/archivedMessage.ts b/libs/dh/message-archive/domain/src/lib/archivedMessage.ts new file mode 100644 index 0000000000..4e72876a31 --- /dev/null +++ b/libs/dh/message-archive/domain/src/lib/archivedMessage.ts @@ -0,0 +1,22 @@ +/** + * @license + * Copyright 2020 Energinet DataHub A/S + * + * Licensed under the Apache License, Version 2.0 (the "License2"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import type { ResultOf } from '@graphql-typed-document-node/core'; +import type { GetArchivedMessagesDocument } from '@energinet-datahub/dh/shared/domain/graphql'; + +export type ArchivedMessage = NonNullable< + NonNullable['archivedMessages']>['nodes'] +>[number]; diff --git a/libs/dh/message-archive/feature-search/.eslintrc.json b/libs/dh/message-archive/feature-search/.eslintrc.json new file mode 100644 index 0000000000..5d569f2f2f --- /dev/null +++ b/libs/dh/message-archive/feature-search/.eslintrc.json @@ -0,0 +1,36 @@ +{ + "extends": ["../../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "dh", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "dh", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/libs/dh/message-archive/feature-search/README.md b/libs/dh/message-archive/feature-search/README.md new file mode 100644 index 0000000000..e8359e972d --- /dev/null +++ b/libs/dh/message-archive/feature-search/README.md @@ -0,0 +1 @@ +# Search Feature diff --git a/libs/dh/message-archive/feature-search/jest.config.ts b/libs/dh/message-archive/feature-search/jest.config.ts new file mode 100644 index 0000000000..ec80ced2ac --- /dev/null +++ b/libs/dh/message-archive/feature-search/jest.config.ts @@ -0,0 +1,38 @@ +/** + * @license + * Copyright 2020 Energinet DataHub A/S + * + * Licensed under the Apache License, Version 2.0 (the "License2"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* eslint-disable */ +export default { + displayName: 'dh-message-archive-feature-search', + preset: '../../../../jest.preset.js', + setupFilesAfterEnv: ['/src/test-setup.ts'], + coverageDirectory: '../../../../coverage/libs/dh/message-archive/feature-search', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], +}; diff --git a/libs/dh/message-archive/feature-search/project.json b/libs/dh/message-archive/feature-search/project.json new file mode 100644 index 0000000000..f43e5e75c7 --- /dev/null +++ b/libs/dh/message-archive/feature-search/project.json @@ -0,0 +1,20 @@ +{ + "name": "dh-message-archive-feature-search", + "$schema": "../../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/dh/message-archive/feature-search/src", + "prefix": "dh", + "projectType": "library", + "tags": ["product:dh", "domain:message-archive", "type:feature"], + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], + "options": { + "jestConfig": "libs/dh/message-archive/feature-search/jest.config.ts" + } + }, + "lint": { + "executor": "@nx/eslint:lint" + } + } +} diff --git a/libs/dh/message-archive/feature-search/src/index.ts b/libs/dh/message-archive/feature-search/src/index.ts new file mode 100644 index 0000000000..e0bee7c9a5 --- /dev/null +++ b/libs/dh/message-archive/feature-search/src/index.ts @@ -0,0 +1,17 @@ +/** + * @license + * Copyright 2020 Energinet DataHub A/S + * + * Licensed under the Apache License, Version 2.0 (the "License2"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './lib/page.component'; diff --git a/libs/dh/message-archive/feature-search/src/lib/details.component.ts b/libs/dh/message-archive/feature-search/src/lib/details.component.ts new file mode 100644 index 0000000000..9fab4018f4 --- /dev/null +++ b/libs/dh/message-archive/feature-search/src/lib/details.component.ts @@ -0,0 +1,133 @@ +/** + * @license + * Copyright 2020 Energinet DataHub A/S + * + * Licensed under the Apache License, Version 2.0 (the "License2"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { HttpClient } from '@angular/common/http'; +import { Component, computed, inject, output, signal, viewChild } from '@angular/core'; +import { TranslocoDirective } from '@ngneat/transloco'; +import { map, startWith, switchMap, tap } from 'rxjs'; + +import { VaterFlexComponent, VaterUtilityDirective } from '@energinet-datahub/watt/vater'; +import { WattButtonComponent } from '@energinet-datahub/watt/button'; +import { WattCodeComponent } from '@energinet-datahub/watt/code'; +import { WattDatePipe } from '@energinet-datahub/watt/date'; +import { + WattDescriptionListComponent, + WattDescriptionListItemComponent, +} from '@energinet-datahub/watt/description-list'; +import { WATT_DRAWER, WattDrawerComponent } from '@energinet-datahub/watt/drawer'; +import { WattSpinnerComponent } from '@energinet-datahub/watt/spinner'; + +import { DhEmDashFallbackPipe, streamToFile } from '@energinet-datahub/dh/shared/ui-util'; +import { ArchivedMessage } from '@energinet-datahub/dh/message-archive/domain'; +import { toObservable, toSignal } from '@angular/core/rxjs-interop'; + +@Component({ + selector: 'dh-message-archive-search-details', + standalone: true, + imports: [ + TranslocoDirective, + VaterFlexComponent, + VaterUtilityDirective, + WATT_DRAWER, + WattButtonComponent, + WattCodeComponent, + WattDatePipe, + WattDescriptionListComponent, + WattDescriptionListItemComponent, + WattSpinnerComponent, + DhEmDashFallbackPipe, + ], + template: ` + + +

{{ documentType() }} ({{ businessTransaction() }})

+ + + + + + +
+ + + {{ t('download') }} + + + + @if (loading()) { + + + + } @else { + + } + +
+ `, +}) +export class DhMessageArchiveSearchDetailsComponent { + private httpClient = inject(HttpClient); + + close = output(); + message = signal(null); + loading = signal(true); + + documentChange = toObservable(this.message).pipe( + tap(() => this.loading.set(true)), + map((message) => message?.documentUrl), + switchMap((url) => (!url ? [''] : this.httpClient.get(url, { responseType: 'text' }))), + tap(() => this.loading.set(false)), + startWith('') + ); + + document = toSignal(this.documentChange, { requireSync: true }); + + businessTransaction = computed(() => this.message()?.businessTransaction); + messageId = computed(() => this.message()?.messageId); + documentType = computed(() => this.message()?.documentType); + createdAt = computed(() => this.message()?.createdAt); + sender = computed(() => this.message()?.sender?.displayName); + receiver = computed(() => this.message()?.receiver?.displayName); + + drawer = viewChild(WattDrawerComponent); + + download = () => { + // TODO: Consider using .json or .xml based on the document type + const download = streamToFile({ name: `${this.messageId()}.txt`, type: '' }); + download(this.document()).subscribe(); + }; + + open = (message: ArchivedMessage) => { + this.message.set(message); + this.drawer()?.open(); + }; + + onClose = () => { + this.message.set(null); + this.drawer()?.close(); + this.close.emit(); + }; +} diff --git a/libs/dh/message-archive/feature-search/src/lib/form/start.ts b/libs/dh/message-archive/feature-search/src/lib/form/start.ts new file mode 100644 index 0000000000..7baa0de253 --- /dev/null +++ b/libs/dh/message-archive/feature-search/src/lib/form/start.ts @@ -0,0 +1,38 @@ +/** + * @license + * Copyright 2020 Energinet DataHub A/S + * + * Licensed under the Apache License, Version 2.0 (the "License2"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { FormGroup } from '@angular/forms'; +import dayjs from 'dayjs'; +import { DocumentType, BusinessReason } from '@energinet-datahub/dh/shared/domain/graphql'; +import { dhMakeFormControl } from '@energinet-datahub/dh/shared/ui-util'; + +const documentTypes = dhMakeFormControl(); +const businessReasons = dhMakeFormControl(); +const senderNumber = dhMakeFormControl(); +const receiverNumber = dhMakeFormControl(); +const start = dhMakeFormControl(dayjs().startOf('day').toDate()); +const end = dhMakeFormControl(dayjs().endOf('day').toDate()); + +export const form = new FormGroup({ + documentTypes, + businessReasons, + senderNumber, + receiverNumber, + start, + end, +}); + +export type FormValues = ReturnType; diff --git a/libs/dh/message-archive/feature-search/src/lib/page.component.ts b/libs/dh/message-archive/feature-search/src/lib/page.component.ts new file mode 100644 index 0000000000..c3223450b4 --- /dev/null +++ b/libs/dh/message-archive/feature-search/src/lib/page.component.ts @@ -0,0 +1,37 @@ +/** + * @license + * Copyright 2020 Energinet DataHub A/S + * + * Licensed under the Apache License, Version 2.0 (the "License2"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Component } from '@angular/core'; + +import { DhMessageArchiveSearchDetailsComponent } from './details.component'; +import { DhMessageArchiveSearchStartComponent } from './start.component'; +import { DhMessageArchiveSearchTableComponent } from './table.component'; + +@Component({ + selector: 'dh-message-archive-search-page', + standalone: true, + imports: [ + DhMessageArchiveSearchDetailsComponent, + DhMessageArchiveSearchStartComponent, + DhMessageArchiveSearchTableComponent, + ], + template: ` + + + + `, +}) +export class DhMessageArchiveSearchPageComponent {} diff --git a/libs/dh/message-archive/feature-search/src/lib/start.component.ts b/libs/dh/message-archive/feature-search/src/lib/start.component.ts new file mode 100644 index 0000000000..9fed6b143d --- /dev/null +++ b/libs/dh/message-archive/feature-search/src/lib/start.component.ts @@ -0,0 +1,143 @@ +/** + * @license + * Copyright 2020 Energinet DataHub A/S + * + * Licensed under the Apache License, Version 2.0 (the "License2"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Component, computed, output, viewChild } from '@angular/core'; +import { ReactiveFormsModule } from '@angular/forms'; +import { TranslocoDirective } from '@ngneat/transloco'; + +import { VaterStackComponent } from '@energinet-datahub/watt/vater'; +import { WattButtonComponent } from '@energinet-datahub/watt/button'; +import { WattDatetimepickerComponent } from '@energinet-datahub/watt/datetimepicker'; +import { WattDropdownComponent } from '@energinet-datahub/watt/dropdown'; +import { WattModalActionsComponent, WattModalComponent } from '@energinet-datahub/watt/modal'; + +import { + DhDropdownTranslatorDirective, + dhEnumToWattDropdownOptions, +} from '@energinet-datahub/dh/shared/ui-util'; +import { query } from '@energinet-datahub/dh/shared/util-apollo'; +import { + BusinessReason, + DocumentType, + GetActorsDocument, + GetArchivedMessagesQueryVariables, +} from '@energinet-datahub/dh/shared/domain/graphql'; + +import { form } from './form/start'; + +@Component({ + selector: 'dh-message-archive-search-start', + standalone: true, + imports: [ + ReactiveFormsModule, + TranslocoDirective, + VaterStackComponent, + WattButtonComponent, + WattDatetimepickerComponent, + WattDropdownComponent, + WattModalActionsComponent, + WattModalComponent, + DhDropdownTranslatorDirective, + ], + template: ` + +
+ + + + + + + + + + {{ t('cancel') }} + + + {{ t('confirm') }} + + +
+ `, +}) +export class DhMessageArchiveSearchStartComponent { + form = form; + + start = output(); + clear = output(); + modal = viewChild.required('modal'); + + documentTypeOptions = dhEnumToWattDropdownOptions(DocumentType); + businessReasonOptions = dhEnumToWattDropdownOptions(BusinessReason); + + actorsQuery = query(GetActorsDocument); + actors = computed(() => this.actorsQuery.data()?.actors ?? []); + actorOptions = computed(() => + this.actors().map((actor) => ({ + value: actor.glnOrEicNumber, + displayValue: actor.name || actor.glnOrEicNumber, + })) + ); + + open = () => this.modal().open(); + onSubmit = () => { + const values = this.form.getRawValue(); + if (!values || !values.start) return; + const { start, end, ...variables } = values; + this.start.emit({ ...variables, created: { start, end } }); + }; +} diff --git a/libs/dh/message-archive/feature-search/src/lib/table.component.ts b/libs/dh/message-archive/feature-search/src/lib/table.component.ts new file mode 100644 index 0000000000..5c78122b4a --- /dev/null +++ b/libs/dh/message-archive/feature-search/src/lib/table.component.ts @@ -0,0 +1,128 @@ +/** + * @license + * Copyright 2020 Energinet DataHub A/S + * + * Licensed under the Apache License, Version 2.0 (the "License2"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Component, output, signal } from '@angular/core'; +import { TranslocoDirective } from '@ngneat/transloco'; + +import { VaterUtilityDirective } from '@energinet-datahub/watt/vater'; +import { WattButtonComponent } from '@energinet-datahub/watt/button'; +import { WattDataTableComponent } from '@energinet-datahub/watt/data'; +import { WattDatePipe } from '@energinet-datahub/watt/date'; +import { WattEmptyStateComponent } from '@energinet-datahub/watt/empty-state'; +import { WattTableColumnDef, WATT_TABLE } from '@energinet-datahub/watt/table'; + +import { + GetArchivedMessagesQueryVariables, + SortEnumType, +} from '@energinet-datahub/dh/shared/domain/graphql'; +import { GetArchivedMessagesDataSource } from '@energinet-datahub/dh/shared/domain/graphql/data-source'; +import { ArchivedMessage } from '@energinet-datahub/dh/message-archive/domain'; + +@Component({ + selector: 'dh-message-archive-search-table', + standalone: true, + imports: [ + TranslocoDirective, + VaterUtilityDirective, + WATT_TABLE, + WattButtonComponent, + WattDataTableComponent, + WattDatePipe, + WattEmptyStateComponent, + ], + template: ` + +

{{ t('results') }}

+ + {{ t('new') }} + + + +
+ {{ row.businessTransaction }} +
+ {{ row.documentType }} +
+
+ +
+ {{ row.sender?.displayName }} +
+ {{ row.sender?.glnOrEicNumber }} +
+
+ +
+ {{ row.receiver?.displayName }} +
+ {{ row.receiver?.glnOrEicNumber }} +
+
+ + {{ row.createdAt | wattDate: 'long' }} + +
+
+ `, +}) +export class DhMessageArchiveSearchTableComponent { + new = output(); + select = output(); + selection = signal(undefined); + + columns: WattTableColumnDef = { + messageId: { accessor: 'messageId' }, + documentType: { accessor: 'documentType' }, + sender: { accessor: (m) => m.sender?.displayName }, + receiver: { accessor: (m) => m.receiver?.displayName }, + createdAt: { accessor: 'createdAt' }, + }; + + dataSource = new GetArchivedMessagesDataSource({ + skip: true, + variables: { + created: { start: new Date(), end: new Date() }, + order: { createdAt: SortEnumType.Desc }, + }, + }); + + fetch = (variables: GetArchivedMessagesQueryVariables) => this.dataSource.refetch(variables); + reset = () => this.dataSource.reset(); + clearSelection = () => this.selection.set(undefined); + + onRowClick = (row: ArchivedMessage) => { + this.selection.set(row); + this.select.emit(row); + }; +} diff --git a/libs/dh/message-archive/feature-search/src/test-setup.ts b/libs/dh/message-archive/feature-search/src/test-setup.ts new file mode 100644 index 0000000000..919d6d7569 --- /dev/null +++ b/libs/dh/message-archive/feature-search/src/test-setup.ts @@ -0,0 +1,28 @@ +/** + * @license + * Copyright 2020 Energinet DataHub A/S + * + * Licensed under the Apache License, Version 2.0 (the "License2"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import 'jest-preset-angular/setup-jest'; + +import { setUpTestbed, setUpAngularTestingLibrary } from '@energinet-datahub/gf/test-util-staging'; +import { addDomMatchers } from '@energinet-datahub/gf/test-util-matchers'; +import { setupMSWServer } from '@energinet-datahub/gf/test-util-msw'; +import { dhLocalApiEnvironment } from '@energinet-datahub/dh/shared/assets'; +import { mocks } from '@energinet-datahub/dh/shared/data-access-mocks'; + +setupMSWServer(dhLocalApiEnvironment.apiBase, mocks); +addDomMatchers(); +setUpTestbed(); +setUpAngularTestingLibrary(); diff --git a/libs/dh/message-archive/feature-search/tsconfig.json b/libs/dh/message-archive/feature-search/tsconfig.json new file mode 100644 index 0000000000..b9e5be0863 --- /dev/null +++ b/libs/dh/message-archive/feature-search/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "es2022", + "useDefineForClassFields": false, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/libs/dh/message-archive/feature-search/tsconfig.lib.json b/libs/dh/message-archive/feature-search/tsconfig.lib.json new file mode 100644 index 0000000000..9127387056 --- /dev/null +++ b/libs/dh/message-archive/feature-search/tsconfig.lib.json @@ -0,0 +1,17 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": [ + "src/**/*.spec.ts", + "src/test-setup.ts", + "jest.config.ts", + "src/**/*.test.ts" + ], + "include": ["src/**/*.ts"] +} diff --git a/libs/dh/message-archive/feature-search/tsconfig.spec.json b/libs/dh/message-archive/feature-search/tsconfig.spec.json new file mode 100644 index 0000000000..6e5925e5c4 --- /dev/null +++ b/libs/dh/message-archive/feature-search/tsconfig.spec.json @@ -0,0 +1,16 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../../dist/out-tsc", + "module": "commonjs", + "target": "es2016", + "types": ["jest", "node"] + }, + "files": ["src/test-setup.ts"], + "include": [ + "jest.config.ts", + "src/**/*.test.ts", + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +} diff --git a/libs/dh/message-archive/shell/src/lib/dh-message-archive-shell.routes.ts b/libs/dh/message-archive/shell/src/lib/dh-message-archive-shell.routes.ts index 5e239a87bb..34166512df 100644 --- a/libs/dh/message-archive/shell/src/lib/dh-message-archive-shell.routes.ts +++ b/libs/dh/message-archive/shell/src/lib/dh-message-archive-shell.routes.ts @@ -14,17 +14,31 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { inject } from '@angular/core'; import { Routes } from '@angular/router'; +import { DhFeatureFlagsService } from '@energinet-datahub/dh/shared/feature-flags'; import { DhMessageArchiveLogSearchComponent } from '@energinet-datahub/dh/message-archive/feature-log-search'; export const dhMessageArchiveShellRoutes: Routes = [ + { + path: '', + canMatch: [() => inject(DhFeatureFlagsService).isEnabled('message-archive-v2')], + loadComponent: () => + import('@energinet-datahub/dh/message-archive/feature-search').then( + (m) => m.DhMessageArchiveSearchPageComponent + ), + pathMatch: 'full', + data: { + titleTranslationKey: 'messageArchive.topBarTitle', + }, + }, { path: '', component: DhMessageArchiveLogSearchComponent, pathMatch: 'full', data: { - titleTranslationKey: 'messageArchive.search.topBarTitle', + titleTranslationKey: 'messageArchive.topBarTitle', }, }, ]; diff --git a/libs/dh/profile/data-access-graphql/project.json b/libs/dh/profile/data-access-graphql/project.json index 9cd39d3087..b8b729e303 100644 --- a/libs/dh/profile/data-access-graphql/project.json +++ b/libs/dh/profile/data-access-graphql/project.json @@ -5,6 +5,7 @@ "sourceRoot": "libs/dh/profile/data-access-graphql", "prefix": "dh", "tags": ["product:dh", "domain:profile", "type:data-access"], + "implicitDependencies": ["api-dh"], "targets": { "lint": { "executor": "@nx/eslint:lint" diff --git a/libs/dh/shared/data-access-graphql/project.json b/libs/dh/shared/data-access-graphql/project.json index 77a5535b50..c5dde04872 100644 --- a/libs/dh/shared/data-access-graphql/project.json +++ b/libs/dh/shared/data-access-graphql/project.json @@ -4,6 +4,7 @@ "projectType": "library", "sourceRoot": "libs/dh/shared/data-access-graphql/src", "prefix": "dh", + "implicitDependencies": ["api-dh"], "targets": { "test": { "executor": "@nx/jest:jest", diff --git a/libs/dh/shared/data-access-graphql/src/lib/graphql/get-actors-by-eic-function-for-dropdowns.ts b/libs/dh/shared/data-access-graphql/src/lib/graphql/get-actors-by-eic-function-for-dropdowns.ts index 503b335664..3d16e6457d 100644 --- a/libs/dh/shared/data-access-graphql/src/lib/graphql/get-actors-by-eic-function-for-dropdowns.ts +++ b/libs/dh/shared/data-access-graphql/src/lib/graphql/get-actors-by-eic-function-for-dropdowns.ts @@ -28,7 +28,7 @@ import { exists } from '@energinet-datahub/dh/shared/util-operators'; import { WattDropdownOptions } from '@energinet-datahub/watt/dropdown'; export function getActorOptions( - eicFunctions: [EicFunction], + eicFunctions: EicFunction[], valueType: 'glnOrEicNumber' | 'actorId' = 'glnOrEicNumber' ): Observable { const apollo = inject(Apollo); diff --git a/libs/dh/shared/data-access-mocks/src/lib/data/balance-responsible-agreements.ts b/libs/dh/shared/data-access-mocks/src/lib/data/balance-responsible-agreements.ts index 586ab00a6f..a7bba53784 100644 --- a/libs/dh/shared/data-access-mocks/src/lib/data/balance-responsible-agreements.ts +++ b/libs/dh/shared/data-access-mocks/src/lib/data/balance-responsible-agreements.ts @@ -18,6 +18,8 @@ import { BalanceResponsibilityAgreement, BalanceResponsibilityAgreementStatus, GridAreaDto, + GridAreaStatus, + GridAreaType, MarketParticipantMeteringPointType, PriceAreaCode, } from '@energinet-datahub/dh/shared/domain/graphql'; @@ -32,6 +34,8 @@ const gridArea: GridAreaDto = { validFrom: new Date('2024-03-01T00:00+03:00'), validTo: new Date('2024-03-01T00:00+04:00'), includedInCalculation: true, + status: GridAreaStatus.Active, + type: GridAreaType.Distribution, }; export const balanceResponsibleAgreements: BalanceResponsibilityAgreement[] = [ diff --git a/libs/dh/shared/data-access-mocks/src/lib/data/esett-detailed-exchange-events.ts b/libs/dh/shared/data-access-mocks/src/lib/data/esett-detailed-exchange-events.ts index be92b57f2b..8b7df3142e 100644 --- a/libs/dh/shared/data-access-mocks/src/lib/data/esett-detailed-exchange-events.ts +++ b/libs/dh/shared/data-access-mocks/src/lib/data/esett-detailed-exchange-events.ts @@ -20,6 +20,8 @@ import { EsettOutgoingMessage, EsettTimeSeriesType, PriceAreaCode, + GridAreaType, + GridAreaStatus, } from '@energinet-datahub/dh/shared/domain/graphql'; import dayjs from 'dayjs'; @@ -44,6 +46,8 @@ export const eSettDetailedExchangeEvents: EsettOutgoingMessage[] = [ validTo: null, validFrom: new Date(), includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, calculationType: ExchangeEventCalculationType.Aggregation, documentStatus: DocumentStatus.Accepted, @@ -66,6 +70,8 @@ export const eSettDetailedExchangeEvents: EsettOutgoingMessage[] = [ validTo: null, validFrom: new Date(), includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, calculationType: ExchangeEventCalculationType.Aggregation, documentStatus: DocumentStatus.Rejected, @@ -88,6 +94,8 @@ export const eSettDetailedExchangeEvents: EsettOutgoingMessage[] = [ validTo: null, validFrom: new Date(), includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, calculationType: ExchangeEventCalculationType.Aggregation, documentStatus: DocumentStatus.AwaitingReply, @@ -110,6 +118,8 @@ export const eSettDetailedExchangeEvents: EsettOutgoingMessage[] = [ validTo: null, validFrom: new Date(), includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, calculationType: ExchangeEventCalculationType.BalanceFixing, documentStatus: DocumentStatus.AwaitingReply, diff --git a/libs/dh/shared/data-access-mocks/src/lib/data/esett-exchange-events.ts b/libs/dh/shared/data-access-mocks/src/lib/data/esett-exchange-events.ts index 3167fea5f1..a986e3649e 100644 --- a/libs/dh/shared/data-access-mocks/src/lib/data/esett-exchange-events.ts +++ b/libs/dh/shared/data-access-mocks/src/lib/data/esett-exchange-events.ts @@ -37,6 +37,8 @@ import { ExchangeEventSearchResult, PriceAreaCode, EsettTimeSeriesType, + GridAreaType, + GridAreaStatus, } from '@energinet-datahub/dh/shared/domain/graphql'; export const eSettExchangeEvents: ExchangeEventSearchResult[] = [ @@ -56,6 +58,8 @@ export const eSettExchangeEvents: ExchangeEventSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, calculationType: ExchangeEventCalculationType.Aggregation, gridAreaCodeOut: null, @@ -81,6 +85,8 @@ export const eSettExchangeEvents: ExchangeEventSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, calculationType: ExchangeEventCalculationType.Aggregation, gridAreaCodeOut: '111', @@ -106,6 +112,8 @@ export const eSettExchangeEvents: ExchangeEventSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, calculationType: ExchangeEventCalculationType.Aggregation, gridAreaCodeOut: '222', @@ -131,6 +139,8 @@ export const eSettExchangeEvents: ExchangeEventSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, calculationType: ExchangeEventCalculationType.BalanceFixing, gridAreaCodeOut: '333', @@ -156,6 +166,8 @@ export const eSettExchangeEvents: ExchangeEventSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, calculationType: ExchangeEventCalculationType.BalanceFixing, gridAreaCodeOut: '333', @@ -181,6 +193,8 @@ export const eSettExchangeEvents: ExchangeEventSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, calculationType: ExchangeEventCalculationType.BalanceFixing, gridAreaCodeOut: '333', diff --git a/libs/dh/shared/data-access-mocks/src/lib/data/esett/mga-imbalance-search-response-query.ts b/libs/dh/shared/data-access-mocks/src/lib/data/esett/mga-imbalance-search-response-query.ts index 1f39eab53f..6cdbfad93b 100644 --- a/libs/dh/shared/data-access-mocks/src/lib/data/esett/mga-imbalance-search-response-query.ts +++ b/libs/dh/shared/data-access-mocks/src/lib/data/esett/mga-imbalance-search-response-query.ts @@ -33,6 +33,8 @@ */ import { GetMeteringGridAreaImbalanceQuery, + GridAreaStatus, + GridAreaType, MeteringGridAreaImbalanceSearchResult, PriceAreaCode, } from '@energinet-datahub/dh/shared/domain/graphql'; @@ -55,6 +57,8 @@ const mgaImbalanceSearchResult: MeteringGridAreaImbalanceSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, documentDateTime: new Date('2024-02-19T09:03:20.000Z'), receivedDateTime: new Date('2024-02-19T09:05:19.415Z'), @@ -153,6 +157,8 @@ const mgaImbalanceSearchResult: MeteringGridAreaImbalanceSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, documentDateTime: new Date('2024-02-19T09:03:20.000Z'), receivedDateTime: new Date('2024-02-19T09:05:19.415Z'), @@ -254,6 +260,8 @@ const mgaImbalanceSearchResult: MeteringGridAreaImbalanceSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, documentDateTime: new Date('2024-02-19T06:11:01.000Z'), receivedDateTime: new Date('2024-02-19T06:11:15.166Z'), @@ -359,6 +367,8 @@ const mgaImbalanceSearchResult: MeteringGridAreaImbalanceSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, documentDateTime: new Date('2024-02-19T06:11:01.000Z'), receivedDateTime: new Date('2024-02-19T06:11:15.166Z'), @@ -464,6 +474,8 @@ const mgaImbalanceSearchResult: MeteringGridAreaImbalanceSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, documentDateTime: new Date('2024-02-18T09:04:20.000Z'), receivedDateTime: new Date('2024-02-18T09:05:45.274Z'), @@ -562,6 +574,8 @@ const mgaImbalanceSearchResult: MeteringGridAreaImbalanceSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, documentDateTime: new Date('2024-02-18T09:04:20.000Z'), receivedDateTime: new Date('2024-02-18T09:05:45.274Z'), @@ -660,6 +674,8 @@ const mgaImbalanceSearchResult: MeteringGridAreaImbalanceSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, documentDateTime: new Date('2024-02-18T06:11:56.000Z'), receivedDateTime: new Date('2024-02-18T06:12:10.384Z'), @@ -765,6 +781,8 @@ const mgaImbalanceSearchResult: MeteringGridAreaImbalanceSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, documentDateTime: new Date('2024-02-18T06:11:56.000Z'), receivedDateTime: new Date('2024-02-18T06:12:10.384Z'), @@ -870,6 +888,8 @@ const mgaImbalanceSearchResult: MeteringGridAreaImbalanceSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, documentDateTime: new Date('2024-02-17T09:05:54.000Z'), receivedDateTime: new Date('2024-02-17T09:06:59.176Z'), @@ -968,6 +988,8 @@ const mgaImbalanceSearchResult: MeteringGridAreaImbalanceSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, documentDateTime: new Date('2024-02-17T09:05:54.000Z'), receivedDateTime: new Date('2024-02-17T09:06:59.176Z'), @@ -1066,6 +1088,8 @@ const mgaImbalanceSearchResult: MeteringGridAreaImbalanceSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, documentDateTime: new Date('2024-02-17T06:11:51.000Z'), receivedDateTime: new Date('2024-02-17T06:12:06.802Z'), @@ -1171,6 +1195,8 @@ const mgaImbalanceSearchResult: MeteringGridAreaImbalanceSearchResult[] = [ validFrom: new Date('2020-01-01T00:00:00.000Z'), __typename: 'GridAreaDto', includedInCalculation: true, + type: GridAreaType.Distribution, + status: GridAreaStatus.Active, }, documentDateTime: new Date('2024-02-17T06:11:51.000Z'), receivedDateTime: new Date('2024-02-17T06:12:06.802Z'), diff --git a/libs/dh/shared/data-access-mocks/src/lib/data/get-grid-area-overview.ts b/libs/dh/shared/data-access-mocks/src/lib/data/get-grid-area-overview.ts index 97fdfddb2a..cc2576f744 100644 --- a/libs/dh/shared/data-access-mocks/src/lib/data/get-grid-area-overview.ts +++ b/libs/dh/shared/data-access-mocks/src/lib/data/get-grid-area-overview.ts @@ -14,7 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { GetGridAreaOverviewQuery } from '@energinet-datahub/dh/shared/domain/graphql'; +import { + GetGridAreaOverviewQuery, + GridAreaStatus, + GridAreaType, + PriceAreaCode, +} from '@energinet-datahub/dh/shared/domain/graphql'; export const getGridAreaOverviewMock: GetGridAreaOverviewQuery = { __typename: 'Query', @@ -24,78 +29,90 @@ export const getGridAreaOverviewMock: GetGridAreaOverviewQuery = { code: '003', id: '3', name: 'Grid Area 3', - priceAreaCode: 'DK1', + priceAreaCode: PriceAreaCode.Dk1, actorName: 'Actor 3', actorNumber: '123456783', organizationName: 'Org 3', validFrom: new Date('2021-08-15T12:30:00'), validTo: null, fullFlexDate: new Date('2021-08-16T12:30:00'), + status: GridAreaStatus.Active, + type: GridAreaType.Distribution, }, { __typename: 'GridAreaOverviewItemDto', code: '001', id: '1', name: 'Grid Area 1', - priceAreaCode: 'DK1', + priceAreaCode: PriceAreaCode.Dk1, actorName: 'Actor 1', actorNumber: '123456781', organizationName: 'Org 1', validFrom: new Date('2021-08-17T12:30:00'), validTo: null, fullFlexDate: new Date('2021-08-18T12:30:00'), + status: GridAreaStatus.Archived, + type: GridAreaType.Aboard, }, { __typename: 'GridAreaOverviewItemDto', code: '002', id: '2', name: 'Grid Area 1', - priceAreaCode: 'DK1', + priceAreaCode: PriceAreaCode.Dk1, actorName: 'Actor 2', actorNumber: '123456782', organizationName: 'Org 2', validFrom: new Date('2021-08-14T12:30:00'), validTo: null, fullFlexDate: new Date('2021-08-14T12:30:00'), + status: GridAreaStatus.Created, + type: GridAreaType.GridLossAbroad, }, { __typename: 'GridAreaOverviewItemDto', code: '004', id: '4', name: 'Grid Area 4', - priceAreaCode: 'DK1', + priceAreaCode: PriceAreaCode.Dk1, actorName: 'Actor 4', actorNumber: '123456784', organizationName: 'Org 4', validFrom: new Date('2021-08-15T12:30:00'), validTo: null, fullFlexDate: new Date('2021-08-16T12:30:00'), + status: GridAreaStatus.Expired, + type: GridAreaType.Other, }, { __typename: 'GridAreaOverviewItemDto', code: '005', id: '5', name: 'Grid Area 5', - priceAreaCode: 'DK1', + priceAreaCode: PriceAreaCode.Dk1, actorName: 'Actor 5', actorNumber: '123456785', organizationName: 'Org 5', validFrom: new Date('2021-08-17T12:30:00'), validTo: null, fullFlexDate: new Date('2021-08-18T12:30:00'), + status: GridAreaStatus.Active, + type: GridAreaType.Transmission, }, { __typename: 'GridAreaOverviewItemDto', code: '006', id: '6', name: 'Grid Area 6', - priceAreaCode: 'DK1', + priceAreaCode: PriceAreaCode.Dk1, actorName: 'Actor 6', actorNumber: '123456786', organizationName: 'Org 6', validFrom: new Date('2021-08-19T12:30:00'), validTo: null, fullFlexDate: new Date('2021-08-20T12:30:00'), + status: GridAreaStatus.Active, + type: GridAreaType.GridLossDk, }, ], }; diff --git a/libs/dh/shared/data-access-mocks/src/lib/data/message-archive-search-response-logs.ts b/libs/dh/shared/data-access-mocks/src/lib/data/message-archive-search-response-logs.ts index 9eb7254f75..0aec100030 100644 --- a/libs/dh/shared/data-access-mocks/src/lib/data/message-archive-search-response-logs.ts +++ b/libs/dh/shared/data-access-mocks/src/lib/data/message-archive-search-response-logs.ts @@ -133,6 +133,7 @@ export const messageArchiveSearchResponseLogs: SearchResult = { id: rejectedMessageId, }, { + messageId: 'RequestAggregatedMeasureData-ID', documentType: 'RequestAggregatedMeasureData', createdDate: '2023-06-14T12:12:29.5600357+00:00', senderGln: '5790001330552', diff --git a/libs/dh/shared/data-access-mocks/src/lib/message-archive.ts b/libs/dh/shared/data-access-mocks/src/lib/message-archive.ts index b508035d25..6dd55b91d8 100644 --- a/libs/dh/shared/data-access-mocks/src/lib/message-archive.ts +++ b/libs/dh/shared/data-access-mocks/src/lib/message-archive.ts @@ -21,9 +21,21 @@ import { mswConfig } from '@energinet-datahub/gf/util-msw'; import { actors } from './data/message-archive-actors'; import { messageArchiveSearchResponseLogs } from './data/message-archive-search-response-logs'; import { document, documentJson } from './data/message-archived-document'; +import { + BusinessReason, + BusinessTransaction, + DocumentType, + mockGetArchivedMessagesQuery, +} from '@energinet-datahub/dh/shared/domain/graphql'; export function messageArchiveMocks(apiBase: string) { - return [archivedMessageSearch(apiBase), getActors(apiBase), getDocument(apiBase)]; + return [ + archivedMessageSearch(apiBase), + getActors(apiBase), + getDocument(apiBase), + getDocumentById(apiBase), + getArchivedMessages(apiBase), + ]; } export function archivedMessageSearch(apiBase: string) { @@ -46,11 +58,64 @@ export function getDocument(apiBase: string) { async (): Promise> => { await delay(mswConfig.delay); const random = Math.floor(Math.random() * 1000); + return random % 2 === 0 + ? HttpResponse.text(document, { headers: { 'Content-Type': 'text/xml' } }) + : HttpResponse.json(documentJson, { headers: { 'Content-Type': 'application/json' } }); + } + ); +} - console.log(random); +export function getDocumentById(apiBase: string) { + return http.get( + `${apiBase}/v1/MessageArchive/Document?id=:id`, + async (): Promise> => { + await delay(mswConfig.delay); + const random = Math.floor(Math.random() * 1000); return random % 2 === 0 ? HttpResponse.text(document, { headers: { 'Content-Type': 'text/xml' } }) : HttpResponse.json(documentJson, { headers: { 'Content-Type': 'application/json' } }); } ); } + +function getArchivedMessages(apiBase: string) { + return mockGetArchivedMessagesQuery(async () => { + await delay(mswConfig.delay); + return HttpResponse.json({ + data: { + __typename: 'Query', + archivedMessages: { + __typename: 'ArchivedMessagesConnection', + pageInfo: { + __typename: 'PageInfo', + startCursor: 'startCursor', + endCursor: 'endCursor', + }, + totalCount: messageArchiveSearchResponseLogs.messages.length, + nodes: messageArchiveSearchResponseLogs.messages.map((m) => ({ + __typename: 'ArchivedMessage', + id: m.id, + messageId: m.messageId, + documentType: m.documentType as DocumentType, + receiver: { + __typename: 'Actor', + id: '8698f30b-5e9d-4f70-9e8b-ce79d8b1b303', + glnOrEicNumber: m.receiverGln ?? '', + displayName: 'Energinet DataHub', + }, + sender: { + __typename: 'Actor', + id: '8698f30b-5e9d-4f70-9e8b-ce79d8b1b303', + glnOrEicNumber: m.senderGln ?? '', + displayName: 'Energinet DataHub', + }, + createdAt: m.createdDate ? new Date(m.createdDate) : new Date(), + documentUrl: `${apiBase}/v1/MessageArchive/Document?id=${m.id}`, + businessTransaction: BusinessTransaction.Rsm016, + businessReason: BusinessReason.D14, + })), + }, + }, + }); + }); +} diff --git a/libs/dh/shared/data-access-mocks/src/lib/wholesale.ts b/libs/dh/shared/data-access-mocks/src/lib/wholesale.ts index e5f6b6b1f2..41e570087a 100644 --- a/libs/dh/shared/data-access-mocks/src/lib/wholesale.ts +++ b/libs/dh/shared/data-access-mocks/src/lib/wholesale.ts @@ -41,6 +41,8 @@ import { CalculationProgressStep, ProgressStatus, CalculationExecutionType, + GridAreaStatus, + GridAreaType, } from '@energinet-datahub/dh/shared/domain/graphql'; import { mockRequestCalculationMutation } from '@energinet-datahub/dh/shared/domain/graphql'; @@ -114,6 +116,8 @@ export const mockedGridAreas: GridAreaDto[] = [ priceAreaCode: PriceAreaCode.Dk1, validFrom, validTo: null, + status: GridAreaStatus.Active, + type: GridAreaType.Distribution, includedInCalculation: true, }, { @@ -123,6 +127,8 @@ export const mockedGridAreas: GridAreaDto[] = [ name: 'hello again', displayName: '002 • hello again', priceAreaCode: PriceAreaCode.Dk1, + status: GridAreaStatus.Created, + type: GridAreaType.GridLossDk, validFrom, validTo: null, includedInCalculation: false, diff --git a/libs/dh/shared/domain/src/lib/generated/v1/api/message-archive-http.service.ts b/libs/dh/shared/domain/src/lib/generated/v1/api/message-archive-http.service.ts index 134eae77bf..2702cf76c5 100644 --- a/libs/dh/shared/domain/src/lib/generated/v1/api/message-archive-http.service.ts +++ b/libs/dh/shared/domain/src/lib/generated/v1/api/message-archive-http.service.ts @@ -163,6 +163,80 @@ export class MessageArchiveHttp { ); } + /** + * @param id + * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. + * @param reportProgress flag to report request and response progress. + */ + public v1MessageArchiveDocumentGet(id?: string, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain', context?: HttpContext, transferCache?: boolean}): Observable; + public v1MessageArchiveDocumentGet(id?: string, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain', context?: HttpContext, transferCache?: boolean}): Observable>; + public v1MessageArchiveDocumentGet(id?: string, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'text/plain', context?: HttpContext, transferCache?: boolean}): Observable>; + public v1MessageArchiveDocumentGet(id?: string, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'text/plain', context?: HttpContext, transferCache?: boolean}): Observable { + + let localVarQueryParameters = new HttpParams({encoder: this.encoder}); + if (id !== undefined && id !== null) { + localVarQueryParameters = this.addToHttpParams(localVarQueryParameters, + id, 'id'); + } + + let localVarHeaders = this.defaultHeaders; + + let localVarCredential: string | undefined; + // authentication (Bearer) required + localVarCredential = this.configuration.lookupCredential('Bearer'); + if (localVarCredential) { + localVarHeaders = localVarHeaders.set('Authorization', 'Bearer ' + localVarCredential); + } + + let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept; + if (localVarHttpHeaderAcceptSelected === undefined) { + // to determine the Accept header + const httpHeaderAccepts: string[] = [ + 'text/plain' + ]; + localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts); + } + if (localVarHttpHeaderAcceptSelected !== undefined) { + localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected); + } + + let localVarHttpContext: HttpContext | undefined = options && options.context; + if (localVarHttpContext === undefined) { + localVarHttpContext = new HttpContext(); + } + + let localVarTransferCache: boolean | undefined = options && options.transferCache; + if (localVarTransferCache === undefined) { + localVarTransferCache = true; + } + + + let responseType_: 'text' | 'json' | 'blob' = 'json'; + if (localVarHttpHeaderAcceptSelected) { + if (localVarHttpHeaderAcceptSelected.startsWith('text')) { + responseType_ = 'text'; + } else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) { + responseType_ = 'json'; + } else { + responseType_ = 'blob'; + } + } + + let localVarPath = `/v1/MessageArchive/Document`; + return this.httpClient.request('get', `${this.configuration.basePath}${localVarPath}`, + { + context: localVarHttpContext, + params: localVarQueryParameters, + responseType: responseType_, + withCredentials: this.configuration.withCredentials, + headers: localVarHeaders, + observe: observe, + transferCache: localVarTransferCache, + reportProgress: reportProgress + } + ); + } + /** * @param id * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. diff --git a/libs/dh/shared/feature-authorization/src/lib/dh-actor-storage.ts b/libs/dh/shared/feature-authorization/src/lib/dh-actor-storage.ts index e5c7578590..0cfa5d8445 100644 --- a/libs/dh/shared/feature-authorization/src/lib/dh-actor-storage.ts +++ b/libs/dh/shared/feature-authorization/src/lib/dh-actor-storage.ts @@ -73,7 +73,7 @@ export class DhActorStorage { this.setSelectedActorId(actor.id); }; - getSelectedActor = () => { + getSelectedActor = (): SelectionActor | null => { const selectedActorInLS = this._localStorage.getItem(this.selectedActorKey); const selectedActorInSS = this._sessionStorage.getItem(this.selectedActorKey); diff --git a/libs/dh/shared/feature-flags/src/lib/dh-feature-flags.ts b/libs/dh/shared/feature-flags/src/lib/dh-feature-flags.ts index 9d844b5517..e73025a4cd 100644 --- a/libs/dh/shared/feature-flags/src/lib/dh-feature-flags.ts +++ b/libs/dh/shared/feature-flags/src/lib/dh-feature-flags.ts @@ -66,6 +66,10 @@ export const dhFeatureFlagsConfig = { DhAppEnvironment.prod, ], }, + 'message-archive-v2': { + created: '25-09-2024', + disabledEnvironments: [DhAppEnvironment.preprod, DhAppEnvironment.prod], + }, } satisfies FeatureFlagConfig; export type DhFeatureFlags = keyof typeof dhFeatureFlagsConfig; diff --git a/libs/dh/shared/util-apollo/src/lib/dataSource.ts b/libs/dh/shared/util-apollo/src/lib/dataSource.ts index ceac4eaa28..4d31672c06 100644 --- a/libs/dh/shared/util-apollo/src/lib/dataSource.ts +++ b/libs/dh/shared/util-apollo/src/lib/dataSource.ts @@ -21,11 +21,10 @@ import { debounceTime, filter, map, - merge, + mergeWith, Observable, ReplaySubject, skip, - startWith, Subscription, switchMap, take, @@ -70,6 +69,10 @@ export class ApolloDataSource this._configureSort(sort), 0); + } this._sort = sort; this._updateChangeSubscription(); } @@ -123,13 +129,19 @@ export class ApolloDataSource['subscribeToMore'] = (options) => this._query.subscribeToMore(options); + reset() { + // Reset subject so it does not have an initial value + this._inputChange = new ReplaySubject(1); + this._updateChangeSubscription(); + this._totalCount.set(0); + this._data.set([]); + this._query.reset(); + if (this.paginator) this.paginator.length = 0; + if (this.sort) this._configureSort(this.sort); + } + connect() { - return this._connection.pipe( - tap((connection) => this._totalCount.set(connection.totalCount)), - map((connection) => connection.nodes ?? []), - tap((nodes) => this._data.set(nodes)), - startWith([] as TNode[]) - ); + return toObservable(this._data); } disconnect() { @@ -151,11 +163,11 @@ export class ApolloDataSource ({ filter })) + map((filter) => ({ filter })), + mergeWith(this._inputChange), + map((variables) => ({ variables })) ); const sortChange = sort.sortChange.pipe( filter((s) => Boolean(s.direction)), - map((s) => ({ ...firstPage(paginator), order: { [s.active]: s.direction.toUpperCase() } })), - tap(() => paginator.firstPage()) + map((s) => ({ [s.active]: s.direction.toUpperCase() })), + map((order) => ({ skip: this.totalCount <= 1, variables: { order } })) ); // Create observables that emits just before the sort and input changes, in order // to prevent the paginator observable from running in response to `firstPage()`. + const beforeInputChange = connectable(inputChange); const beforeSortChange = connectable(sort.sortChange); - const beforeInputChange = connectable(this._inputChange); const pageChange = this._connection.pipe( + tap((connection) => this._totalCount.set(connection.totalCount)), tap((connection) => (paginator.length = connection.totalCount)), tap(() => (paginator.disabled = false)), switchMap((connection) => paginator.page.pipe( take(1), - takeUntil(beforeSortChange), takeUntil(beforeInputChange), + takeUntil(beforeSortChange), tap(() => (paginator.disabled = true)), - map((event) => navigate(paginator, event, connection.pageInfo)) + map((event) => navigate(paginator, event, connection.pageInfo)), + map((variables) => ({ variables })) ) ) ); - const inputChange = this._inputChange.pipe( + const dataChange = this._connection.pipe(map((connection) => connection.nodes ?? [])); + const optionsChange = inputChange.pipe( + mergeWith(sortChange), tap(() => paginator.firstPage()), - map((variables) => ({ - ...firstPage(paginator), - ...variables, - })) - ); - - const variablesChange = merge( - filterChange, - sortChange, - pageChange, - inputChange - ) as Observable; + map((opts) => ({ ...opts, variables: { ...firstPage(paginator), ...opts.variables } })), + mergeWith(pageChange) + ) as Observable>; this._subscription?.unsubscribe(); - this._subscription = beforeSortChange.connect(); + this._subscription = dataChange.subscribe((nodes) => this._data.set(nodes)); this._subscription.add(beforeInputChange.connect()); - this._subscription.add(variablesChange.subscribe((v) => this._query.refetch(v))); + this._subscription.add(beforeSortChange.connect()); + this._subscription.add(optionsChange.subscribe((opts) => this._query.setOptions(opts))); } } diff --git a/libs/dh/shared/util-apollo/src/lib/mutation.ts b/libs/dh/shared/util-apollo/src/lib/mutation.ts index e7f28b7c02..b3dd42eebb 100644 --- a/libs/dh/shared/util-apollo/src/lib/mutation.ts +++ b/libs/dh/shared/util-apollo/src/lib/mutation.ts @@ -46,6 +46,7 @@ export function mutation( const data = signal(undefined); const error = signal(undefined); const loading = signal(false); + const called = signal(false); return { // Upcast to prevent writing to signals @@ -56,6 +57,7 @@ export function mutation( data.set(undefined); error.set(undefined); loading.set(false); + called.set(false); }, mutate(options?: Partial>) { const mergedOptions = { ...parentOptions, ...options }; diff --git a/libs/dh/shared/util-apollo/src/lib/query.ts b/libs/dh/shared/util-apollo/src/lib/query.ts index da209aea5b..895d260def 100644 --- a/libs/dh/shared/util-apollo/src/lib/query.ts +++ b/libs/dh/shared/util-apollo/src/lib/query.ts @@ -68,6 +68,7 @@ export type QueryResult = { error: Signal; loading: Signal; networkStatus: Signal; + called: Signal; reset: () => void; getOptions: () => QueryOptions; setOptions: (options: Partial>) => Promise>; @@ -95,7 +96,7 @@ export function query( // a new `watchQuery` (with optionally new variables) is executed each time `refetch` is called. const options$ = new BehaviorSubject(options); const ref$ = options$.pipe( - skipWhile((opts) => opts?.skip ?? false), + filter((opts) => !opts?.skip), map((opts) => client.watchQuery({ ...opts, query: document })), share() ); @@ -132,6 +133,7 @@ export function query( const data = signal(undefined); const error = signal(undefined); const loading = signal(!options?.skip); + const called = signal(false); const networkStatus = signal(options?.skip ? NetworkStatus.ready : NetworkStatus.loading); // Update the signal values based on the result of the query @@ -141,6 +143,7 @@ export function query( error.set(result.error); loading.set(result.loading); networkStatus.set(result.networkStatus); + called.set(true); }); // Clean up when the component is destroyed @@ -155,17 +158,21 @@ export function query( error: error as Signal, loading: loading as Signal, networkStatus: networkStatus as Signal, + called: called as Signal, reset: () => { reset$.next(); + options$.next({ ...options, skip: true }); data.set(undefined); error.set(undefined); loading.set(false); networkStatus.set(NetworkStatus.ready); + called.set(false); }, getOptions: () => options$.value ?? {}, setOptions: (options: Partial>) => { const result = firstValueFrom(result$.pipe(filter((result) => !result.loading))); - options$.next({ ...options$.value, skip: false, ...options }); + const mergedVariables = { ...options$.value?.variables, ...options.variables } as TVariables; + options$.next({ ...options$.value, skip: false, ...options, variables: mergedVariables }); return result; }, refetch: (variables?: Partial) => { @@ -174,8 +181,8 @@ export function query( options$.next({ ...options$.value, skip: false, - variables: mergedVariables, fetchPolicy: 'network-only', + variables: mergedVariables, }); return result; }, diff --git a/libs/dh/wholesale/data-access-graphql/project.json b/libs/dh/wholesale/data-access-graphql/project.json index 0797893f9e..a4e6c844fa 100644 --- a/libs/dh/wholesale/data-access-graphql/project.json +++ b/libs/dh/wholesale/data-access-graphql/project.json @@ -5,6 +5,7 @@ "sourceRoot": "libs/dh/wholesale/data-access-graphql", "prefix": "dh", "tags": ["product:dh", "domain:wholesale", "type:data-access"], + "implicitDependencies": ["api-dh"], "targets": { "lint": { "executor": "@nx/eslint:lint" diff --git a/libs/dh/wholesale/feature-settlement-reports/src/lib/button/dh-request-settlement-report-button.component.ts b/libs/dh/wholesale/feature-settlement-reports/src/lib/button/dh-request-settlement-report-button.component.ts index cc9d3872c4..c652826fff 100644 --- a/libs/dh/wholesale/feature-settlement-reports/src/lib/button/dh-request-settlement-report-button.component.ts +++ b/libs/dh/wholesale/feature-settlement-reports/src/lib/button/dh-request-settlement-report-button.component.ts @@ -14,13 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, inject } from '@angular/core'; +import { Component, DestroyRef, inject } from '@angular/core'; import { TranslocoPipe } from '@ngneat/transloco'; import { WattButtonComponent } from '@energinet-datahub/watt/button'; import { WattModalService } from '@energinet-datahub/watt/modal'; import { DhRequestSettlementReportModalComponent } from '../modal/dh-request-settlement-report-modal.component'; +import { DhRequestAsSettlementReportModalComponent } from '../modal/dh-request-as-settlement-report-modal.component'; +import { + DhActorStorage, + PermissionService, +} from '@energinet-datahub/dh/shared/feature-authorization'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @Component({ selector: 'dh-request-settlement-report-button', @@ -34,10 +40,29 @@ import { DhRequestSettlementReportModalComponent } from '../modal/dh-request-set }) export class DhRequestSettlementReportButtonComponent { private readonly modalService = inject(WattModalService); + private readonly permissionService = inject(PermissionService); + private readonly actorStorage = inject(DhActorStorage); + private readonly destroyRef = inject(DestroyRef); openModal() { - this.modalService.open({ - component: DhRequestSettlementReportModalComponent, - }); + this.permissionService + .isFas() + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((isFas) => { + if (isFas) { + this.modalService.open({ + component: DhRequestAsSettlementReportModalComponent, + }); + } else { + this.modalService.open({ + component: DhRequestSettlementReportModalComponent, + data: { + isFas: false, + actorId: this.actorStorage.getSelectedActorId(), + marketRole: this.actorStorage.getSelectedActor()?.marketRole, + }, + }); + } + }); } } diff --git a/libs/dh/wholesale/feature-settlement-reports/src/lib/modal/dh-request-as-settlement-report-modal.component.html b/libs/dh/wholesale/feature-settlement-reports/src/lib/modal/dh-request-as-settlement-report-modal.component.html new file mode 100644 index 0000000000..2f56c08d9d --- /dev/null +++ b/libs/dh/wholesale/feature-settlement-reports/src/lib/modal/dh-request-as-settlement-report-modal.component.html @@ -0,0 +1,44 @@ + + + +
+ + + +
+ + + {{ t("cancel") }} + + {{ t("continue") }} + + +
diff --git a/libs/dh/wholesale/feature-settlement-reports/src/lib/modal/dh-request-as-settlement-report-modal.component.ts b/libs/dh/wholesale/feature-settlement-reports/src/lib/modal/dh-request-as-settlement-report-modal.component.ts new file mode 100644 index 0000000000..e02f2a04fd --- /dev/null +++ b/libs/dh/wholesale/feature-settlement-reports/src/lib/modal/dh-request-as-settlement-report-modal.component.ts @@ -0,0 +1,134 @@ +/** + * @license + * Copyright 2020 Energinet DataHub A/S + * + * Licensed under the Apache License, Version 2.0 (the "License2"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { Component, DestroyRef, inject, signal } from '@angular/core'; +import { + FormControl, + FormGroup, + NonNullableFormBuilder, + ReactiveFormsModule, + Validators, +} from '@angular/forms'; +import { getActorOptions } from '@energinet-datahub/dh/shared/data-access-graphql'; +import { EicFunction, GetActorByIdDocument } from '@energinet-datahub/dh/shared/domain/graphql'; +import { WattButtonComponent } from '@energinet-datahub/watt/button'; +import { WattDropdownComponent } from '@energinet-datahub/watt/dropdown'; +import { WattFieldErrorComponent } from '@energinet-datahub/watt/field'; +import { WATT_MODAL, WattModalService, WattTypedModal } from '@energinet-datahub/watt/modal'; +import { VaterStackComponent } from '@energinet-datahub/watt/vater'; +import { TranslocoDirective } from '@ngneat/transloco'; +import { RxPush } from '@rx-angular/template/push'; + +import { DhRequestSettlementReportModalComponent } from '../modal/dh-request-settlement-report-modal.component'; +import { Apollo } from 'apollo-angular'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { + DhActorStorage, + PermissionService, +} from '@energinet-datahub/dh/shared/feature-authorization'; + +type DhFormType = FormGroup<{ + actorId: FormControl; +}>; + +@Component({ + selector: 'dh-request-as-settlement-report-modal', + standalone: true, + imports: [ + RxPush, + ReactiveFormsModule, + TranslocoDirective, + + WATT_MODAL, + VaterStackComponent, + WattDropdownComponent, + WattButtonComponent, + WattFieldErrorComponent, + ], + templateUrl: './dh-request-as-settlement-report-modal.component.html', +}) +export class DhRequestAsSettlementReportModalComponent extends WattTypedModal { + private readonly formBuilder = inject(NonNullableFormBuilder); + private readonly modalService = inject(WattModalService); + private readonly destroyRef = inject(DestroyRef); + private readonly apollo = inject(Apollo); + + private readonly permissionService = inject(PermissionService); + private readonly actorStorage = inject(DhActorStorage); + + form: DhFormType = this.formBuilder.group({ + actorId: new FormControl(this.actorStorage.getSelectedActorId(), { + validators: Validators.required, + nonNullable: true, + }), + }); + + actorOptions$ = getActorOptions( + [EicFunction.DataHubAdministrator, EicFunction.GridAccessProvider, EicFunction.EnergySupplier], + 'actorId' + ); + + submitInProgress = signal(false); + + submit(): void { + if (this.form.invalid || !this.form.value.actorId) { + return; + } + + this.submitInProgress.set(true); + + if (this.form.value.actorId == this.actorStorage.getSelectedActorId()) { + this.permissionService + .isFas() + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((isFas) => { + this.modalService.close(true); + this.modalService.open({ + component: DhRequestSettlementReportModalComponent, + data: { + isFas, + actorId: this.actorStorage.getSelectedActor()?.id, + marketRole: this.actorStorage.getSelectedActor()?.marketRole, + }, + }); + + this.submitInProgress.set(false); + }); + } else { + this.apollo + .query({ + query: GetActorByIdDocument, + variables: { + id: this.form.value.actorId, + }, + }) + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe((result) => { + this.modalService.close(true); + this.modalService.open({ + component: DhRequestSettlementReportModalComponent, + data: { + isFas: false, + actorId: result.data.actorById.id, + marketRole: result.data.actorById.marketRole, + }, + }); + + this.submitInProgress.set(false); + }); + } + } +} diff --git a/libs/dh/wholesale/feature-settlement-reports/src/lib/modal/dh-request-settlement-report-modal.component.html b/libs/dh/wholesale/feature-settlement-reports/src/lib/modal/dh-request-settlement-report-modal.component.html index 2710983517..8ed59c51ac 100644 --- a/libs/dh/wholesale/feature-settlement-reports/src/lib/modal/dh-request-settlement-report-modal.component.html +++ b/libs/dh/wholesale/feature-settlement-reports/src/lib/modal/dh-request-settlement-report-modal.component.html @@ -21,6 +21,41 @@ >
+ @if (hasMoreThanOneGridAreaOption()) { +
+ + @if (multipleGridAreasSelected$ | push) { + + {{ t("gridAreaHint", { count: form.controls.gridAreas.value?.length }) }} + + } + + + @if (multipleGridAreasSelected$ | push) { + + {{ t("combineResultsInOneFile") }} + + } +
+ } + + @if ((showEnergySupplierDropdown$ | push) && form.controls.energySupplier) { +
+ +
+ } +
- @if ((showEnergySupplierDropdown$ | push) && form.controls.energySupplier) { -
- -
- } - - @if (hasMoreThanOneGridAreaOption()) { -
- - @if (miltipleGridAreasSelected$ | push) { - - {{ t("gridAreaHint", { count: form.controls.gridAreas.value?.length }) }} - - } - - - @if (miltipleGridAreasSelected$ | push) { - - {{ t("combineResultsInOneFile") }} - - } -
- } - ; }>; +type SettlementReportRequestedBy = { + isFas: boolean; + actorId: string; + marketRole: EicFunction; +}; + @Component({ selector: 'dh-request-settlement-report-modal', standalone: true, @@ -132,16 +135,14 @@ type DhFormType = FormGroup<{ `, templateUrl: './dh-request-settlement-report-modal.component.html', }) -export class DhRequestSettlementReportModalComponent extends WattTypedModal { +export class DhRequestSettlementReportModalComponent extends WattTypedModal { private readonly formBuilder = inject(NonNullableFormBuilder); private readonly environmentInjector = inject(EnvironmentInjector); private readonly destroyRef = inject(DestroyRef); private readonly apollo = inject(Apollo); - private readonly permissionService = inject(PermissionService); private readonly toastService = inject(WattToastService); private readonly modalService = inject(WattModalService); - private readonly actorStorage = inject(DhActorStorage); private modal = viewChild.required(WattModalComponent); @@ -170,16 +171,13 @@ export class DhRequestSettlementReportModalComponent extends WattTypedModal { useApi: new FormControl(false, { nonNullable: true }), }); - showEnergySupplierDropdown$ = this.permissionService.isFas().pipe( - map( - (isFas) => - isFas || this.actorStorage.getSelectedActor().marketRole === EicFunction.SystemOperator - ), + showEnergySupplierDropdown$ = of(this.modalData.isFas).pipe( + map((isFas) => isFas || this.modalData.marketRole === EicFunction.SystemOperator), tap((showEnergySupplierDropdown) => { if (showEnergySupplierDropdown) { this.form.addControl( 'energySupplier', - new FormControl(null, Validators.required) + new FormControl(ALL_ENERGY_SUPPLIERS, Validators.required) ); } }) @@ -201,7 +199,7 @@ export class DhRequestSettlementReportModalComponent extends WattTypedModal { showMonthlySumCheckbox$ = this.shouldShowMonthlySumCheckbox(); - miltipleGridAreasSelected$: Observable = this.form.controls.gridAreas.valueChanges.pipe( + multipleGridAreasSelected$: Observable = this.form.controls.gridAreas.valueChanges.pipe( map((gridAreas) => (gridAreas?.length ? gridAreas.length > 1 : false)), tap((moreThanOneGridAreas) => { if (!moreThanOneGridAreas) { @@ -295,6 +293,26 @@ export class DhRequestSettlementReportModalComponent extends WattTypedModal { return; } + let marketRole: SettlementReportMarketRole; + + switch (this.modalData.marketRole) { + case EicFunction.DataHubAdministrator: + marketRole = SettlementReportMarketRole.DataHubAdministrator; + break; + case EicFunction.EnergySupplier: + marketRole = SettlementReportMarketRole.EnergySupplier; + break; + case EicFunction.GridAccessProvider: + marketRole = SettlementReportMarketRole.GridAccessProvider; + break; + case EicFunction.SystemOperator: + marketRole = SettlementReportMarketRole.SystemOperator; + break; + default: + marketRole = SettlementReportMarketRole.Other; + break; + } + this.apollo .mutate({ mutation: RequestSettlementReportDocument, @@ -316,6 +334,8 @@ export class DhRequestSettlementReportModalComponent extends WattTypedModal { energySupplier: energySupplier == ALL_ENERGY_SUPPLIERS ? null : energySupplier, csvLanguage: translate('selectedLanguageIso'), useApi, + requestAsActorId: this.modalData.actorId, + requestAsMarketRole: marketRole, }, }, refetchQueries: (result) => { @@ -350,11 +370,9 @@ export class DhRequestSettlementReportModalComponent extends WattTypedModal { } private getCalculationTypeOptions(): WattDropdownOptions { - const selectedUser = this.actorStorage.getSelectedActor(); - return dhEnumToWattDropdownOptions(CalculationType, null, [ CalculationType.Aggregation, - selectedUser?.marketRole === EicFunction.SystemOperator ? CalculationType.BalanceFixing : '', + this.modalData.marketRole === EicFunction.SystemOperator ? CalculationType.BalanceFixing : '', ]); } @@ -387,16 +405,15 @@ export class DhRequestSettlementReportModalComponent extends WattTypedModal { } private showAllGridAres(): Observable { - const isFas$ = this.permissionService.isFas(); const canSeeAllGridAreas = [EicFunction.EnergySupplier, EicFunction.SystemOperator].includes( - this.actorStorage.getSelectedActor().marketRole + this.modalData.marketRole ); - return isFas$.pipe(map((isFas) => isFas || canSeeAllGridAreas)); + return of(this.modalData.isFas || canSeeAllGridAreas); } private getGridAreaOptionsForActor(): Observable { - const actorId = this.actorStorage.getSelectedActorId(); + const actorId = this.modalData.actorId; return this.apollo .query({ query: GetActorByIdDocument, diff --git a/libs/eo/core/globalization/configuration-watt-translation/src/lib/eo-watt-translation.providers.ts b/libs/eo/core/globalization/configuration-watt-translation/src/lib/eo-watt-translation.providers.ts index 9ee84880c3..2bcfc2f35b 100644 --- a/libs/eo/core/globalization/configuration-watt-translation/src/lib/eo-watt-translation.providers.ts +++ b/libs/eo/core/globalization/configuration-watt-translation/src/lib/eo-watt-translation.providers.ts @@ -42,9 +42,9 @@ export class EoDataIntlService extends WattDataIntlService { transloco.selectTranslateObject('shared').subscribe((translations) => { this.search = translations.search; this.emptyTitle = translations.empty.title; - this.emptyMessage = translations.empty.message; + this.emptyText = translations.empty.message; this.errorTitle = translations.error.title; - this.errorMessage = translations.error.message; + this.errorText = translations.error.message; this.changes.next(); }); } diff --git a/libs/watt/src/lib/components/data/watt-data-intl.service.ts b/libs/watt/src/lib/components/data/watt-data-intl.service.ts index 9bf7f06962..01cbbe2472 100644 --- a/libs/watt/src/lib/components/data/watt-data-intl.service.ts +++ b/libs/watt/src/lib/components/data/watt-data-intl.service.ts @@ -22,7 +22,9 @@ export class WattDataIntlService { readonly changes: Subject = new Subject(); search = 'Search'; emptyTitle = 'No results found'; - emptyMessage = 'Try changing the search criteria.'; + emptyText = 'Try changing the search criteria.'; errorTitle = 'An unexpected error occured'; - errorMessage = 'Unfortunately, an error occurred while retrieving the necessary information.'; + errorText = 'Unfortunately, an error occurred while retrieving the necessary information.'; + defaultTitle = 'An unexpected error occured'; + defaultText = 'Unfortunately, an error occurred while retrieving the necessary information.'; } diff --git a/libs/watt/src/lib/components/data/watt-data-table.component.ts b/libs/watt/src/lib/components/data/watt-data-table.component.ts index 00d69e188f..e4abdd44e4 100644 --- a/libs/watt/src/lib/components/data/watt-data-table.component.ts +++ b/libs/watt/src/lib/components/data/watt-data-table.component.ts @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Component, ContentChild, Input, ViewEncapsulation, inject } from '@angular/core'; +import { Component, ViewEncapsulation, contentChild, inject, input, output } from '@angular/core'; import { VaterFlexComponent, @@ -78,54 +78,57 @@ import { WattDataIntlService } from './watt-data-intl.service'; `, ], template: ` - + - {{ count ?? table.dataSource.totalCount }} + {{ count() ?? table().dataSource.totalCount }} - @if (enableSearch) { - + @if (enableSearch()) { + } - @if (!table.loading && table.dataSource.filteredData.length === 0) { + @if (!table().loading && table().dataSource.filteredData.length === 0) {
}
- @if (enablePaginator) { - + @if (enablePaginator()) { + }
`, }) export class WattDataTableComponent { - @Input() error: unknown; - @Input() enableSearch = true; - @Input() searchLabel?: string; - @Input() enablePaginator = true; - @Input() count?: number; - @Input() variant: WATT_CARD_VARIANT = 'elevation'; + intl = inject(WattDataIntlService); - @ContentChild(WattTableComponent, { descendants: true }) - table!: WattTableComponent; + error = input(); + ready = input(true); + enableSearch = input(true); + searchLabel = input(); + enablePaginator = input(true); + count = input(); + variant = input('elevation'); - intl = inject(WattDataIntlService); + clear = output(); + + table = contentChild.required(WattTableComponent, { descendants: true }); onSearch(value: string) { - this.table.dataSource.filter = value; + this.table().dataSource.filter = value; + if (!value) this.clear.emit(); } } diff --git a/libs/watt/src/lib/components/field/watt-field.component.scss b/libs/watt/src/lib/components/field/watt-field.component.scss index 0e29c64e99..68ed3de4da 100644 --- a/libs/watt/src/lib/components/field/watt-field.component.scss +++ b/libs/watt/src/lib/components/field/watt-field.component.scss @@ -72,7 +72,7 @@ watt-field { display: block; &:not(.watt-field--chip) { - min-height: 100px; + min-height: 93px; } &:not(.watt-field--chip).watt-field--unlabelled { diff --git a/libs/watt/src/lib/components/picker/datetimepicker/watt-datetimepicker.component.ts b/libs/watt/src/lib/components/picker/datetimepicker/watt-datetimepicker.component.ts index 0bc889a758..eedec79251 100644 --- a/libs/watt/src/lib/components/picker/datetimepicker/watt-datetimepicker.component.ts +++ b/libs/watt/src/lib/components/picker/datetimepicker/watt-datetimepicker.component.ts @@ -32,6 +32,13 @@ import dayjs from 'dayjs'; WattTimepickerComponent, VaterFlexComponent, ], + styles: [ + ` + watt-datetimepicker { + width: 100%; + } + `, + ], template: ` -{{ icon }} +@if (customIcon) { + +} @else { + {{ icon }} +} diff --git a/libs/watt/src/lib/foundations/icon/icon.component.ts b/libs/watt/src/lib/foundations/icon/icon.component.ts index f9aa1888d1..b3b31d6af8 100644 --- a/libs/watt/src/lib/foundations/icon/icon.component.ts +++ b/libs/watt/src/lib/foundations/icon/icon.component.ts @@ -74,6 +74,9 @@ export class WattIconComponent { * @returns */ private setIcon(name?: WattIcon) { + this.icon = ''; + this.customIcon = ''; + if (!name) { console.warn('No icon was provided!'); return; diff --git a/tsconfig.base.json b/tsconfig.base.json index d825965bda..a3af77f13e 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -125,6 +125,9 @@ "@energinet-datahub/dh/message-archive/feature-log-search": [ "libs/dh/message-archive/feature-log-search/src/index.ts" ], + "@energinet-datahub/dh/message-archive/feature-search": [ + "libs/dh/message-archive/feature-search/src/index.ts" + ], "@energinet-datahub/dh/message-archive/shell": [ "libs/dh/message-archive/shell/src/index.ts" ],