Untitled
using KMD.Elements.MDP.ConnectionPoints.Application.Dtos.MeteringPoints; using KMD.Elements.MDP.ConnectionPoints.Application.MeteringPointProcesses.ChangeFormulaProcess.Mappers; using KMD.Elements.MDP.ConnectionPoints.Application.MeteringPointProcesses.Exceptions; using KMD.Elements.MDP.ConnectionPoints.Application.Services.ExternalCommunication.ConnectionPoints; using KMD.Elements.MDP.ConnectionPoints.Application.Services.ExternalCommunication.MeterFrames; using KMD.Elements.MDP.ConnectionPoints.Application.Services.ExternalCommunication.MeteringPoints; using KMD.Elements.MDP.ConnectionPoints.Application.Services.ExternalCommunication.MeteringPointsV2; using KMD.Elements.MDP.ConnectionPoints.Contracts.ChangeFormulaProcessCommand; using KMD.Elements.MDP.ConnectionPoints.Core.Constants.MeteringPoints; using KMD.Elements.MDP.ConnectionPoints.Core.Exceptions; using KMD.Elements.MDP.ConnectionPoints.Models.Models.MeteringPointIds; using KMD.Elements.MDP.ConnectionPoints.Models.Models.MeteringPointProcesses.ValueObjects; using SupplyType = KMD.Elements.MDP.ConnectionPoints.Models.Models.Common.Enums.SupplyType; namespace KMD.Elements.MDP.ConnectionPoints.Application.MeteringPointProcesses.ChangeFormulaProcess.Commands.StartChangeFormulaProcess; public class ChangeFormulaProcessCommandFactory( IMeterFramesService meterFramesService, IConnectionPointsService connectionPointsService, IMeteringPointsV2Service meteringPointsService, IMeteringPointsService electricityMeteringPointsService) : IChangeFormulaProcessCommandFactory { private ChangeFormulaPayloadBuilder _payloadBuilder = null!; private string? _oldSubtypeOfMeteringPoint = null; public async Task<StartChangeFormulaProcess> CreateAsync( ChangeFormulaProcessCommandPayload payload, DateTime timestamp, CancellationToken cancellationToken) { _payloadBuilder = new ChangeFormulaPayloadBuilder( payload.MeteringPointVersionId, payload.ValidFrom, payload.ProcessId ?? Guid.NewGuid(), payload.StartedBy, payload.OnBehalfOf, DateTime.UtcNow, ChangeFormulaParentProcessMapper.Map(payload.ParentProcess)); var meteringPointId = MeteringPointIdGenerator.ExtractMeteringPointId(payload.MeteringPointVersionId); //if (meteringPointId.SupplyType == SupplyType.Electricity) //{ // throw new NotSupportedException($"SupplyType {meteringPointId.SupplyType} is not supported"); //} await BuildUpdatePayload(meteringPointId.Id, meteringPointId.SupplyType, payload, cancellationToken); var formulaPayload = await GetFormulaPayload(payload.MeteringPointVersionId, meteringPointId.SupplyType, cancellationToken); await BuildFormulaPayload(payload, formulaPayload, meteringPointId.SupplyType, cancellationToken); return _payloadBuilder.Build(); } private async Task BuildUpdatePayload( string meteringPointId, SupplyType supplyType, ChangeFormulaProcessCommandPayload payload, CancellationToken cancellationToken) { switch (supplyType) { case SupplyType.Water: await BuildUpdatePayloadForWater(meteringPointId, payload, cancellationToken); break; case SupplyType.Heating: await BuildUpdatePayloadForHeating(meteringPointId, payload, cancellationToken); break; case SupplyType.Electricity: await BuildUpdatePayloadForElectricity(meteringPointId, payload, cancellationToken); break; } } private async Task BuildFormulaPayload( ChangeFormulaProcessCommandPayload payload, FormulaVersionDto? oldFormula, SupplyType supplyType, CancellationToken cancellationToken) { if (oldFormula is null) { _payloadBuilder.WithFormula(payload.Formula); return; } if (!payload.Formula.IsSimpleFormula && !HasVirtualFormulaChanged(payload, oldFormula)) { return; } if (payload.Formula.IsSimpleFormula && payload.Formula.MeterFrameId == oldFormula.MeterFrameId && payload.Formula.RegisterRequirementId == oldFormula.RegisterRequirementId) { return; } if (payload.Formula.MeterFrameId != oldFormula.MeterFrameId) { var meter = await BuildMeterPayload(payload, cancellationToken) ?? GetDefaultMeterData(supplyType); _payloadBuilder.WithMeterPayload(meter); } else if (payload.Formula.RegisterRequirementId != oldFormula.RegisterRequirementId) { var meter = await BuildMeterPayload(payload, cancellationToken) ?? GetDefaultMeterData(supplyType); _payloadBuilder.WithMeterInUpdatePayload(meter); } _payloadBuilder.WithFormula(payload.Formula); } private static bool HasVirtualFormulaChanged( ChangeFormulaProcessCommandPayload payload, FormulaVersionDto oldFormula) { if (payload.Formula.FormulaExpression != oldFormula.Formula) { return true; } if (payload.Formula.FormulaParameters == null && oldFormula.FormulaParameters == null) { return false; } if (payload.Formula.FormulaParameters == null || oldFormula.FormulaParameters == null) { return true; } if (payload.Formula.FormulaParameters.Count != oldFormula.FormulaParameters.Count) { return true; } var newFormulaParameters = payload.Formula.FormulaParameters.OrderBy(x => x.Name).ToList(); var oldFormulaParameters = oldFormula.FormulaParameters.OrderBy(x => x.Name).ToList(); return newFormulaParameters.Where((x, y) => AreFormulaParametersDifferent(x, oldFormulaParameters[y])).Any(); } private static bool AreFormulaParametersDifferent(FormulaParameter newFormula, FormulaParameterDto oldFormula) => newFormula.Name != oldFormula.Name || newFormula.FormulaParameterType.ToString() != oldFormula.FormulaParameterType.ToString() || newFormula.Description != oldFormula.Description || newFormula.MeteringPointTypeCode != oldFormula.MeteringPointTypeCode; private async Task<MeterUpdatePayload?> BuildMeterPayload(ChangeFormulaProcessCommandPayload payload, CancellationToken cancellationToken) { var meterFrameId = payload.Formula.MeterFrameId!.Value; var registerRequirementId = payload.Formula.RegisterRequirementId!.Value; var meterInformation = await meterFramesService.GetMeterInformationByMeterFrameRegisterRequirementAsync( meterFrameId, registerRequirementId, cancellationToken); if (string.IsNullOrEmpty(payload.SubTypeOfMeteringPoint)!) { if (payload.SubTypeOfMeteringPoint != _oldSubtypeOfMeteringPoint) { var functionCode = GetFunctionCode(_oldSubtypeOfMeteringPoint, payload.SubTypeOfMeteringPoint); return new MeterUpdatePayload() { ConversionFactor = meterInformation!.ConversionFactor, NumberOfDigits = meterInformation.NumberOfDigits, UnitType = meterInformation.UnitType, MeterNumber = meterInformation.MeterNumber, MeterReadingType = meterInformation.MeterReadingType, Function = functionCode, SubtypeOfMeteringPoint = payload.SubTypeOfMeteringPoint }; } return null; } if (meterInformation is null) { return null; } return new MeterUpdatePayload() { ConversionFactor = meterInformation!.ConversionFactor, NumberOfDigits = meterInformation.NumberOfDigits, UnitType = meterInformation.UnitType, MeterNumber = meterInformation.MeterNumber, MeterReadingType = meterInformation.MeterReadingType }; } private string? GetFunctionCode(string? oldSubtypeOfMeteringPoint, string? newSubTypeOfMeteringPoint) { if ((oldSubtypeOfMeteringPoint == SubTypesOfMeteringPoint.D02_Virtual || oldSubtypeOfMeteringPoint == SubTypesOfMeteringPoint.D03_Calculated) && newSubTypeOfMeteringPoint == SubTypesOfMeteringPoint.D01_Physical) { return "2"; } if ((newSubTypeOfMeteringPoint == SubTypesOfMeteringPoint.D02_Virtual || newSubTypeOfMeteringPoint == SubTypesOfMeteringPoint.D03_Calculated) && oldSubtypeOfMeteringPoint == SubTypesOfMeteringPoint.D01_Physical) { return "3"; } return null; } private static MeterUpdatePayload GetDefaultMeterData(SupplyType supplyType) => new() { ConversionFactor = 1, NumberOfDigits = "1", UnitType = supplyType is SupplyType.Water ? "M3" : "MWH", MeterNumber = "FIKTIV", MeterReadingType = "D01" }; private async Task BuildUpdatePayloadForWater( string meteringPointId, ChangeFormulaProcessCommandPayload payload, CancellationToken cancellationToken) { var meteringPointVersion = await meteringPointsService.GetWaterMeteringPointVersionAsync(meteringPointId, cancellationToken); if (meteringPointVersion == null) { throw new MeteringPointNotFoundException($"Metering point with id {meteringPointId} not found in Metering Points domain."); } if (meteringPointVersion.ConnectionPointId is null) { throw new MeteringPointProcessValidationException("Connection point id is missing on metering point."); } var connectionPointNumber = await GetConnectionPointNumber(meteringPointVersion.ConnectionPointId.Value, cancellationToken); if (connectionPointNumber is null) { throw new MeteringPointProcessValidationException("Connection point number is missing on metering point."); } _payloadBuilder.WithUnitType(payload.UnitType, meteringPointVersion.ProductUnitType) .WithMeterReadingOccurrence(payload.MeterReadingOccurrence, meteringPointVersion.MeterReadingOccurrence) .WithConnectionPointId(meteringPointVersion.ConnectionPointId!.Value) .WithNoMeterAndMeterSize(meteringPointVersion.NoMeter, meteringPointVersion.MeterSize) .WithConnectionPointNumber(connectionPointNumber) .WithTypeOfMeteringPoint(meteringPointVersion.TypeOfMeteringPoint!); } private async Task BuildUpdatePayloadForHeating( string meteringPointId, ChangeFormulaProcessCommandPayload payload, CancellationToken cancellationToken) { var meteringPointVersion = await meteringPointsService.GetHeatingMeteringPointVersionAsync(meteringPointId, cancellationToken); if (meteringPointVersion == null) { throw new MeteringPointNotFoundException($"Metering point with id {meteringPointId} not found in Metering Points domain."); } if (meteringPointVersion.ConnectionPointId is null) { throw new MeteringPointProcessValidationException("Connection point id is missing on metering point."); } var connectionPointNumber = await GetConnectionPointNumber(meteringPointVersion.ConnectionPointId!.Value, cancellationToken); if (connectionPointNumber is null) { throw new MeteringPointProcessValidationException("Connection point number is missing on metering point."); } _payloadBuilder.WithUnitType(payload.UnitType, meteringPointVersion.ProductUnitType) .WithMeterReadingOccurrence(payload.MeterReadingOccurrence, meteringPointVersion.MeterReadingOccurrence) .WithConnectionPointId(meteringPointVersion.ConnectionPointId!.Value) .WithConnectionPointNumber(connectionPointNumber) .WithTypeOfMeteringPoint(meteringPointVersion.TypeOfMeteringPoint!); } private async Task BuildUpdatePayloadForElectricity( string meteringPointId, ChangeFormulaProcessCommandPayload payload, CancellationToken cancellationToken) { var meteringPointVersion = await electricityMeteringPointsService.GetMeteringPointVersionByIdAsync(meteringPointId, cancellationToken); if (meteringPointVersion == null) { throw new MeteringPointNotFoundException($"Metering point with id {meteringPointId} not found in Metering Points domain."); } _oldSubtypeOfMeteringPoint = meteringPointVersion.SubTypeOfMeteringPoint; if (!ShouldCreateBrs006(meteringPointVersion.SubTypeOfMeteringPoint, payload.SubTypeOfMeteringPoint)) { return; } if (meteringPointVersion.ConnectionPointId is null) { throw new MeteringPointProcessValidationException("Connection point id is missing on metering point."); } var connectionPointNumber = await GetConnectionPointNumber(meteringPointVersion.ConnectionPointId!.Value, cancellationToken); if (connectionPointNumber is null) { throw new MeteringPointProcessValidationException("Connection point number is missing on metering point."); } _payloadBuilder.WithUnitType(payload.UnitType, meteringPointVersion.ProductUnitType) .WithMeterReadingOccurrence(payload.MeterReadingOccurrence, meteringPointVersion.MeterReadingOccurrence) .WithConnectionPointId(meteringPointVersion.ConnectionPointId!.Value) .WithConnectionPointNumber(connectionPointNumber) .WithTypeOfMeteringPoint(meteringPointVersion.TypeOfMeteringPoint!); } private bool ShouldCreateBrs006(string? oldSubtypeOfMeteringPoint, string? newSubTypeOfMeteringPoint) { if (oldSubtypeOfMeteringPoint == SubTypesOfMeteringPoint.D02_Virtual && newSubTypeOfMeteringPoint == SubTypesOfMeteringPoint.D03_Calculated) { return true; } if (oldSubtypeOfMeteringPoint == SubTypesOfMeteringPoint.D03_Calculated && newSubTypeOfMeteringPoint == SubTypesOfMeteringPoint.D02_Virtual) { return true; } return false; } private async Task<FormulaVersionDto?> GetFormulaPayload( string meteringPointVersionId, SupplyType supplyType, CancellationToken cancellationToken) { switch (supplyType) { case SupplyType.Heating: { var dto = await meteringPointsService.GetHeatingFormulaVersionAsync(meteringPointVersionId, cancellationToken); return dto; } case SupplyType.Water: { var dto = await meteringPointsService.GetWaterFormulaVersionAsync(meteringPointVersionId, cancellationToken); return dto; } case SupplyType.Electricity: default: throw new ArgumentOutOfRangeException(nameof(supplyType), supplyType, null); } } private async Task<string?> GetConnectionPointNumber( Guid connectionPointId, CancellationToken cancellationToken) { var connectionPoint = await connectionPointsService.GetConnectionPointAsync(connectionPointId, cancellationToken); return connectionPoint?.ConnectionPointNumber; } }
Leave a Comment