diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index bde72c3e..405a1dac 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -16,7 +16,7 @@ Add a brief description of the change(s) you have made - [ ] I have checked there are no unintentional line ending changes - [ ] I have added tests where applicable - [ ] If I have made any changes to the code, I have used the IDE auto-formatter on it -- [ ] If I have made any changes to website flow, I have updated the [Flow Miro Board](https://miro.com/app/board/uXjVK6F2rKo=/) +- [ ] If I have made any changes to website flow, I have updated the [Flow Miro Board](https://miro.com/app/board/uXjVK4BNrG0=/) - [ ] If I have made any changes to website flow, I have checked forward and back behaviour is still consistent - [ ] If I have made any changes to content strings or resource files, I have followed [the documentation](https://github.com/UKGovernmentBEIS/beis-simple-energy-advice-beta/blob/main/docs/LocalisationDocumentation.md) @@ -24,4 +24,4 @@ Add a brief description of the change(s) you have made \ No newline at end of file +--> diff --git a/.gitignore b/.gitignore index 6a089894..a01be2a2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # User preferences .idea +SimpleEnergyAdvice.sln.DotSettings.user +SimpleEnergyAdvice.sln.DotSettings # Dependencies node_modules/ diff --git a/SeaPublicWebsite.BusinessLogic/ExternalServices/Bre/BreRequest.cs b/SeaPublicWebsite.BusinessLogic/ExternalServices/Bre/BreRequest.cs index eeb037d7..63133849 100644 --- a/SeaPublicWebsite.BusinessLogic/ExternalServices/Bre/BreRequest.cs +++ b/SeaPublicWebsite.BusinessLogic/ExternalServices/Bre/BreRequest.cs @@ -34,6 +34,8 @@ public class BreRequest public int? roof_type { get; set; } + public bool? pv_panel { get; set; } + public int wall_type { get; set; } public int glazing_type { get; set; } @@ -57,7 +59,8 @@ public BreRequest( int[] breNormalDaysOffHours, decimal? breTemperature, BreFloorType? breFloorType, - bool? breOutsideSpace + bool? breOutsideSpace, + bool? brePvPanels ) { property_type = ((int) brePropertyType).ToString(); @@ -67,6 +70,7 @@ public BreRequest( wall_type = (int) breWallType; //no input for floor_type in BRE API roof_type = (int?) breRoofType; + pv_panel = brePvPanels; glazing_type = (int) breGlazingType; //no input for outdoor heater space in BRE API heating_system = (int) breHeatingSystem; diff --git a/SeaPublicWebsite.BusinessLogic/ExternalServices/Bre/RecommendationService.cs b/SeaPublicWebsite.BusinessLogic/ExternalServices/Bre/RecommendationService.cs index c3573f4b..a9adac1d 100644 --- a/SeaPublicWebsite.BusinessLogic/ExternalServices/Bre/RecommendationService.cs +++ b/SeaPublicWebsite.BusinessLogic/ExternalServices/Bre/RecommendationService.cs @@ -162,6 +162,8 @@ private static BreRequest CreateRequest(PropertyData propertyData) bool? breOutsideSpace = GetBreOutsideSpace(propertyData.HasOutdoorSpace); + bool? brePvPanels = GetBrePvPanels(propertyData.SolarElectricPanels); + BreRequest request = new( brePropertyType: brePropertyType, breBuiltForm: breBuiltForm, @@ -177,7 +179,8 @@ private static BreRequest CreateRequest(PropertyData propertyData) breNormalDaysOffHours: breNormalDaysOffHours, breTemperature: propertyData.Temperature, breFloorType: breFloorType, - breOutsideSpace: breOutsideSpace + breOutsideSpace: breOutsideSpace, + brePvPanels: brePvPanels ); return request; @@ -540,5 +543,17 @@ private static bool GetBreOutsideSpace(HasOutdoorSpace? hasOutdoorSpace) _ => throw new ArgumentOutOfRangeException() }; } + + private static bool? GetBrePvPanels(SolarElectricPanels? solarElectricPanels) + { + return solarElectricPanels switch + { + SolarElectricPanels.Yes => true, + SolarElectricPanels.No => false, + SolarElectricPanels.DoNotKnow => false, + null => null, + _ => throw new ArgumentOutOfRangeException() + }; + } } } \ No newline at end of file diff --git a/SeaPublicWebsite.BusinessLogic/Models/Enums/QuestionFlowStep.cs b/SeaPublicWebsite.BusinessLogic/Models/Enums/QuestionFlowStep.cs index 7c59965d..3b7cf507 100644 --- a/SeaPublicWebsite.BusinessLogic/Models/Enums/QuestionFlowStep.cs +++ b/SeaPublicWebsite.BusinessLogic/Models/Enums/QuestionFlowStep.cs @@ -24,6 +24,7 @@ public enum QuestionFlowStep FloorConstruction, FloorInsulated, RoofConstruction, + SolarElectricPanels, LoftSpace, LoftAccess, RoofInsulated, diff --git a/SeaPublicWebsite.BusinessLogic/Models/Enums/SolarElectricPanels.cs b/SeaPublicWebsite.BusinessLogic/Models/Enums/SolarElectricPanels.cs new file mode 100644 index 00000000..6d855881 --- /dev/null +++ b/SeaPublicWebsite.BusinessLogic/Models/Enums/SolarElectricPanels.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; + +namespace SeaPublicWebsite.BusinessLogic.Models.Enums +{ + public enum SolarElectricPanels + { + [Display(ResourceType = typeof(Resources.Enum.SolarElectricPanels), Description = nameof(Resources.Enum.SolarElectricPanels.Yes))] + Yes, + [Display(ResourceType = typeof(Resources.Enum.SolarElectricPanels), Description = nameof(Resources.Enum.SolarElectricPanels.No))] + No, + [Display(ResourceType = typeof(Resources.Enum.SolarElectricPanels), Description = nameof(Resources.Enum.SolarElectricPanels.DoNotKnow))] + DoNotKnow + } +} \ No newline at end of file diff --git a/SeaPublicWebsite.BusinessLogic/Models/PropertyData.cs b/SeaPublicWebsite.BusinessLogic/Models/PropertyData.cs index b27f20e3..2e18a4b8 100644 --- a/SeaPublicWebsite.BusinessLogic/Models/PropertyData.cs +++ b/SeaPublicWebsite.BusinessLogic/Models/PropertyData.cs @@ -37,6 +37,7 @@ public class PropertyData public FloorConstruction? FloorConstruction { get; set; } public FloorInsulated? FloorInsulated { get; set; } public RoofConstruction? RoofConstruction { get; set; } + public SolarElectricPanels? SolarElectricPanels { get; set; } public LoftSpace? LoftSpace { get; set; } public LoftAccess? LoftAccess { get; set; } public RoofInsulated? RoofInsulated { get; set; } @@ -140,6 +141,7 @@ public void ResetUnusedFields() if (!HasRoof()) { RoofConstruction = null; + SolarElectricPanels = null; } if (RoofConstruction is not Enums.RoofConstruction.Mixed and not Enums.RoofConstruction.Pitched) diff --git a/SeaPublicWebsite.BusinessLogic/PropertyDataUpdater.cs b/SeaPublicWebsite.BusinessLogic/PropertyDataUpdater.cs index aaa7d418..78077a80 100644 --- a/SeaPublicWebsite.BusinessLogic/PropertyDataUpdater.cs +++ b/SeaPublicWebsite.BusinessLogic/PropertyDataUpdater.cs @@ -226,6 +226,18 @@ public QuestionFlowStep UpdateRoofConstruction( entryPoint); } + public QuestionFlowStep UpdateSolarElectricPanels( + PropertyData propertyData, + SolarElectricPanels? solarElectricPanels, + QuestionFlowStep? entryPoint) + { + return UpdatePropertyData( + p => { p.SolarElectricPanels = solarElectricPanels; }, + propertyData, + QuestionFlowStep.SolarElectricPanels, + entryPoint); + } + public QuestionFlowStep UpdateLoftSpace( PropertyData propertyData, LoftSpace? loftSpace, diff --git a/SeaPublicWebsite.BusinessLogic/Resources/Enum/SolarElectricPanels.Designer.cs b/SeaPublicWebsite.BusinessLogic/Resources/Enum/SolarElectricPanels.Designer.cs new file mode 100644 index 00000000..4c40ccfe --- /dev/null +++ b/SeaPublicWebsite.BusinessLogic/Resources/Enum/SolarElectricPanels.Designer.cs @@ -0,0 +1,89 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SeaPublicWebsite.BusinessLogic.Resources.Enum { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class SolarElectricPanels { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal SolarElectricPanels() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SeaPublicWebsite.BusinessLogic.Resources.Enum.SolarElectricPanels", typeof(SolarElectricPanels).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to I don't know. + /// + public static string DoNotKnow { + get { + return ResourceManager.GetString("DoNotKnow", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No. + /// + public static string No { + get { + return ResourceManager.GetString("No", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Yes. + /// + public static string Yes { + get { + return ResourceManager.GetString("Yes", resourceCulture); + } + } + } +} diff --git a/SeaPublicWebsite.BusinessLogic/Resources/Enum/SolarElectricPanels.cy.resx b/SeaPublicWebsite.BusinessLogic/Resources/Enum/SolarElectricPanels.cy.resx new file mode 100644 index 00000000..00b04580 --- /dev/null +++ b/SeaPublicWebsite.BusinessLogic/Resources/Enum/SolarElectricPanels.cy.resx @@ -0,0 +1,23 @@ + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Oes + + + Nac oes + + + Ddim yn gwybod + + \ No newline at end of file diff --git a/SeaPublicWebsite.BusinessLogic/Resources/Enum/SolarElectricPanels.resx b/SeaPublicWebsite.BusinessLogic/Resources/Enum/SolarElectricPanels.resx new file mode 100644 index 00000000..115020b0 --- /dev/null +++ b/SeaPublicWebsite.BusinessLogic/Resources/Enum/SolarElectricPanels.resx @@ -0,0 +1,30 @@ + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Yes + + + No + + + I don't know + + \ No newline at end of file diff --git a/SeaPublicWebsite.BusinessLogic/SeaPublicWebsite.BusinessLogic.csproj b/SeaPublicWebsite.BusinessLogic/SeaPublicWebsite.BusinessLogic.csproj index 83f3a309..cc81a71f 100644 --- a/SeaPublicWebsite.BusinessLogic/SeaPublicWebsite.BusinessLogic.csproj +++ b/SeaPublicWebsite.BusinessLogic/SeaPublicWebsite.BusinessLogic.csproj @@ -135,6 +135,10 @@ PublicResXFileCodeGenerator BreBuiltForm.Designer.cs + + PublicResXFileCodeGenerator + SolarElectricPanels.Designer.cs + diff --git a/SeaPublicWebsite.BusinessLogic/Services/QuestionFlowService.cs b/SeaPublicWebsite.BusinessLogic/Services/QuestionFlowService.cs index 830b1f36..d100b2eb 100644 --- a/SeaPublicWebsite.BusinessLogic/Services/QuestionFlowService.cs +++ b/SeaPublicWebsite.BusinessLogic/Services/QuestionFlowService.cs @@ -46,6 +46,7 @@ public QuestionFlowStep PreviousStep( QuestionFlowStep.LoftSpace => LoftSpaceBackDestination(entryPoint), QuestionFlowStep.LoftAccess => LoftAccessBackDestination(entryPoint), QuestionFlowStep.RoofInsulated => RoofInsulatedBackDestination(entryPoint), + QuestionFlowStep.SolarElectricPanels => SolarElectricPanelsBackDestination(propertyData, entryPoint), QuestionFlowStep.OutdoorSpace => OutdoorSpaceBackDestination(entryPoint), QuestionFlowStep.GlazingType => GlazingTypeBackDestination(propertyData, entryPoint), QuestionFlowStep.HeatingType => HeatingTypeBackDestination(entryPoint), @@ -88,6 +89,7 @@ public QuestionFlowStep NextStep(QuestionFlowStep page, PropertyData propertyDat QuestionFlowStep.LoftSpace => LoftSpaceForwardDestination(propertyData, entryPoint), QuestionFlowStep.LoftAccess => LoftAccessForwardDestination(propertyData, entryPoint), QuestionFlowStep.RoofInsulated => RoofInsulatedForwardDestination(entryPoint), + QuestionFlowStep.SolarElectricPanels => SolarElectricPanelsForwardDestination(entryPoint), QuestionFlowStep.OutdoorSpace => OutdoorSpaceForwardDestination(entryPoint), QuestionFlowStep.GlazingType => GlazingTypeForwardDestination(entryPoint), QuestionFlowStep.HeatingType => HeatingTypeForwardDestination(propertyData, entryPoint), @@ -325,6 +327,25 @@ private QuestionFlowStep RoofInsulatedBackDestination(QuestionFlowStep? entryPoi ? QuestionFlowStep.AnswerSummary : QuestionFlowStep.LoftAccess; } + + private QuestionFlowStep SolarElectricPanelsBackDestination(PropertyData propertyData, QuestionFlowStep? entryPoint) + { + if (entryPoint is QuestionFlowStep.SolarElectricPanels) + { + return QuestionFlowStep.AnswerSummary; + } + + return propertyData switch + { + { RoofConstruction: RoofConstruction.Flat } + => QuestionFlowStep.RoofConstruction, + { LoftSpace: not LoftSpace.Yes } + => QuestionFlowStep.LoftSpace, + { LoftAccess: not LoftAccess.Yes } + => QuestionFlowStep.LoftAccess, + _ => QuestionFlowStep.RoofInsulated + }; + } private QuestionFlowStep GlazingTypeBackDestination(PropertyData propertyData, QuestionFlowStep? entryPoint) { @@ -335,16 +356,7 @@ private QuestionFlowStep GlazingTypeBackDestination(PropertyData propertyData, Q if (propertyData.HasRoof()) { - return propertyData switch - { - { RoofConstruction: RoofConstruction.Flat } - => QuestionFlowStep.RoofConstruction, - { LoftSpace: not LoftSpace.Yes } - => QuestionFlowStep.LoftSpace, - { LoftAccess: not LoftAccess.Yes } - => QuestionFlowStep.LoftAccess, - _ => QuestionFlowStep.RoofInsulated - }; + return QuestionFlowStep.SolarElectricPanels; } if (propertyData.HasFloor()) @@ -674,15 +686,15 @@ private QuestionFlowStep RoofConstructionForwardDestination(PropertyData propert { return QuestionFlowStep.LoftSpace; } - + if (entryPoint is not null) { return QuestionFlowStep.AnswerSummary; } - return QuestionFlowStep.GlazingType; + return QuestionFlowStep.SolarElectricPanels; } - + private QuestionFlowStep LoftSpaceForwardDestination(PropertyData propertyData, QuestionFlowStep? entryPoint) { if (propertyData.LoftSpace is LoftSpace.Yes) @@ -695,7 +707,7 @@ private QuestionFlowStep LoftSpaceForwardDestination(PropertyData propertyData, return QuestionFlowStep.AnswerSummary; } - return QuestionFlowStep.GlazingType; + return QuestionFlowStep.SolarElectricPanels; } private QuestionFlowStep LoftAccessForwardDestination(PropertyData propertyData, QuestionFlowStep? entryPoint) @@ -710,14 +722,19 @@ private QuestionFlowStep LoftAccessForwardDestination(PropertyData propertyData, return QuestionFlowStep.AnswerSummary; } - return QuestionFlowStep.GlazingType; + return QuestionFlowStep.SolarElectricPanels; } private QuestionFlowStep RoofInsulatedForwardDestination(QuestionFlowStep? entryPoint) { return entryPoint is not null ? QuestionFlowStep.AnswerSummary - : QuestionFlowStep.GlazingType; + : QuestionFlowStep.SolarElectricPanels; + } + + private QuestionFlowStep SolarElectricPanelsForwardDestination(QuestionFlowStep? entryPoint) + { + return entryPoint is not null ? QuestionFlowStep.AnswerSummary : QuestionFlowStep.GlazingType; } private QuestionFlowStep GlazingTypeForwardDestination(QuestionFlowStep? entryPoint) diff --git a/SeaPublicWebsite.Data/Migrations/20241129102009_AddSolarPVAnswer.Designer.cs b/SeaPublicWebsite.Data/Migrations/20241129102009_AddSolarPVAnswer.Designer.cs new file mode 100644 index 00000000..ac81d637 --- /dev/null +++ b/SeaPublicWebsite.Data/Migrations/20241129102009_AddSolarPVAnswer.Designer.cs @@ -0,0 +1,333 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using SeaPublicWebsite.Data; + +#nullable disable + +namespace SeaPublicWebsite.Data.Migrations +{ + [DbContext(typeof(SeaDbContext))] + [Migration("20241129102009_AddSolarPVAnswer")] + partial class AddSolarPVAnswer + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FriendlyName") + .HasColumnType("text"); + + b.Property("Xml") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("DataProtectionKeys"); + }); + + modelBuilder.Entity("SeaPublicWebsite.BusinessLogic.Models.Epc", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BungalowType") + .HasColumnType("integer"); + + b.Property("CavityWallsInsulated") + .HasColumnType("integer"); + + b.Property("ConstructionAgeBand") + .HasColumnType("integer"); + + b.Property("EpcHeatingType") + .HasColumnType("integer"); + + b.Property("FlatType") + .HasColumnType("integer"); + + b.Property("FloorConstruction") + .HasColumnType("integer"); + + b.Property("FloorInsulated") + .HasColumnType("integer"); + + b.Property("GlazingType") + .HasColumnType("integer"); + + b.Property("HasHotWaterCylinder") + .HasColumnType("integer"); + + b.Property("HouseType") + .HasColumnType("integer"); + + b.Property("LodgementYear") + .HasColumnType("integer"); + + b.Property("PropertyDataId") + .HasColumnType("integer"); + + b.Property("PropertyType") + .HasColumnType("integer"); + + b.Property("RoofConstruction") + .HasColumnType("integer"); + + b.Property("RoofInsulated") + .HasColumnType("integer"); + + b.Property("SolidWallsInsulated") + .HasColumnType("integer"); + + b.Property("WallConstruction") + .HasColumnType("integer"); + + b.Property("xmin") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid"); + + b.HasKey("Id"); + + b.HasIndex("PropertyDataId") + .IsUnique(); + + b.ToTable("Epc"); + }); + + modelBuilder.Entity("SeaPublicWebsite.BusinessLogic.Models.PropertyData", b => + { + b.Property("PropertyDataId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PropertyDataId")); + + b.Property("BungalowType") + .HasColumnType("integer"); + + b.Property("CavityWallsInsulated") + .HasColumnType("integer"); + + b.Property("Country") + .HasColumnType("integer"); + + b.Property("EditedDataId") + .HasColumnType("integer"); + + b.Property("EpcDetailsConfirmed") + .HasColumnType("integer"); + + b.Property("FlatType") + .HasColumnType("integer"); + + b.Property("FloorConstruction") + .HasColumnType("integer"); + + b.Property("FloorInsulated") + .HasColumnType("integer"); + + b.Property("GlazingType") + .HasColumnType("integer"); + + b.Property("HasHotWaterCylinder") + .HasColumnType("integer"); + + b.Property("HasOutdoorSpace") + .HasColumnType("integer"); + + b.Property("HasSeenRecommendations") + .HasColumnType("boolean"); + + b.Property("HeatingPattern") + .HasColumnType("integer"); + + b.Property("HeatingType") + .HasColumnType("integer"); + + b.Property("HoursOfHeatingEvening") + .HasColumnType("integer"); + + b.Property("HoursOfHeatingMorning") + .HasColumnType("integer"); + + b.Property("HouseType") + .HasColumnType("integer"); + + b.Property("LoftAccess") + .HasColumnType("integer"); + + b.Property("LoftSpace") + .HasColumnType("integer"); + + b.Property("NumberOfOccupants") + .HasColumnType("integer"); + + b.Property("OtherHeatingType") + .HasColumnType("integer"); + + b.Property("OwnershipStatus") + .HasColumnType("integer"); + + b.Property("PropertyType") + .HasColumnType("integer"); + + b.Property("RecommendationsFirstRetrievedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Reference") + .HasColumnType("text"); + + b.Property("ReturningUser") + .HasColumnType("boolean"); + + b.Property("RoofConstruction") + .HasColumnType("integer"); + + b.Property("RoofInsulated") + .HasColumnType("integer"); + + b.Property("SearchForEpc") + .HasColumnType("integer"); + + b.Property("SolarElectricPanels") + .HasColumnType("integer"); + + b.Property("SolidWallsInsulated") + .HasColumnType("integer"); + + b.Property("Temperature") + .HasColumnType("numeric"); + + b.Property("WallConstruction") + .HasColumnType("integer"); + + b.Property("YearBuilt") + .HasColumnType("integer"); + + b.Property("xmin") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid"); + + b.HasKey("PropertyDataId"); + + b.HasIndex("EditedDataId") + .IsUnique(); + + b.HasIndex("Reference") + .IsUnique(); + + b.ToTable("PropertyData"); + }); + + modelBuilder.Entity("SeaPublicWebsite.BusinessLogic.Models.PropertyRecommendation", b => + { + b.Property("PropertyRecommendationId") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("PropertyRecommendationId")); + + b.Property("Key") + .HasColumnType("integer"); + + b.Property("Lifetime") + .HasColumnType("integer"); + + b.Property("LifetimeSaving") + .HasColumnType("integer"); + + b.Property("MaxInstallCost") + .HasColumnType("integer"); + + b.Property("MinInstallCost") + .HasColumnType("integer"); + + b.Property("PropertyDataId") + .HasColumnType("integer"); + + b.Property("RecommendationAction") + .HasColumnType("integer"); + + b.Property("Saving") + .HasColumnType("integer"); + + b.Property("Summary") + .HasColumnType("text"); + + b.Property("Title") + .HasColumnType("text"); + + b.Property("xmin") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid"); + + b.HasKey("PropertyRecommendationId"); + + b.HasIndex("PropertyDataId"); + + b.ToTable("PropertyRecommendations"); + }); + + modelBuilder.Entity("SeaPublicWebsite.BusinessLogic.Models.Epc", b => + { + b.HasOne("SeaPublicWebsite.BusinessLogic.Models.PropertyData", null) + .WithOne("Epc") + .HasForeignKey("SeaPublicWebsite.BusinessLogic.Models.Epc", "PropertyDataId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("SeaPublicWebsite.BusinessLogic.Models.PropertyData", b => + { + b.HasOne("SeaPublicWebsite.BusinessLogic.Models.PropertyData", null) + .WithOne("UneditedData") + .HasForeignKey("SeaPublicWebsite.BusinessLogic.Models.PropertyData", "EditedDataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("SeaPublicWebsite.BusinessLogic.Models.PropertyRecommendation", b => + { + b.HasOne("SeaPublicWebsite.BusinessLogic.Models.PropertyData", "PropertyData") + .WithMany("PropertyRecommendations") + .HasForeignKey("PropertyDataId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PropertyData"); + }); + + modelBuilder.Entity("SeaPublicWebsite.BusinessLogic.Models.PropertyData", b => + { + b.Navigation("Epc"); + + b.Navigation("PropertyRecommendations"); + + b.Navigation("UneditedData"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/SeaPublicWebsite.Data/Migrations/20241129102009_AddSolarPVAnswer.cs b/SeaPublicWebsite.Data/Migrations/20241129102009_AddSolarPVAnswer.cs new file mode 100644 index 00000000..34cc4fa5 --- /dev/null +++ b/SeaPublicWebsite.Data/Migrations/20241129102009_AddSolarPVAnswer.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace SeaPublicWebsite.Data.Migrations +{ + public partial class AddSolarPVAnswer : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SolarElectricPanels", + table: "PropertyData", + type: "integer", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SolarElectricPanels", + table: "PropertyData"); + } + } +} diff --git a/SeaPublicWebsite.Data/Migrations/SeaDbContextModelSnapshot.cs b/SeaPublicWebsite.Data/Migrations/SeaDbContextModelSnapshot.cs index 271a2b04..0bdde940 100644 --- a/SeaPublicWebsite.Data/Migrations/SeaDbContextModelSnapshot.cs +++ b/SeaPublicWebsite.Data/Migrations/SeaDbContextModelSnapshot.cs @@ -208,6 +208,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("SearchForEpc") .HasColumnType("integer"); + b.Property("SolarElectricPanels") + .HasColumnType("integer"); + b.Property("SolidWallsInsulated") .HasColumnType("integer"); diff --git a/SeaPublicWebsite.UnitTests/BreApi.cs b/SeaPublicWebsite.UnitTests/BreApi.cs index d141c7d8..fc3e612c 100644 --- a/SeaPublicWebsite.UnitTests/BreApi.cs +++ b/SeaPublicWebsite.UnitTests/BreApi.cs @@ -26,7 +26,8 @@ public void BreRequestMeasuresShouldBeTrue() breNormalDaysOffHours: null, breTemperature: null, breFloorType: BreFloorType.DontKnow, - breOutsideSpace: true + breOutsideSpace: true, + brePvPanels: false ); // Assert diff --git a/SeaPublicWebsite.UnitTests/BusinessLogic/Models/PropertyDataTests.cs b/SeaPublicWebsite.UnitTests/BusinessLogic/Models/PropertyDataTests.cs index c23dbb2d..2b05241e 100644 --- a/SeaPublicWebsite.UnitTests/BusinessLogic/Models/PropertyDataTests.cs +++ b/SeaPublicWebsite.UnitTests/BusinessLogic/Models/PropertyDataTests.cs @@ -45,6 +45,7 @@ private PropertyData InitializePropertyData() Temperature = 20, UneditedData = new PropertyData(), HasSeenRecommendations = false, + SolarElectricPanels = SolarElectricPanels.Yes, RecommendationsFirstRetrievedAt = DateTime.Now.ToUniversalTime(), PropertyRecommendations = new List { diff --git a/SeaPublicWebsite.UnitTests/BusinessLogic/Models/ResetUnusedFieldsTests.cs b/SeaPublicWebsite.UnitTests/BusinessLogic/Models/ResetUnusedFieldsTests.cs index f1f89dab..59f06124 100644 --- a/SeaPublicWebsite.UnitTests/BusinessLogic/Models/ResetUnusedFieldsTests.cs +++ b/SeaPublicWebsite.UnitTests/BusinessLogic/Models/ResetUnusedFieldsTests.cs @@ -119,7 +119,8 @@ public void RunResetUnusedFieldTestCases(ResetUnusedFieldsTestCase testCase) FlatType = FlatType.GroundFloor, RoofConstruction = RoofConstruction.Mixed, LoftSpace = LoftSpace.Yes, - RoofInsulated = RoofInsulated.Yes + RoofInsulated = RoofInsulated.Yes, + SolarElectricPanels = SolarElectricPanels.Yes }, new() { @@ -137,7 +138,8 @@ public void RunResetUnusedFieldTestCases(ResetUnusedFieldsTestCase testCase) FloorInsulated = FloorInsulated.Yes, RoofConstruction = RoofConstruction.Mixed, LoftSpace = LoftSpace.Yes, - RoofInsulated = RoofInsulated.Yes + RoofInsulated = RoofInsulated.Yes, + SolarElectricPanels = SolarElectricPanels.Yes }, new() { diff --git a/SeaPublicWebsite.UnitTests/BusinessLogic/Services/QuestionFlowServiceTests.cs b/SeaPublicWebsite.UnitTests/BusinessLogic/Services/QuestionFlowServiceTests.cs index b012d983..4d7ca647 100644 --- a/SeaPublicWebsite.UnitTests/BusinessLogic/Services/QuestionFlowServiceTests.cs +++ b/SeaPublicWebsite.UnitTests/BusinessLogic/Services/QuestionFlowServiceTests.cs @@ -401,6 +401,55 @@ public void RunSkipLinkTestCases(QuestionFlowServiceTestCase testCase) entryPoint: QuestionFlowStep.RoofConstruction ), QuestionFlowStep.AnswerSummary), + new( + "Solar (PV) panels goes back to roof construction if the user has flat roof", + new Input( + QuestionFlowStep.SolarElectricPanels, + "ABCDEFGH", + propertyType: PropertyType.House, + roofConstruction: RoofConstruction.Flat + ), + QuestionFlowStep.RoofConstruction), + new( + "Solar (PV) panels goes back to loft space if the user does not have flat roof nor loft space", + new Input( + QuestionFlowStep.SolarElectricPanels, + "ABCDEFGH", + propertyType: PropertyType.House, + roofConstruction: RoofConstruction.Pitched, + loftSpace: LoftSpace.No + ), + QuestionFlowStep.LoftSpace), + new( + "Solar (PV) panels goes back to loft access if the user does not have flat roof and has inaccessible loft space", + new Input( + QuestionFlowStep.SolarElectricPanels, + "ABCDEFGH", + propertyType: PropertyType.House, + roofConstruction: RoofConstruction.Pitched, + loftSpace: LoftSpace.Yes, + accessibleLoft: LoftAccess.No + ), + QuestionFlowStep.LoftAccess), + new( + "Solar (PV) panels goes back to roof insulation if the user does not have flat roof but has accessible loft space", + new Input( + QuestionFlowStep.SolarElectricPanels, + "ABCDEFGH", + propertyType: PropertyType.House, + roofConstruction: RoofConstruction.Pitched, + loftSpace: LoftSpace.Yes, + accessibleLoft: LoftAccess.Yes + ), + QuestionFlowStep.RoofInsulated), + new( + "Changing solar (PV) panels goes back to summary", + new Input( + QuestionFlowStep.SolarElectricPanels, + "ABCDEFGH", + entryPoint: QuestionFlowStep.SolarElectricPanels + ), + QuestionFlowStep.AnswerSummary), new( "Loft space goes back to roof construction", new Input( @@ -447,46 +496,14 @@ public void RunSkipLinkTestCases(QuestionFlowServiceTestCase testCase) ), QuestionFlowStep.AnswerSummary), new( - "Glazing type goes back to roof construction if the user has flat roof", + "Glazing type goes back to solar (PV) panels if the user has flat roof", new Input( QuestionFlowStep.GlazingType, "ABCDEFGH", propertyType: PropertyType.House, roofConstruction: RoofConstruction.Flat ), - QuestionFlowStep.RoofConstruction), - new( - "Glazing type goes back to loft space if the user does not have flat roof nor loft space", - new Input( - QuestionFlowStep.GlazingType, - "ABCDEFGH", - propertyType: PropertyType.House, - roofConstruction: RoofConstruction.Pitched, - loftSpace: LoftSpace.No - ), - QuestionFlowStep.LoftSpace), - new( - "Glazing type goes back to loft access if the user does not have flat roof and has inaccessible loft space", - new Input( - QuestionFlowStep.GlazingType, - "ABCDEFGH", - propertyType: PropertyType.House, - roofConstruction: RoofConstruction.Pitched, - loftSpace: LoftSpace.Yes, - accessibleLoft: LoftAccess.No - ), - QuestionFlowStep.LoftAccess), - new( - "Glazing type goes back to roof insulation if the user does not have flat roof but has accessible loft space", - new Input( - QuestionFlowStep.GlazingType, - "ABCDEFGH", - propertyType: PropertyType.House, - roofConstruction: RoofConstruction.Pitched, - loftSpace: LoftSpace.Yes, - accessibleLoft: LoftAccess.Yes - ), - QuestionFlowStep.RoofInsulated), + QuestionFlowStep.SolarElectricPanels), new( "Glazing type goes back to floor construction if the user was not asked about their roof", new Input( @@ -1060,21 +1077,12 @@ public void RunSkipLinkTestCases(QuestionFlowServiceTestCase testCase) ), QuestionFlowStep.GlazingType), new( - "Roof construction continues to loft space if roof is pitched", + "Roof construction continues to solar (PV) panels", new Input( QuestionFlowStep.RoofConstruction, - "ABCDEFGH", - roofConstruction: RoofConstruction.Pitched - ), - QuestionFlowStep.LoftSpace), - new( - "Roof construction continues to loft space if roof is mixed", - new Input( - QuestionFlowStep.RoofConstruction, - "ABCDEFGH", - roofConstruction: RoofConstruction.Mixed + "ABCDEFGH" ), - QuestionFlowStep.LoftSpace), + QuestionFlowStep.SolarElectricPanels), new( "Changing roof construction continues to summary if roof is not pitched", new Input( @@ -1085,13 +1093,20 @@ public void RunSkipLinkTestCases(QuestionFlowServiceTestCase testCase) ), QuestionFlowStep.AnswerSummary), new( - "Roof construction continues to glazing type space if roof is not pitched", + "Solar (PV) panels continues to glazing type", new Input( - QuestionFlowStep.RoofConstruction, - "ABCDEFGH", - roofConstruction: RoofConstruction.Flat + QuestionFlowStep.SolarElectricPanels, + "ABCDEFGH" ), QuestionFlowStep.GlazingType), + new( + "Changing solar (PV) panels continues to summary", + new Input( + QuestionFlowStep.SolarElectricPanels, + "ABCDEFGH", + entryPoint: QuestionFlowStep.SolarElectricPanels + ), + QuestionFlowStep.AnswerSummary), new( "Loft space continues to loft access if user has it", new Input( @@ -1110,13 +1125,13 @@ public void RunSkipLinkTestCases(QuestionFlowServiceTestCase testCase) ), QuestionFlowStep.AnswerSummary), new( - "Loft space continues to glazing type if user does not have it", + "Loft space continues to Solar (PV) panels if user does not have it", new Input( QuestionFlowStep.LoftSpace, "ABCDEFGH", loftSpace: LoftSpace.No ), - QuestionFlowStep.GlazingType), + QuestionFlowStep.SolarElectricPanels), new( "Loft access continues to roof insulation if user has it", new Input( @@ -1144,20 +1159,20 @@ public void RunSkipLinkTestCases(QuestionFlowServiceTestCase testCase) ), QuestionFlowStep.AnswerSummary), new( - "Loft access continues to glazing type if user does not have it", + "Loft access continues to Solar (PV) panels if user does not have it", new Input( QuestionFlowStep.LoftAccess, "ABCDEFGH", loftSpace: LoftSpace.No ), - QuestionFlowStep.GlazingType), + QuestionFlowStep.SolarElectricPanels), new( - "Roof insulated continues to glazing type", + "Roof insulated continues to Solar (PV) type", new Input( QuestionFlowStep.RoofInsulated, "ABCDEFGH" ), - QuestionFlowStep.GlazingType), + QuestionFlowStep.SolarElectricPanels), new( "Changing roof insulated continues to summary", new Input( diff --git a/SeaPublicWebsite/Controllers/EnergyEfficiencyController.cs b/SeaPublicWebsite/Controllers/EnergyEfficiencyController.cs index 179f793a..be99370f 100644 --- a/SeaPublicWebsite/Controllers/EnergyEfficiencyController.cs +++ b/SeaPublicWebsite/Controllers/EnergyEfficiencyController.cs @@ -806,6 +806,39 @@ public async Task RoofConstruction_Post(RoofConstructionViewModel return RedirectToNextStep(nextStep, viewModel.Reference, viewModel.EntryPoint); } + + [HttpGet("solar-electric-panels/{reference}")] + public async Task SolarElectricPanels_Get(string reference, QuestionFlowStep? entryPoint = null) + { + var propertyData = await propertyDataStore.LoadPropertyDataAsync(reference); + + var viewModel = new SolarElectricPanelsViewModel + { + SolarElectricPanels = propertyData.SolarElectricPanels, + Reference = propertyData.Reference, + Epc = propertyData.Epc, + EntryPoint = entryPoint, + BackLink = GetBackUrl(QuestionFlowStep.SolarElectricPanels, propertyData, entryPoint) + }; + + return View("SolarElectricPanels", viewModel); + } + + [HttpPost("solar-electric-panels/{reference}")] + public async Task SolarElectricPanels_Post(SolarElectricPanelsViewModel viewModel) + { + if (!ModelState.IsValid) + { + return await SolarElectricPanels_Get(viewModel.Reference, viewModel.EntryPoint); + } + + var nextStep = await answerService.UpdateSolarElectricPanels( + viewModel.Reference, + viewModel.SolarElectricPanels, + viewModel.EntryPoint); + + return RedirectToNextStep(nextStep, viewModel.Reference, viewModel.EntryPoint); + } [HttpGet("loft-space/{reference}")] public async Task LoftSpace_Get(string reference, QuestionFlowStep? entryPoint = null) @@ -1590,6 +1623,7 @@ private PathByActionArguments GetActionArgumentsForQuestion( QuestionFlowStep.FloorConstruction => new PathByActionArguments(nameof(FloorConstruction_Get), "EnergyEfficiency", GetRouteValues(reference, extraRouteValues, entryPoint)), QuestionFlowStep.FloorInsulated => new PathByActionArguments(nameof(FloorInsulated_Get), "EnergyEfficiency", GetRouteValues(reference, extraRouteValues, entryPoint)), QuestionFlowStep.RoofConstruction => new PathByActionArguments(nameof(RoofConstruction_Get), "EnergyEfficiency", GetRouteValues(reference, extraRouteValues, entryPoint)), + QuestionFlowStep.SolarElectricPanels => new PathByActionArguments(nameof(SolarElectricPanels_Get), "EnergyEfficiency", GetRouteValues(reference, extraRouteValues, entryPoint)), QuestionFlowStep.LoftSpace => new PathByActionArguments(nameof(LoftSpace_Get), "EnergyEfficiency", GetRouteValues(reference, extraRouteValues, entryPoint)), QuestionFlowStep.LoftAccess => new PathByActionArguments(nameof(LoftAccess_Get), "EnergyEfficiency", GetRouteValues(reference, extraRouteValues, entryPoint)), QuestionFlowStep.RoofInsulated => new PathByActionArguments(nameof(RoofInsulated_Get), "EnergyEfficiency", GetRouteValues(reference, extraRouteValues, entryPoint)), diff --git a/SeaPublicWebsite/Models/EnergyEfficiency/SolarElectricPanelsViewModel.cs b/SeaPublicWebsite/Models/EnergyEfficiency/SolarElectricPanelsViewModel.cs new file mode 100644 index 00000000..28284819 --- /dev/null +++ b/SeaPublicWebsite/Models/EnergyEfficiency/SolarElectricPanelsViewModel.cs @@ -0,0 +1,16 @@ +using GovUkDesignSystem.Attributes.ValidationAttributes; +using SeaPublicWebsite.BusinessLogic.Models; +using SeaPublicWebsite.BusinessLogic.Models.Enums; +using SeaPublicWebsite.Resources; + +namespace SeaPublicWebsite.Models.EnergyEfficiency +{ + public class SolarElectricPanelsViewModel : QuestionFlowViewModel + { + [GovUkValidateRequired(ErrorMessageResourceType = typeof(ErrorMessages), ErrorMessageResourceName = nameof(ErrorMessages.SolarElectricPanelsRequired))] + public SolarElectricPanels? SolarElectricPanels { get; set; } + + public string Reference { get; set; } + public Epc Epc { get; set; } + } +} \ No newline at end of file diff --git a/SeaPublicWebsite/Resources/ErrorMessages.Designer.cs b/SeaPublicWebsite/Resources/ErrorMessages.Designer.cs index 7192d0d5..85d8ebd8 100644 --- a/SeaPublicWebsite/Resources/ErrorMessages.Designer.cs +++ b/SeaPublicWebsite/Resources/ErrorMessages.Designer.cs @@ -392,6 +392,15 @@ internal static string SelectPropertyCountryRequired { } } + /// + /// Looks up a localized string similar to Select if you have solar panels. + /// + internal static string SolarElectricPanelsRequired { + get { + return ResourceManager.GetString("SolarElectricPanelsRequired", resourceCulture); + } + } + /// /// Looks up a localized string similar to Select if your solid walls are insulated. /// diff --git a/SeaPublicWebsite/Resources/ErrorMessages.cy.resx b/SeaPublicWebsite/Resources/ErrorMessages.cy.resx index 80314e81..f3bc772a 100644 --- a/SeaPublicWebsite/Resources/ErrorMessages.cy.resx +++ b/SeaPublicWebsite/Resources/ErrorMessages.cy.resx @@ -153,4 +153,7 @@ rhwng {1} a {2} Rhowch rif rhwng 5 a 35, neu anwybyddwch y cwestiwn hwn + + Dewiswch a oes gennych baneli solar + \ No newline at end of file diff --git a/SeaPublicWebsite/Resources/ErrorMessages.resx b/SeaPublicWebsite/Resources/ErrorMessages.resx index 50fdb799..02a67e85 100644 --- a/SeaPublicWebsite/Resources/ErrorMessages.resx +++ b/SeaPublicWebsite/Resources/ErrorMessages.resx @@ -150,4 +150,7 @@ Enter a number between 5 and 35, or skip this question + + Select if you have solar panels + \ No newline at end of file diff --git a/SeaPublicWebsite/Resources/SharedResources.cy.resx b/SeaPublicWebsite/Resources/SharedResources.cy.resx index 47887310..77b48eb6 100644 --- a/SeaPublicWebsite/Resources/SharedResources.cy.resx +++ b/SeaPublicWebsite/Resources/SharedResources.cy.resx @@ -2631,4 +2631,20 @@ Mae eich Tystysgrif Perfformiad Ynni {0} yn awgrymu nad ydy eich <strong>atig wedi’i inswleiddio’n llwyr</strong> a bod gennych lai na 200mm o ddeunydd inswleiddio. EPCSuggestsYourLoftIsNotFullyInsulatedString + + Mae arae ffotofoltäig solar (PV) ar ben y to yn gasgliad o baneli lliw tywyll. Yn fwyaf cyffredin mae’r paneli yn cael eu cysylltu â'r to â mownt gosod. Yn llai cyffredin maen nhw wedi’u hintegreiddio â'r to ei hun (PV integredig adeilad). + HelpMeAnswerSolarElectricPanelsString + + + Mae eich Tystysgrif Perfformiad Ynni ar gyfer {0} yn awgrymu <strong>nad oes paneli ffotofoltäig solar wedi'u gosod ar eich cartref. </strong> + EPCSuggestsNoSolarPanelsString + + + Mae eich Tystysgrif Perfformiad Ynni ar gyfer {0} yn awgrymu <strong>bod paneli ffotofoltäig solar wedi'u gosod ar eich cartref.</strong> + EPCSuggestsHasSolarPanelsString + + + Oes paneli Ffotofoltäig Solar (PV) wedi’u gosod ar eich eiddo chi? + SolarElectricPanelsQuestionString + \ No newline at end of file diff --git a/SeaPublicWebsite/Resources/SharedResources.resx b/SeaPublicWebsite/Resources/SharedResources.resx index eff9304a..c35f217a 100644 --- a/SeaPublicWebsite/Resources/SharedResources.resx +++ b/SeaPublicWebsite/Resources/SharedResources.resx @@ -2579,4 +2579,20 @@ Your {0} Energy Performance Certificate suggests your <strong>loft is not fully insulated</strong> as it has less than 200mm of insulation. EPCSuggestsYourLoftIsNotFullyInsulatedString + + A rooftop solar photovoltaic (PV) array is a collection of dark coloured panels. Panels are most commonly attached to the roof with a fixed mount. Less commonly they are integrated into the roof itself (building integrated PV).  + HelpMeAnswerSolarElectricPanelsString + + + Your {0} Energy Performance Certificate suggests your home <strong>does not have solar photovoltaic panels installed.</strong> + EPCSuggestsNoSolarPanelsString + + + Your {0} Energy Performance Certificate suggests your home <strong>has solar photovoltaic panels installed.<strong> + EPCSuggestsHasSolarPanelsString + + + Is your property fitted with Solar Photovoltaic (PV) panels?  + SolarElectricPanelsQuestionString + \ No newline at end of file diff --git a/SeaPublicWebsite/Services/AnswerService.cs b/SeaPublicWebsite/Services/AnswerService.cs index df5edb55..965972df 100644 --- a/SeaPublicWebsite/Services/AnswerService.cs +++ b/SeaPublicWebsite/Services/AnswerService.cs @@ -165,6 +165,16 @@ public async Task UpdateRoofConstruction( reference); } + public async Task UpdateSolarElectricPanels( + string reference, + SolarElectricPanels? solarElectricPanels, + QuestionFlowStep? entryPoint) + { + return await UpdatePropertyDataAsync( + (b, p) => b.UpdateSolarElectricPanels(p, solarElectricPanels, entryPoint), + reference); + } + public async Task UpdateLoftSpace( string reference, LoftSpace? loftSpace, diff --git a/SeaPublicWebsite/Views/EnergyEfficiency/AnswerSummary.cshtml b/SeaPublicWebsite/Views/EnergyEfficiency/AnswerSummary.cshtml index b8989923..8a4a70f5 100644 --- a/SeaPublicWebsite/Views/EnergyEfficiency/AnswerSummary.cshtml +++ b/SeaPublicWebsite/Views/EnergyEfficiency/AnswerSummary.cshtml @@ -200,6 +200,36 @@ } } }); + + @if (Model.PropertyData.PropertyType is not PropertyType.ApartmentFlatOrMaisonette || Model.PropertyData.FlatType is FlatType.TopFloor) + { + rows.Add(new() + { + Key = new() + { + Classes = "govuk-!-width-one-quarter", + Text = SharedLocalizer["SolarElectricPanelsQuestionString"].Value + }, + Value = new() + { + Classes = "govuk-!-width-one-half", + Text = GovUkRadioCheckboxLabelTextAttribute.GetLabelText(Model.PropertyData.SolarElectricPanels ?? SolarElectricPanels.DoNotKnow) + }, + Actions = new() + { + Classes = "govuk-!-width-one-quarter", + Items = new() + { + new() + { + Href = Url.Action(nameof(EnergyEfficiencyController.SolarElectricPanels_Get), "EnergyEfficiency", new { reference = Model.PropertyData.Reference, entryPoint = QuestionFlowStep.SolarElectricPanels }), + Text = SharedLocalizer["Change"].Value, + VisuallyHiddenText = SharedLocalizer["SolarElectricPanelsQuestionString"].Value + } + } + } + }); + } if (Model.PropertyData.RoofConstruction is not RoofConstruction.Flat) { diff --git a/SeaPublicWebsite/Views/EnergyEfficiency/SolarElectricPanels.cshtml b/SeaPublicWebsite/Views/EnergyEfficiency/SolarElectricPanels.cshtml new file mode 100644 index 00000000..26961109 --- /dev/null +++ b/SeaPublicWebsite/Views/EnergyEfficiency/SolarElectricPanels.cshtml @@ -0,0 +1,71 @@ +@using GovUkDesignSystem +@using GovUkDesignSystem.GovUkDesignSystemComponents +@using Microsoft.AspNetCore.Mvc.TagHelpers +@using SeaPublicWebsite.BusinessLogic.Models.Enums +@using SeaPublicWebsite.Controllers +@using Microsoft.AspNetCore.Mvc.Localization +@inject IHtmlLocalizer SharedLocalizer + +@model SeaPublicWebsite.Models.EnergyEfficiency.SolarElectricPanelsViewModel +@{ + ViewBag.Title = SharedLocalizer["Solar Photovoltaic (PV) panels"].Value; +} + +@section BeforeMain { + @await Html.GovUkBackLink(new BackLinkViewModel + { + Text = SharedLocalizer["Back"].Value, + Href = Model.BackLink + }) +} + +
+
+ +
+ @Html.AntiForgeryToken() + @(Html.HiddenFor(m => m.EntryPoint)) + + @{ + Func details = + @ +

+ @SharedLocalizer["HelpMeAnswerSolarElectricPanelsString"] +

+
; + } + + @(await Html.GovUkRadiosFor(m => m.SolarElectricPanels, + fieldsetOptions: new FieldsetViewModel + { + Legend = new LegendViewModel + { + Text = SharedLocalizer["SolarElectricPanelsQuestionString"].Value, + Classes = "govuk-fieldset__legend--l", + IsPageHeading = true + } + }, + new HintViewModel + { + Html = @ + @await Html.GovUkDetails(new DetailsViewModel + { + SummaryText = SharedLocalizer["Help me answer this question"].Value, + Html = details + }) + + } + )) + + @await Html.GovUkButton(new ButtonViewModel + { + Text = SharedLocalizer["Continue"].Value + }) + + + +
+
+ @await Html.PartialAsync("/Views/EnergyEfficiency/Partials/_AdditionalSupport.cshtml") +
+
\ No newline at end of file diff --git a/SimpleEnergyAdvice.sln.DotSettings b/SimpleEnergyAdvice.sln.DotSettings deleted file mode 100644 index 037c47f0..00000000 --- a/SimpleEnergyAdvice.sln.DotSettings +++ /dev/null @@ -1,4 +0,0 @@ - - NEVER - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> - <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /> \ No newline at end of file