From 55b1726e89db4f5258a663fa54355382cfea1c56 Mon Sep 17 00:00:00 2001 From: Thomas Ryan Date: Mon, 31 Jul 2023 17:11:35 -0700 Subject: [PATCH] Updated the install fee estimatation process in support of #364. --- NumberSearch.DataAccess/Models/Product.cs | 2 +- .../Controllers/CartController.cs | 110 +++++++++++++++--- NumberSearch.Mvc/NumberSearch.Mvc.csproj | 3 + NumberSearch.Mvc/Views/Cart/Order.cshtml | 4 +- .../images/scaled/onsiteInstall-400.webp | Bin 0 -> 157640 bytes NumberSearch.Tests/Integration.cs | 13 +++ 6 files changed, 113 insertions(+), 19 deletions(-) create mode 100644 NumberSearch.Mvc/wwwroot/images/scaled/onsiteInstall-400.webp diff --git a/NumberSearch.DataAccess/Models/Product.cs b/NumberSearch.DataAccess/Models/Product.cs index a775042b..350ad85f 100644 --- a/NumberSearch.DataAccess/Models/Product.cs +++ b/NumberSearch.DataAccess/Models/Product.cs @@ -118,7 +118,7 @@ public async Task PutAsync(string connectionString) .ExecuteAsync("UPDATE public.\"Products\" " + "SET \"Name\" = @Name, \"Price\" = @Price, \"Description\" = @Description, \"Image\" = @Image, \"Public\" = @Public, \"QuantityAvailable\" = @QuantityAvailable, \"SupportLink\" = @SupportLink, \"DisplayPriority\" = @DisplayPriority, \"VendorPartNumber\" = @VendorPartNumber, \"Type\" = @Type, \"Tags\" = @Tags, \"VendorDescription\" = @VendorDescription, \"VendorFeatures\" = @VendorFeatures, \"MarkdownContent\" = @MarkdownContent, \"InstallTime\" = @InstallTime " + "WHERE \"ProductId\" = @ProductId", - new { Name, Price, Description, Image, Public, ProductId, QuantityAvailable, SupportLink, DisplayPriority, VendorPartNumber, Type, VendorDescription, VendorFeatures, MarkdownContent, InstallTime }) + new { Name, Price, Description, Image, Public, ProductId, QuantityAvailable, SupportLink, DisplayPriority, VendorPartNumber, Type, Tags, VendorDescription, VendorFeatures, MarkdownContent, InstallTime }) .ConfigureAwait(false); if (result == 1) diff --git a/NumberSearch.Mvc/Controllers/CartController.cs b/NumberSearch.Mvc/Controllers/CartController.cs index 1806a6d2..46bc8dc6 100644 --- a/NumberSearch.Mvc/Controllers/CartController.cs +++ b/NumberSearch.Mvc/Controllers/CartController.cs @@ -5,7 +5,6 @@ using Ical.Net.Serialization; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; using NumberSearch.DataAccess; using NumberSearch.DataAccess.InvoiceNinja; @@ -17,7 +16,6 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.ServiceModel.Channels; using System.Text.Json; using System.Threading.Tasks; @@ -158,6 +156,45 @@ public async Task CheckoutAsync() // Create a GUID for an order to prevent multiple order submissions from repeated button clicking. cart.Order.OrderId = Guid.NewGuid(); + // Default to Onsite Installation if there is hardware in the cart. + if (cart?.Products is not null && cart.Products.Count > 0) + { + cart.Order.OnsiteInstallation = true; + + // Add the call out charge and install estimate to the Cart + Product onsite = await Product.GetByIdAsync(Guid.Parse("b174c76a-e067-4a6a-abcf-53b6d3a848e4"), _postgresql); + Product estimate = await Product.GetByIdAsync(Guid.Parse("a032b3ba-da57-4ad3-90ec-c59a3505b075"), _postgresql); + + // Sum all of the install time estimates. + decimal totalInstallTime = 0m; + foreach (var item in cart.Products) + { + var quantity = cart.ProductOrders?.Where(x => x.ProductId == item.ProductId).FirstOrDefault(); + + if (item.InstallTime > 0m && quantity is not null) + { + totalInstallTime += item.InstallTime * quantity.Quantity; + } + } + + var productOrderOnsite = new ProductOrder + { + ProductOrderId = Guid.NewGuid(), + ProductId = onsite.ProductId, + Quantity = 1 + }; + + var productOrderEstimate = new ProductOrder + { + ProductOrderId = Guid.NewGuid(), + ProductId = estimate.ProductId, + Quantity = decimal.ToInt32(Math.Ceiling(totalInstallTime)) + }; + + _ = cart.AddProduct(onsite, productOrderOnsite); + _ = cart.AddProduct(estimate, productOrderEstimate); + } + _ = cart.SetToSession(HttpContext.Session); } @@ -340,7 +377,7 @@ public async Task SubmitAsync(Order order) } else { - Log.Error($"[Checkout] Failed automatic address formating."); + Log.Error($"[Checkout] Failed automatic address formatting."); } // Fillout the address2 information from its components. @@ -419,6 +456,57 @@ public async Task SubmitAsync(Order order) if (cart is not null && cart.ProductOrders is not null) { + if (cart.Products is not null && cart.Products.Count > 0) + { + // Add the call out charge and install estimate to the Cart + Product onsite = await Product.GetByIdAsync(Guid.Parse("b174c76a-e067-4a6a-abcf-53b6d3a848e4"), _postgresql); + Product estimate = await Product.GetByIdAsync(Guid.Parse("a032b3ba-da57-4ad3-90ec-c59a3505b075"), _postgresql); + + // Sum all of the install time estimates. + decimal totalInstallTime = 0m; + foreach (var item in cart.Products) + { + var quantity = cart.ProductOrders?.Where(x => x.ProductId == item.ProductId).FirstOrDefault(); + + if (item.InstallTime > 0m && quantity is not null) + { + totalInstallTime += item.InstallTime * quantity.Quantity; + } + } + + var productOrderOnsite = new ProductOrder + { + ProductOrderId = Guid.NewGuid(), + ProductId = onsite.ProductId, + Quantity = 1 + }; + + var productOrderEstimate = new ProductOrder + { + ProductOrderId = Guid.NewGuid(), + ProductId = estimate.ProductId, + Quantity = decimal.ToInt32(Math.Ceiling(totalInstallTime)) + }; + + if (order.OnsiteInstallation) + { + var checkOnsiteExists = cart.Products.FirstOrDefault(x => x.ProductId == Guid.Parse("b174c76a-e067-4a6a-abcf-53b6d3a848e4")); + var checkEstimateExists = cart.Products.FirstOrDefault(x => x.ProductId == Guid.Parse("a032b3ba-da57-4ad3-90ec-c59a3505b075")); + + if (checkOnsiteExists is null && checkEstimateExists is null) + { + _ = cart.AddProduct(onsite, productOrderOnsite); + _ = cart.AddProduct(estimate, productOrderEstimate); + } + } + else + { + // Remove + _ = cart.RemoveProduct(onsite, productOrderOnsite); + _ = cart.RemoveProduct(estimate, productOrderEstimate); + } + } + foreach (var productOrder in cart.ProductOrders) { productOrder.OrderId = order.OrderId; @@ -536,7 +624,7 @@ public async Task SubmitAsync(Order order) } else if (coupon.Type == "Install") { - // If they have selected onsite installation this coupon removes a $60 charge. + // If they have selected onsite installation this coupon removes a $75 charge. if (order.OnsiteInstallation) { onetimeItems.Add(new Line_Items @@ -629,17 +717,7 @@ public async Task SubmitAsync(Order order) // Handle hardware installation scenarios, if hardware is in the order. if (cart?.Products is not null && cart.Products.Any()) { - if (order.OnsiteInstallation) - { - onetimeItems.Add(new Line_Items - { - product_key = "Onsite Hardware Installation", - notes = $"We'll come visit you and get all your phones setup.", - cost = 75, - quantity = 1 - }); - } - else + if (!order.OnsiteInstallation) { onetimeItems.Add(new Line_Items { @@ -677,7 +755,7 @@ public async Task SubmitAsync(Order order) } } - // Handle the tax information for the invoice and fall back to simplier queries if we get failures. + // Handle the tax information for the invoice and fall back to simpler queries if we get failures. SalesTax specificTaxRate = null!; if (order.State is "WA" || order.State is "Washington") { diff --git a/NumberSearch.Mvc/NumberSearch.Mvc.csproj b/NumberSearch.Mvc/NumberSearch.Mvc.csproj index dfd4594d..fac7b50a 100644 --- a/NumberSearch.Mvc/NumberSearch.Mvc.csproj +++ b/NumberSearch.Mvc/NumberSearch.Mvc.csproj @@ -413,6 +413,9 @@ Always + + Always + Always diff --git a/NumberSearch.Mvc/Views/Cart/Order.cshtml b/NumberSearch.Mvc/Views/Cart/Order.cshtml index 83eedd23..6274f71b 100644 --- a/NumberSearch.Mvc/Views/Cart/Order.cshtml +++ b/NumberSearch.Mvc/Views/Cart/Order.cshtml @@ -697,7 +697,7 @@

Remote installation is free, safe, and done virtually. We'll guide you through every step of plugging in your pre-configured phones!

-

Onsite installation is available in the Greater Seattle Area for a $75 call out charge. Time spent onsite is billed at $125 per hour.

+

Onsite installation is available in the Greater Seattle Area for a $75 call out charge. Time spent onsite is billed at $125 per hour and estimated based on the hardware you order.

} @@ -709,7 +709,7 @@