Error executing template "Designs/Swift/eCom7/CartV2/Step/SR_InvoicesManagementCenterPayment.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_f055495dfe1c4ba9b1d19bd86d33d5d8.Execute() in E:\Domains\Sites\portal.keystonerv.com\Files\Templates\Designs\Swift\eCom7\CartV2\Step\SR_InvoicesManagementCenterPayment.cshtml:line 138
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 2 @using Dynamicweb 3 @using System.IO 4 @using Dynamicweb.Core 5 @using Dynamicweb.Ecommerce.Orders 6 @functions 7 { 8 private void SetDefaultMethods() 9 { 10 LoopItem shippingMethod = GetLoop("Shippingmethods").FirstOrDefault(); 11 if (shippingMethod == null || shippingMethod.GetString("Ecom:Cart.Shippingmethod.ID") == GetString("Ecom:Order.ShippingMethodID")) 12 { 13 return; 14 } 15 16 Order cart = Dynamicweb.Ecommerce.Services.Orders.GetById(GetString("Ecom:Order.ID")); 17 cart.ShippingMethodId = shippingMethod.GetString("Ecom:Cart.Shippingmethod.ID"); 18 cart.ShippingMethod = shippingMethod.GetString("Ecom:Cart.Shippingmethod.Name"); 19 20 // Set default payment based on shopping cart app if user did not selected one 21 if (Context.Current.Request["EcomCartPaymethodID"] == null) 22 { 23 LoopItem paymentMethod = GetLoop("Paymethods").FirstOrDefault(); 24 25 if (paymentMethod != null || paymentMethod.GetString("Ecom:Cart.Paymethod.ID") != GetString("Ecom:Order.ShippingMethodID")) 26 { 27 cart.PaymentMethodId = paymentMethod.GetString("Ecom:Cart.Paymethod.ID"); 28 cart.PaymentMethod = paymentMethod.GetString("Ecom:Cart.Paymethod.Name"); 29 } 30 } 31 32 Dynamicweb.Ecommerce.Services.Orders.Save(cart); 33 string redirect = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(Pageview.Page.ID); 34 Context.Current.Response.Redirect(redirect); 35 } 36 37 private void RedirectToCheckout(bool needsPayment) 38 { 39 if (!needsPayment) return; 40 41 List<LoopItem> payMethods = GetLoop("Paymethods"); 42 bool isSinglePayment = payMethods.Count == 1; 43 44 if (!isSinglePayment) return; 45 46 bool hasSavedCards = GetLoop("SavedCards").Any(); 47 48 if (hasSavedCards) return; 49 50 Order cart = Dynamicweb.Ecommerce.Services.Orders.GetById(GetString("Ecom:Order.ID")); 51 int nextStepIndex = cart.CartV2StepIndex + 1; 52 cart.PaymentMethodId = payMethods.FirstOrDefault().GetString("Ecom:Cart.Paymethod.ID"); 53 cart.PaymentMethod = payMethods.FirstOrDefault().GetString("Ecom:Cart.Paymethod.Name"); 54 Dynamicweb.Ecommerce.Services.Orders.Save(cart); 55 string redirect = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl(Pageview.Page.ID) + "?CartV2.GotoStep" + nextStepIndex + "=true"; 56 Context.Current.Response.Redirect(redirect); 57 } 58 } 59 @{ 60 SetDefaultMethods(); 61 bool needsPayment = GetDouble("Ecom:Order.OrderLines.TotalPriceWithoutSymbol") > 0; 62 RedirectToCheckout(needsPayment); 63 } 64 <div class="grid gap-0"> 65 <div class="cart g-col-12 g-col-lg-8 py-3 py-lg-5 pe-lg-5 order-last order-lg-first"> 66 <form name="ordersubmit" id="ordersubmit" method="post" autocomplete="off"> 67 68 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 69 @using Dynamicweb 70 @using System.IO 71 72 @{ 73 string logoLink = Pageview.CurrentParagraph?.Item["LogoLink"] != null ? Pageview.CurrentParagraph.Item["LogoLink"].ToString() : string.Empty; 74 75 string logoImage = Pageview.CurrentParagraph?.Item["Logo"] != null ? Pageview.CurrentParagraph.Item["Logo"].ToString() : string.Empty; 76 string title = Pageview.CurrentParagraph?.Item["Title"] != null ? Pageview.CurrentParagraph.Item["Title"].ToString() : Pageview.Area.Name; 77 78 string maxWidth = Pageview.CurrentParagraph?.Item["MaxWidth"] != null ? "max-width: " + Pageview.CurrentParagraph.Item["MaxWidth"].ToString() + "px" : string.Empty; 79 maxWidth = maxWidth == "max-width: 0px" ? string.Empty : maxWidth; 80 } 81 82 <div class="mb-4 text-center"> 83 @if (!string.IsNullOrWhiteSpace(logoLink)) 84 { 85 @:<a href="@logoLink" class="text-decoration-none" title="@Translate("Leave checkout")"> 86 } 87 88 @if (logoImage != "") 89 { 90 if (Path.GetExtension(logoImage).ToLower() == ".svg") 91 { 92 <div class="icon-auto" style="@maxWidth"> 93 @ReadFile(logoImage) 94 </div> 95 } 96 else 97 { 98 string imageWidth = Pageview.CurrentParagraph.Item["MaxWidth"] != null ? Pageview.CurrentParagraph.Item["MaxWidth"].ToString() : "400"; 99 string imagePath = "/Admin/Public/GetImage.ashx?width=" + imageWidth + "&image=" + logoImage; 100 101 <picture class="mx-auto d-block"> 102 <img src="@logoImage" alt="@title" style="@maxWidth"> 103 </picture> 104 } 105 } 106 else 107 { 108 <div class="fs-3 p-0">@title</div> 109 } 110 111 @if (!string.IsNullOrWhiteSpace(logoLink)) 112 { 113 @:</a> 114 } 115 </div> 116 117 118 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 119 @using Dynamicweb.Ecommerce.Orders 120 121 @if (GetLoop("ValidationErrors").Count() != 0) 122 { 123 <div class="alert alert-warning" role="alert"> 124 <ul class="m-0 list-unstyled"> 125 @foreach (LoopItem item in GetLoop("ValidationErrors")) 126 { 127 <li>@item.GetValue("Ecom:Cart.ValidationError.ErrorMessage")</li> 128 } 129 </ul> 130 </div> 131 } 132 133 134 @* Logic to remove the voucher code error, when going to next step in checkout *@ 135 @{ 136 string voucherCodeForErrorCheck = GetString("Ecom:Order.Customer.VoucherCode"); 137 Order orderForErrorCheck = new OrderService().GetById(GetString("Ecom:Order.ID")); 138 voucherCodeForErrorCheck = orderForErrorCheck.VoucherUseType == VoucherUseCategoryType.None ? string.Empty : voucherCodeForErrorCheck; 139 } 140 141 <input type="hidden" name="EcomOrderVoucherCode" value="@voucherCodeForErrorCheck"> 142 143 144 <div class="mt-4"> 145 @if (needsPayment) 146 { 147 <h3 class="fs-6 fw-normal mb-0">@Translate("Select payment")</h3> 148 <p class="fs-8 mb-3">@Translate("All transactions are encrypted")</p> 149 <text>@inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 150 151 @{ 152 string paymentErrorMessage = GetString("Ecom:Cart.ValidationError.EcomCartPaymethodId.ErrorMessage"); 153 154 <div class="list-group" id="PaymentMethodsGroup"> 155 @foreach (LoopItem method in GetLoop("Paymethods")) 156 { 157 <label class="list-group-item list-group-item-action"> 158 <dl class="grid gap-1 gap-sm-3 mb-0"> 159 <dt class="g-col-8 g-col-sm-4 fw-normal"> 160 <div class="form-check"> 161 @{ 162 string paymentMethodId = GetString("Ecom:Order.PaymentMethodID"); 163 string paymentMethodIdSaved = method.GetString("Ecom:Cart.Paymethod.ID"); 164 } 165 <input class="form-check-input" type="radio" name="EcomCartPaymethodID" id="EcomCartPaymentmethodID_@method.GetString("Ecom:Cart.Paymethod.ID")" @if (String.Equals(paymentMethodId, paymentMethodIdSaved)) { <text> checked="checked" </text> } value="@method.GetString("Ecom:Cart.Paymethod.ID")" onchange="submitForm()"> 166 <span class="form-check-label">@method.GetString("Ecom:Cart.Paymethod.Name")</span> 167 </div> 168 </dt> 169 <dd class="g-col-12 g-col-sm-7 order-2 order-sm-1 mb-0"> 170 @{ 171 string imagePath = Dynamicweb.Context.Current.Server.MapPath(method.GetString("Ecom:Cart.Paymethod.Icon.Clean")); 172 173 if (File.Exists(imagePath)) 174 { 175 <span class="m-0 d-block" style="height: 1.5rem; width: 100%; background: url('@method.GetString("Ecom:Cart.Paymethod.Icon.Clean")') no-repeat left center; background-size: contain;"></span> 176 } 177 else 178 { 179 <span class="fs-8 lh-1">@method.GetString("Ecom:Cart.Paymethod.Description")</span> 180 } 181 } 182 183 </dd> 184 <dd class="g-col-4 g-col-sm-1 order-1 order-sm-2 mb-0 text-end"> 185 @if (!method.GetBoolean("Ecom:Cart.Paymethod.Price.IsZero")) 186 { 187 <span class="text-price">@method.GetString("Ecom:Cart.Paymethod.Price")</span> 188 } 189 </dd> 190 </dl> 191 </label> 192 } 193 @paymentErrorMessage 194 </div> 195 196 LoopItem selectedPaymentMethodWithSavedCardSupport = GetLoop("Paymethods").FirstOrDefault(p => p.GetBoolean("Ecom:Cart.Paymethod.IsSelected") && p.GetBoolean("Ecom:Cart.Paymethod.SupportSavedCard") && Pageview.User != null); 197 if (selectedPaymentMethodWithSavedCardSupport != null) 198 { 199 bool cardIsSaved = !string.IsNullOrEmpty(GetString("Ecom:Order.SavedCardName")); 200 string cardIsSavedValue = cardIsSaved ? "true" : string.Empty; 201 string savedCardName = ""; 202 203 <div class="list-group" id="SavedCardsGroup"> 204 <h4 class="fs-6 fw-normal mb-0 mt-4">@Translate("Saved Cards")</h4> 205 <p class="fs-8 mb-3">@Translate("Pay with a saved card")</p> 206 207 @foreach (LoopItem card in GetLoop("SavedCards")) 208 { 209 savedCardName = !card.GetBoolean("Ecom:SavedCard.IsSelected") ? card.GetString("Ecom:SavedCard.Name") : savedCardName; 210 211 <label class="list-group-item list-group-item-action"> 212 <div class="form-check fw-normal"> 213 <input class="form-check-input" type="radio" name="EcomCartSavedCardID" id="EcomSavedCardID_@card.GetString("Ecom:SavedCard.ID")" value="@card.GetString("Ecom:SavedCard.ID")" checked="@card.GetBoolean("Ecom:SavedCard.IsSelected")" data-card-name="@card.GetString("Ecom:SavedCard.Name")" onchange="selectSavedCard(this)"> 214 <span class="form-check-label">@card.GetString("Ecom:SavedCard.Name")</span> 215 </div> 216 </label> 217 } 218 219 <label class="list-group-item list-group-item-action"> 220 <dl class="grid gap-0 gap-sm-3 align-items-center mb-0"> 221 <dt class="g-col-4 fw-normal"> 222 <div class="form-check"> 223 <input class="form-check-input" type="radio" name="EcomCartSavedCardID" id="SaveNewCard" value="" checked="@cardIsSavedValue" onchange="selectNewCard(this)"> 224 <span class="form-check-label fst-italic">@Translate("Save a new card")</span> 225 </div> 226 </dt> 227 <dd class="g-col-6 mb-0"> 228 <input type="checkbox" class="d-none" name="EcomOrderSavedCardCreate" id="EcomOrderSavedCardCreate" value="true" checked="@cardIsSavedValue"> 229 <input type="text" class="form-control" id="NewSavedCardName" value="@GetString("Ecom:Order.SavedCardName")" onchange="document.getElementById('MySavedCardName').value=this.value" placeholder="@Translate("New saved card name")"> 230 </dd> 231 </dl> 232 </label> 233 234 <input type="hidden" name="EcomOrderSavedCardName" id="MySavedCardName" value="@savedCardName" /> 235 </div> 236 } 237 } 238 239 <script> 240 function selectSavedCard(element) { 241 let cardName = element.getAttribute('data-card-name'); 242 243 resetRadioButton(element); 244 updateSavedCardName(cardName); 245 updateNewCardValue(false); 246 } 247 248 function selectNewCard(element) { 249 resetRadioButton(element); 250 updateSavedCardName(""); 251 updateNewCardValue(true); 252 } 253 254 function resetRadioButton(element) { 255 let radioList = document.querySelector("input[name='EcomCartSavedCardID']"); 256 for (let i = 0; i < radioList.length; i++) { 257 if (radioList[i].checked && radioList[i].id !== element.id) radioList[i].checked = false; 258 } 259 } 260 261 function updateSavedCardName(value) { 262 let savedCardNameField = document.querySelector("#MySavedCardName"); 263 if (savedCardNameField) { 264 savedCardNameField.value = value; 265 } 266 } 267 268 function updateNewCardValue(value) { 269 let newCardField = document.querySelector("#EcomOrderSavedCardCreate"); 270 if (newCardField) { 271 newCardField.checked = value; 272 } 273 } 274 </script> 275 </text> 276 } 277 else 278 { 279 string dummyPaymentId = Converter.ToString(Pageview.CurrentParagraph.Item["DummyPayment"]); 280 <div class="alert alert-success" role="alert"> 281 @Translate("Your order total is $ 0.00. Click 'Pay Now' button to confirm your payment.") 282 </div> 283 284 <input type="hidden" name="EcomCartPaymethodID" value="@dummyPaymentId"/> 285 } 286 </div> 287 288 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 289 290 @{ 291 string iconPathInvoiceManagementCenterStepsNavigation = "/Files/Templates/Designs/Swift/Assets/icons/"; 292 bool isErpConnectionDown = !Dynamicweb.Core.Converter.ToBoolean(Pageview.GlobalTags.GetTagByName("Global:LiveIntegration.IsWebServiceConnectionAvailable")?.Value ?? "true"); 293 string erpDownCartBehavior = Pageview.CurrentParagraph.Item["ErpDownCartBehavior"]?.ToString() ?? "none"; 294 295 <div class="mt-4 d-flex flex-column flex-md-row justify-content-end gap-3 mt-lg-4"> 296 <a href="@Pageview.CurrentParagraph.Item["InvoicesManagementCenterPageLink"]" class="btn btn-link link-secondary text-decoration-none order-last order-md-first"> 297 <div class="d-flex align-items-center justify-content-center position-relative"> 298 <span class="icon-2 me-1 position-absolute position-md-static start-0"> 299 @ReadFile(iconPathInvoiceManagementCenterStepsNavigation + "chevron-left.svg") 300 </span> 301 <span>@Translate("Back")</span> 302 </div> 303 </a> 304 305 @if (!(isErpConnectionDown && erpDownCartBehavior == "disable")) 306 { 307 <button type="submit" name="@GetString("CartV2.NextStepButtonName")" id="@GetString("CartV2.NextStepButtonName")" class="btn btn-primary order-first order-md-last"> 308 <div class="d-flex align-items-center justify-content-center position-relative"> 309 <span>@Translate("Pay now")</span> 310 <span class="icon-2 ms-1 position-absolute position-md-static end-0"> 311 @ReadFile(iconPathInvoiceManagementCenterStepsNavigation + "chevron-right.svg") 312 </span> 313 </div> 314 </button> 315 } 316 else 317 { 318 <button class="btn btn-primary pe-none disabled">@Translate("Payment is temporarily disabled")</button> 319 } 320 321 <script> 322 if ( window.history.replaceState ) { 323 window.history.replaceState( null, null, window.location.href ); 324 } 325 </script> 326 </div> 327 } 328 329 330 <input type="hidden" id="CurrentStep" /> 331 </form> 332 </div> 333 334 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 335 @using Dna.Keystone.Vin 336 337 @if(GetString("Ecom:OrderContext.ID").Equals(Dna.PaymentLedgers.Constants.OrderContext)) 338 { 339 <text>@using Dynamicweb.Ecommerce.Orders 340 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 341 342 @functions 343 { 344 private class TypeTotal 345 { 346 public string Type { get; set; } 347 public string Currency { get; set; } 348 public double Amount { get; set; } 349 } 350 351 private static List<TypeTotal> SumTotals(IEnumerable<LoopItem> orderlines) 352 { 353 return orderlines.GroupBy(ol => ol.GetString("Ecom:Order:OrderLine.ProductName").ToLower(), 354 (k, total) => new TypeTotal() 355 { 356 Type = k, 357 Currency = total.FirstOrDefault().GetString("Ecom:Order:OrderLine.Price.Currency.Symbol"), 358 Amount = total.Sum(x => x.GetDouble("Ecom:Order:OrderLine.Price.Price.Value")) 359 }).ToList(); 360 } 361 362 private static string GetTotalValue(IEnumerable<TypeTotal> total, string type) 363 { 364 TypeTotal typeTotal = total.FirstOrDefault(t => t.Type.Equals(type, StringComparison.InvariantCultureIgnoreCase)); 365 366 return typeTotal == null ? "" : $"{typeTotal.Currency} {typeTotal.Amount:0.00}"; 367 } 368 } 369 370 @{ 371 List<LoopItem> discounts = GetLoop("OrderLines").Where(o => o.GetBoolean("Ecom:Order:OrderLine.IsDiscount") && o.GetInteger("Ecom:Order:OrderLine.Type") == 1).ToList(); 372 string showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower(); 373 bool neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 374 375 List<TypeTotal> totals = SumTotals(GetLoop("OrderLines").Where(o => o.GetInteger("Ecom:Order:OrderLine.Type") != (int)OrderLineType.Tax).ToList()); 376 377 string summarySidebarClass = string.IsNullOrEmpty(GetString("Ecom:Order.Completed")) ? "g-col-12 g-col-lg-4 position-relative py-2 py-lg-5 ps-lg-5 border-start px-3 px-lg-0 mx-n3 mx-lg-0" : ""; 378 } 379 380 <div class="summary-sidebar @summarySidebarClass" id="summarySidebar"> 381 <div class="position-relative"> 382 383 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 384 385 @{ 386 string iconPath = "/Files/Icons/"; 387 } 388 389 <button class="toggle-order-summary btn text-reset w-100 d-block d-lg-none px-0" type="button" data-bs-toggle="collapse" data-bs-target="#orderSummary" aria-expanded="false" aria-controls="orderSummary" id="OrderSummaryToggleButton"> 390 <span class="d-flex align-items-center justify-content-between"> 391 <span class="d-flex align-items-center gap-2"> 392 <span class="fs-7 lh-1"> 393 <span class="toggle-order-summary-text" id="OrderSummaryToggleButtonLabel">@Translate("Show order summary")</span> 394 </span> 395 <span class="icon-2" id="OrderSummaryToggleButtonIcon" style="transition: all 0.25s ease-in-out;"> 396 @ReadFile(iconPath + "chevron-down.svg") 397 </span> 398 </span> 399 <span class="fw-bold"> 400 <span class="text-price">@GetString("Ecom:Order.Price")</span> 401 </span> 402 </span> 403 </button> 404 405 <script> 406 const orderSummaryToggleButton = document.getElementById("OrderSummaryToggleButton"); 407 const orderSummaryToggleButtonLabel = document.getElementById("OrderSummaryToggleButtonLabel"); 408 const orderSummaryToggleButtonIcon = document.getElementById("OrderSummaryToggleButtonIcon"); 409 const orderSummaryToggleText = '@Translate("Show order summary")'; 410 411 orderSummaryToggleButton.addEventListener('click', function handleClick() { 412 if (orderSummaryToggleButtonLabel.textContent.toLowerCase().includes(orderSummaryToggleText.toLowerCase())) { 413 orderSummaryToggleButtonLabel.textContent = '@Translate("Hide order summary")'; 414 orderSummaryToggleButtonIcon.classList.add("rotate-180"); 415 } else { 416 orderSummaryToggleButtonLabel.textContent = orderSummaryToggleText; 417 orderSummaryToggleButtonIcon.classList.remove("rotate-180"); 418 } 419 }); 420 </script> 421 422 423 424 <div class="d-lg-block h-lg-auto visible-lg-visible pb-2 pb-md-0 collapse" id="orderSummary"> 425 <div class="d-flex flex-column gap-3 position-relative mb-2" id="orderSummaryList" style="overflow-x: hidden; overflow-y: hidden;"> 426 @foreach (LoopItem orderline in GetLoop("OrderLines")) { 427 string name = orderline.GetString("Ecom:Order:OrderLine.ProductName"); 428 string priceTotalWithDiscounts = orderline.GetString("Ecom:Order:OrderLine.TotalPriceWithProductDiscounts.PriceFormatted"); 429 string discountTotal = orderline.GetString("Ecom:Order:OrderLine.TotalDiscount.PriceFormatted"); 430 bool isProduct = orderline.GetBoolean("Ecom:Order:OrderLine.IsProduct"); 431 432 if (isProduct) 433 { 434 <article class="grid grid-12"> 435 <div class="g-col-12"> 436 <div class="grid grid-12"> 437 <div class="g-col-6 grid grid-6 gap-0"> 438 <div class="g-col-6"> 439 @* Title *@ 440 <h3 class="h6 fs-7 mb-0">@name: @orderline.GetString("Ecom:Order:OrderLine.ProductNumber")</h3> 441 </div> 442 </div> 443 <div class="g-col-6 text-end"> 444 @* Total *@ 445 <span class="h6 mb-0 d-block fs-7"> 446 <span class="text-price">@priceTotalWithDiscounts</span> 447 </span> 448 @if (orderline.GetDouble("Ecom:Order:OrderLine.TotalDiscount.Price.Value") != 0) 449 { 450 <span class="m-0 d-block fs-8"> 451 <span class="text-price">@discountTotal</span> 452 </span> 453 } 454 </div> 455 </div> 456 </div> 457 </article> 458 } 459 } 460 <div class="btn btn-primary position-absolute bottom-0 mb-3 btn-sm d-none" style="width: auto; left: 50%; transform: translateX(-50%);" id="scrollToViewMoreButton">@Translate("Scroll to view more")</div> 461 </div> 462 463 <div id="orderSummaryFooter"> 464 @if (discounts.Any() || GetDouble("Ecom:Order.PaymentFee.Price.Value") != 0 || GetDouble("Ecom:Order.Taxes.Total.Price.Value") != 0) { 465 <div class="fs-8 pt-2 border-top"> 466 @* Discounts (only order discounts) *@ 467 @foreach (LoopItem orderline in discounts) 468 { 469 <div class="d-flex justify-content-between mb-2"><span>@orderline.GetString("Ecom:Order:OrderLine.ProductName")</span><span>@orderline.GetString("Ecom:Order:OrderLine.TotalPriceWithProductDiscounts.PriceFormatted")</span></div> 470 } 471 472 @* Payment *@ 473 @if (GetDouble("Ecom:Order.PaymentFee.Price.Value") != 0) 474 { 475 <div class="d-flex justify-content-between mb-2"> 476 <span>@Translate("Payment")</span> 477 <span class="text-price">@GetString("Ecom:Order.PaymentFee.PriceFormatted")</span> 478 </div> 479 } 480 481 @* Sales tax *@ 482 @if (!(showPricesWithVat == "false" && !neverShowVat)) 483 { 484 if (GetDouble("Ecom:Order.Taxes.Total.Price.Value") != 0) 485 { 486 <div class="d-flex justify-content-between mb-2"> 487 <span>@Translate("Sales tax")</span> 488 <span>@GetString("Ecom:Order.Taxes.Total.PriceFormatted")</span> 489 </div> 490 } 491 } 492 </div> 493 } 494 495 <div class="fs-8 pt-2 border-top"> 496 @if(!string.IsNullOrEmpty(GetTotalValue(totals, "Invoice"))) { 497 <div class="d-flex justify-content-between mb-2"> 498 <span>@Translate("Total of Invoices")</span> 499 <span class="text-price">@GetTotalValue(totals, "Invoice")</span> 500 </div> 501 } 502 503 @if(!string.IsNullOrEmpty(GetTotalValue(totals, "Proforma"))) { 504 <div class="d-flex justify-content-between mb-2"> 505 <span>@Translate("Total of Proforma")</span> 506 <span class="text-price">@GetTotalValue(totals, "Proforma")</span> 507 </div> 508 } 509 510 @if(!string.IsNullOrEmpty(GetTotalValue(totals, "Credit"))) { 511 <div class="d-flex justify-content-between mb-2"> 512 <span>@Translate("Total of Credit Memos")</span> 513 <span class="text-price">@GetTotalValue(totals, "Credit")</span> 514 </div> 515 } 516 517 @if(!string.IsNullOrEmpty(GetTotalValue(totals, "Discount"))) { 518 <div class="d-flex justify-content-between mb-2"> 519 <span>@Translate("Discounts")</span> 520 <span class="text-price">@GetTotalValue(totals, "Discount")</span> 521 </div> 522 } 523 524 @if(!string.IsNullOrEmpty(GetTotalValue(totals, "Discount"))) { 525 <div class="d-flex justify-content-between mb-2"> 526 <span>@Translate("Discounts")</span> 527 <span class="text-price">@GetTotalValue(totals, "Discount")</span> 528 </div> 529 } 530 </div> 531 532 <div class="fs-8 pt-3 border-top"> 533 <div class="d-flex justify-content-between mb-2 fs-6 fw-bold"><span>@Translate("Total")</span><span class="text-price fs-5">@GetString("Ecom:Order.Price.PriceFormatted")</span></div> 534 </div> 535 </div> 536 </div> 537 </div> 538 </div> 539 </text> 540 } 541 else 542 { 543 <div class="g-col-12 g-col-lg-4 py-2 p-3 p-lg-4 p-xl-5" id="summarySidebar"> 544 545 @*START CUSTOM CODE*@ 546 @{ 547 var summarySidebarSelectedVinRow = Dna.Keystone.Vin.Helpers.GetSelectedVinRow(); 548 var vinLookUpServicePageId = GetPageIdByNavigationTag("VinLookupServicePage"); 549 var vinLookupServicePageUrl = vinLookUpServicePageId > 0 ? $"Default.aspx?ID={vinLookUpServicePageId}&{Constants.Request.CloseModalAfterSelect}=True" : ""; 550 551 <header class="g-col-12 cartCurrentVehicle"> 552 @if (summarySidebarSelectedVinRow != null) 553 { 554 var unitDetailPageId = GetPageIdByNavigationTag("UnitDetails"); 555 var unitDetailPageFriendlyUrl = unitDetailPageId > 0 ? Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl($"Default.aspx?ID={unitDetailPageId}") : string.Empty; 556 557 <h4 class="fs-6 fw-bold">@Translate("Current Vehicle")</h4> 558 559 <dl class="d-flex flex-row flex-wrap gap-3 align-items-center fs-8 border-bottom pt-2 pt-lg-3 pb-2 pb-lg-3"> 560 561 <dt>@Translate("VIN")</dt> 562 <dd class="mb-0 me-2"> 563 @if (!string.IsNullOrEmpty(unitDetailPageFriendlyUrl)) 564 { 565 var url = $"{unitDetailPageFriendlyUrl}?vq={summarySidebarSelectedVinRow.Vin}"; 566 <a href="@url" target="_blank">@summarySidebarSelectedVinRow.Vin</a> 567 } 568 else 569 { 570 @summarySidebarSelectedVinRow.Vin 571 } 572 </dd> 573 574 <dt>@Translate("Make")</dt> 575 <dd class="mb-0 me-2">@summarySidebarSelectedVinRow.Make</dd> 576 577 <dt>@Translate("Model")</dt> 578 <dd class="mb-0 me-2">@summarySidebarSelectedVinRow.Model</dd> 579 580 <dt>@Translate("Warranty")</dt> 581 <dd class="mb-0 me-2">@(summarySidebarSelectedVinRow.IsWarrantyValid() ? Translate("Warranty Active") : Translate("Warranty Expired"))</dd> 582 583 <dt>@Translate("Retail Sold")</dt> 584 <dd class="mb-0 me-2">@Dna.Keystone.Vin.Helpers.GetDateFormatted(summarySidebarSelectedVinRow.ShipDate)</dd> 585 586 <dt>@Translate("Model Year")</dt> 587 <dd class="mb-0 me-2">@summarySidebarSelectedVinRow.ModelYear</dd> 588 </dl> 589 } 590 else 591 { 592 <h4 class="fs-6 fw-bold text-danger">@Translate("Stock Order")</h4> 593 594 <div class="d-flex flex-row flex-wrap gap-3 align-items-center fs-8 border-bottom pt-0 pb-2 pb-lg-3 mb-3"> 595 <div class="w-100 text-left"> 596 <button class="rowAddVinButton btn p-0 text-uppercase" onclick="CurrentVehicle.OpenVinLookupModal();"> 597 <span class="icon-3 pe-none"> 598 @ReadFile("/Files/Templates/Designs/Swift/Assets/icons/" + "add-vin-asset.svg") 599 </span> 600 <span>@Translate("Add Vin")</span> 601 </button> 602 </div> 603 </div> 604 } 605 </header> 606 607 <div class="modal fade js-product" id="DynamicModal" tabindex="-1" aria-hidden="true"> 608 <div class="modal-dialog modal-dialog-centered modal-md"> 609 <div class="modal-content theme light" id="DynamicModalContent"> 610 @* The content here comes from an external request *@ 611 </div> 612 </div> 613 </div> 614 615 <script id="CurrentVehicleVinLookupModal" type="text/html"> 616 <div class="modal-dialog modal-xl modal-fullscreen-xl-down"> 617 <div class="modal-content"> 618 <div class="modal-header"> 619 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="@Translate("Close")"></button> 620 </div> 621 <div class="modal-body"> 622 <div class="ratio ratio-16x9"> 623 <iframe class="w-100 h-100" src="@vinLookupServicePageUrl"></iframe> 624 </div> 625 </div> 626 </div> 627 </div> 628 </script> 629 } 630 @*END CUSTOM CODE*@ 631 632 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 633 634 @{ 635 string iconPath = "/Files/Icons/"; 636 } 637 638 <button class="toggle-order-summary btn text-reset w-100 d-block d-lg-none px-0" type="button" data-bs-toggle="collapse" data-bs-target="#orderSummary" aria-expanded="false" aria-controls="orderSummary" id="OrderSummaryToggleButton"> 639 <span class="d-flex align-items-center justify-content-between"> 640 <span class="d-flex align-items-center gap-2"> 641 <span class="fs-7 lh-1"> 642 <span class="toggle-order-summary-text" id="OrderSummaryToggleButtonLabel">@Translate("Show order summary")</span> 643 </span> 644 <span class="icon-2" id="OrderSummaryToggleButtonIcon" style="transition: all 0.25s ease-in-out;"> 645 @ReadFile(iconPath + "chevron-down.svg") 646 </span> 647 </span> 648 <span class="fw-bold"> 649 <span class="text-price">@GetString("Ecom:Order.Price")</span> 650 </span> 651 </span> 652 </button> 653 654 <script> 655 const orderSummaryToggleButton = document.getElementById("OrderSummaryToggleButton"); 656 const orderSummaryToggleButtonLabel = document.getElementById("OrderSummaryToggleButtonLabel"); 657 const orderSummaryToggleButtonIcon = document.getElementById("OrderSummaryToggleButtonIcon"); 658 const orderSummaryToggleText = '@Translate("Show order summary")'; 659 660 orderSummaryToggleButton.addEventListener('click', function handleClick() { 661 if (orderSummaryToggleButtonLabel.textContent.toLowerCase().includes(orderSummaryToggleText.toLowerCase())) { 662 orderSummaryToggleButtonLabel.textContent = '@Translate("Hide order summary")'; 663 orderSummaryToggleButtonIcon.classList.add("rotate-180"); 664 } else { 665 orderSummaryToggleButtonLabel.textContent = orderSummaryToggleText; 666 orderSummaryToggleButtonIcon.classList.remove("rotate-180"); 667 } 668 }); 669 </script> 670 671 672 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 673 674 <div class="d-lg-block h-lg-auto collapse pt-2 pt-lg-0" id="orderSummary"> 675 <div class="d-flex flex-column gap-2 gap-lg-3 pb-2 pb-lg-3"> 676 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 677 @using Dynamicweb.Ecommerce.ProductCatalog 678 679 @functions { 680 private static string GetPrimaryImage(LoopItem orderline, string shopId) 681 { 682 bool isProductIdOrNumber = !string.IsNullOrEmpty(orderline.GetString("Ecom:Order:OrderLine.ProductID")) || !string.IsNullOrEmpty(orderline.GetString("Ecom:Order:OrderLine.ProductNumber")); //Live Cart orderlines may not return ProductId. Manually entered products may not have ProductNumber 683 bool isProduct = orderline.GetBoolean("Ecom:Order:OrderLine.IsProduct") || (orderline.GetBoolean("Ecom:Order:OrderLine.IsDiscount") && isProductIdOrNumber); 684 string productId = orderline.GetString("Ecom:Order:OrderLine.ProductID"); 685 string variantId = orderline.GetString("Ecom:Order:OrderLine.ProductVariantID"); 686 687 if (!isProduct || string.IsNullOrEmpty(productId)) return ""; 688 689 ProductViewModelSettings productSetting = new ProductViewModelSettings 690 { 691 LanguageId = Dynamicweb.Ecommerce.Common.Context.LanguageID, 692 CurrencyCode = Dynamicweb.Ecommerce.Common.Context.Currency.Code, 693 CountryCode = Dynamicweb.Ecommerce.Common.Context.Country.Code2, 694 ShopId = shopId 695 }; 696 ProductViewModel product = ViewModelFactory.CreateView(productSetting, productId, variantId); 697 return product.DefaultImage.Value; 698 } 699 } 700 701 @{ 702 var orderlines = GetLoop("OrderLines"); 703 } 704 705 @for (int i = orderlines.Count - 1; i >= 0; i--) 706 { 707 var orderline = orderlines[i]; 708 string name = orderline.GetString("Ecom:Order:OrderLine.ProductName"); 709 string orderlineImage = GetPrimaryImage(orderline, GetString("Ecom:Order.ShopID")); 710 string image = "/Admin/Public/GetImage.ashx?width=" + 180 + "&height=" + 180 + "&crop=5&fillcanvas=true&Background=ffffff&image=" + orderlineImage + "&format=webp"; 711 image = !orderlineImage.StartsWith("/Files/", StringComparison.OrdinalIgnoreCase) ? orderlineImage : image; 712 string removeFromBasketLink = orderline.GetString("Ecom:Order:OrderLine.DeleteLink"); 713 string priceTotalWithDiscounts = orderline.GetString("Ecom:Order:OrderLine.TotalPriceWithProductDiscounts.PriceFormatted"); 714 string priceBefore = orderline.GetString("Ecom:Product.InformativePrice.PriceFormatted"); 715 string unitPrice = orderline.GetString("Ecom:Order:OrderLine.UnitPrice.PriceFormatted"); 716 string discountPrice = orderline.GetString("Ecom:Order:OrderLine.UnitPriceWithProductDiscount.PriceFormatted"); 717 string discountTotal = orderline.GetString("Ecom:Order:OrderLine.TotalDiscount.PriceFormatted"); 718 string variantText = orderline.GetString("Ecom:Order:OrderLine.ProductVariantText"); 719 var orderlineId = orderline.GetValue("Ecom:Order:OrderLine.Id"); 720 var quantity = orderline.GetDouble("Ecom:Order:OrderLine.Quantity"); 721 var unitName = orderline.GetString("Ecom:Order:OrderLine.UnitName"); 722 string primaryGroupId = orderline.GetString("Ecom:Order:OrderLine.PrimaryOrDefaultGroupId"); 723 string productId = orderline.GetString("Ecom:Order:OrderLine.ProductID"); 724 string variantId = orderline.GetString("Ecom:Order:OrderLine.ProductVariantID"); 725 @*START CUSTOM CODE*@ 726 var productNumber = orderline.GetString("Ecom:Order:OrderLine.ProductNumber"); 727 @*END CUSTOM CODE*@ 728 729 string link = "Default.aspx?ID=" + GetPageIdByNavigationTag("Shop"); 730 link += $"&GroupID={primaryGroupId}"; 731 link += $"&ProductID={productId}"; 732 link += !string.IsNullOrEmpty(variantId) ? $"&VariantID={variantId}" : ""; 733 734 bool isProductIdOrNumber = !string.IsNullOrEmpty(orderline.GetString("Ecom:Order:OrderLine.ProductID")) || !string.IsNullOrEmpty(orderline.GetString("Ecom:Order:OrderLine.ProductNumber")); //Live Cart orderlines may not return ProductId. Manually entered products may not have ProductNumber 735 bool isProduct = orderline.GetBoolean("Ecom:Order:OrderLine.IsProduct") || (orderline.GetBoolean("Ecom:Order:OrderLine.IsDiscount") && isProductIdOrNumber); 736 737 if (isProduct) 738 { 739 <article class="grid grid-12"> 740 741 <div class="g-col-2"> 742 <a href="@link" class="ratio ratio-1x1 d-block " title="@name"> 743 <img src="@image" style="object-fit: contain;" alt="@name"> 744 </a> 745 </div> 746 747 <div class="g-col-10"> 748 749 <div class="d-flex flex-column gap-1"> 750 @* Title *@ 751 <h3 class="h6 fs-7 m-0"> 752 <a href="@link" class="text-decoration-none" title="@name">@name</a> 753 </h3> 754 755 @*START CUSTOM CODE - Show product number*@ 756 @if (!string.IsNullOrEmpty(productNumber)) 757 { 758 <p class="fs-8 fw-bold m-0">@productNumber</p> 759 } 760 @*END CUSTOM CODE*@ 761 762 @* Variants *@ 763 @if (!string.IsNullOrEmpty(variantText)) 764 { 765 <p class="fs-8 m-0">@variantText</p> 766 } 767 768 @if (orderline.GetBoolean("Ecom:Order:OrderLine.IsDiscount")) 769 { 770 @* Free product notice *@ 771 <p class="fs-8 m-0">@Translate("Free product")</p> 772 } 773 else 774 { 775 @* Unit price *@ 776 <p class="fs-8 m-0"> 777 @if (!string.IsNullOrEmpty(unitName)) 778 { 779 <span>@unitName: </span> 780 } 781 @if (discountPrice == unitPrice) 782 { 783 <span class="text-price">@unitPrice</span> 784 } 785 else 786 { 787 <span class="text-price">@discountPrice</span> 788 <span class="text-decoration-line-through"> 789 <span class="text-price">@unitPrice</span> 790 </span> 791 } 792 </p> 793 } 794 <div class="d-flex flex-row justify-content-between"> 795 @* Quantity *@ 796 <span class="fs-8 d-block">@Translate("Qty"): @quantity</span> 797 798 <div class="text-end flex-fill"> 799 @* Total *@ 800 <span class="h6 d-block fs-7 m-0"> 801 <span class="text-price">@priceTotalWithDiscounts</span> 802 </span> 803 @if (orderline.GetDouble("Ecom:Order:OrderLine.TotalDiscount.Price.Value") != 0.0) 804 { 805 <span class="d-block fs-8"> 806 <span class="text-price">@discountTotal</span> 807 </span> 808 } 809 </div> 810 </div> 811 </div> 812 </div> 813 </article> 814 } 815 } 816 817 </div> 818 819 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 820 821 @{ 822 double totalPriceWithoutOrderDiscountsFeesAndTaxesValue = GetDouble("Ecom:Order.TotalPriceWithoutDiscountsFeesAndTaxes.Price.Value") + GetDouble("Ecom:Order.TotalProductDiscount.Price.Value"); 823 var orderCurrency = Dynamicweb.Ecommerce.Services.Currencies.GetCurrency(GetString("Ecom:Order.Currency.Code")); 824 string totalPriceWithoutOrderDiscountsFeesAndTaxes = Dynamicweb.Ecommerce.Services.Currencies.Format(orderCurrency, totalPriceWithoutOrderDiscountsFeesAndTaxesValue); 825 826 string showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower(); 827 bool neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 828 829 bool disableVouchers = Pageview.CurrentParagraph?.Item["DisableVouchers"] != null ? (Boolean)Pageview.CurrentParagraph.Item["DisableVouchers"] : false; 830 disableVouchers = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("CompletedOrderId")) ? true : disableVouchers; 831 832 <div class="d-flex flex-column gap-2 gap-lg-3 pb-3 bottom-0 sticky-receipt theme" id="orderSummaryFooter"> 833 834 @if (!disableVouchers && Pageview.CurrentParagraph?.Item.SystemName != "Swift_QuoteCheckoutApp") 835 { 836 <text> 837 @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> 838 @using Dynamicweb.Ecommerce.Orders 839 840 @{ 841 string voucherCode = GetString("Ecom:Order.Customer.VoucherCode"); 842 string voucherCodeError = GetString("Ecom:Cart.ValidationError.EcomOrderVoucherCode.ErrorMessage"); 843 string validState = string.Empty; 844 bool vouchersAppliedAsDiscounts = false; 845 846 IEnumerable<string> voucherCodes = new List<string>(); 847 Order order = new OrderService().GetById(GetString("Ecom:Order.ID")); 848 849 850 if (!string.IsNullOrWhiteSpace(voucherCode)) 851 { 852 if (order.VoucherUseType.HasFlag(VoucherUseCategoryType.Discount)) 853 { 854 voucherCodes = voucherCode.Split(new string[] { ",", ";", " " }, StringSplitOptions.RemoveEmptyEntries); 855 vouchersAppliedAsDiscounts = true; 856 } 857 else 858 { 859 voucherCodes = new string[] { voucherCode.Trim() }; 860 } 861 } 862 863 var voucherErrors = new List<string>(); 864 if(!vouchersAppliedAsDiscounts) 865 { 866 foreach (string code in voucherCodes) 867 { 868 Dynamicweb.Ecommerce.Orders.Vouchers.Voucher vouch = Dynamicweb.Ecommerce.Services.Vouchers.GetVoucherByCode(code); 869 if (vouch == null) 870 { 871 validState = "is-invalid"; 872 voucherErrors.Add(Translate("Voucher") + " <span class='fw-bold'>" + code + "</span> " + Translate("not found")); 873 continue; 874 } 875 if (vouch.DateUsed.HasValue) 876 { 877 validState = "is-invalid"; 878 voucherErrors.Add(Translate("Voucher") + " <span class='fw-bold'>" + code + "</span> " + Translate("already used")); 879 continue; 880 } 881 } 882 } 883 884 var voucherErrorMessage = string.Join(",", voucherErrors); 885 886 <div class="py-3 border-top" id="orderVoucherForm"> 887 <form method="post" id="VoucherForm"> 888 <div class="input-group input-primary-button-group has-validation"> 889 <input type="text" class="form-control @(validState)" name="EcomOrderVoucherCodeField" placeholder="@Translate("Add voucher here")" id="EcomOrderVoucherCodeField" value="" aria-label="@Translate("Voucher input")" oninput="document.querySelector('#EcomOrderVoucherCode').value = this.value;" onkeyup="document.querySelector('#EcomOrderVoucherCode').value = this.value;"> 890 <button class="btn btn-sm btn-primary d-inline-flex align-items-center justify-content-center" type="submit" id="EcomOrderVoucherApply" style="min-width: 100px;"> 891 <span>@Translate("Apply")</span> 892 </button> 893 894 <div class="invalid-feedback"> 895 @voucherErrorMessage 896 </div> 897 </div> 898 <input type="hidden" name="EcomOrderVoucherCode" id="EcomOrderVoucherCode" value="@voucherCode"> 899 <label for="EcomOrderVoucherCodeField" class="visually-hidden">@Translate("Add voucher here")</label> 900 </form> 901 902 @if (!string.IsNullOrWhiteSpace(voucherCode) && vouchersAppliedAsDiscounts) 903 { 904 <div class="d-flex flex-wrap gap-2 pt-3"> 905 906 @foreach (string code in voucherCodes) 907 { 908 <form method="post"> 909 <input type="hidden" name="EcomOrderVoucherCode" value="@voucherCode.Replace(code+",", "").Replace(","+code, "").Replace(code, "")"> 910 <span class="badge fw-normal d-inline-flex align-items-center justify-content-center opacity-50 opacity-100-hover" style="background-color:var(--swift-foreground-color);color:var(--swift-background-color);"> 911 <span class="icon-2"> 912 @ReadFile("/Files/Templates/Designs/Swift/Assets/icons/tag.svg") 913 </span> 914 <span class="mx-2">@code</span> 915 <button type="submit" class="text-reset bg-transparent border-0 p-0" aria-label="@Translate("Remove voucher")" id="RemoveVoucherButton"> 916 <span class="icon-2"> 917 @ReadFile("/Files/Templates/Designs/Swift/Assets/icons/x.svg") 918 </span> 919 </button> 920 </span> 921 </form> 922 } 923 </div> 924 } 925 @voucherCodeError 926 </div> 927 } 928 929 </text> 930 } 931 932 <div class="fs-8 border-top pt-2 pt-lg-3"> 933 @* Subtotal *@ 934 <div class="d-flex justify-content-between fw-bold"> 935 <span>@Translate("Subtotal")</span> 936 <span class="text-end"> 937 <span class="d-block"> 938 @if (GetDouble("Ecom:Order.TotalPriceWithoutDiscountsFeesAndTaxes.Price.Value") != totalPriceWithoutOrderDiscountsFeesAndTaxesValue) 939 { 940 <span class="text-price fw-normal text-decoration-line-through">@GetString("Ecom:Order.TotalPriceWithoutDiscountsFeesAndTaxes.PriceFormatted")</span> 941 } 942 <span class="text-price">@totalPriceWithoutOrderDiscountsFeesAndTaxes</span> 943 </span> 944 945 @if (!neverShowVat && showPricesWithVat == "false") 946 { 947 <span class="fs-8 fw-normal d-block">@Translate("Excl. VAT")</span> 948 } 949 else if (!neverShowVat) 950 { 951 <span class="fs-8 fw-normal d-block">@Translate("Incl. VAT")</span> 952 } 953 </span> 954 </div> 955 956 @* Discounts (only order discounts) *@ 957 @foreach (LoopItem orderline in GetLoop("OrderLines")) 958 { 959 bool isDiscount = orderline.GetBoolean("Ecom:Order:OrderLine.IsDiscount"); 960 bool isProductIdOrNumber = !string.IsNullOrEmpty(orderline.GetString("Ecom:Order:OrderLine.ProductID")) || !string.IsNullOrEmpty(orderline.GetString("Ecom:Order:OrderLine.ProductNumber")); //Live Cart orderlines may not return ProductId. Manually entered products may not have ProductNumber 961 bool isOrderAmountDiscount = orderline.GetInteger("Ecom:Order:OrderLine.Type") == 1 && !isProductIdOrNumber; 962 if (isDiscount && isOrderAmountDiscount) 963 { 964 <div class="d-flex justify-content-between"><span>@orderline.GetString("Ecom:Order:OrderLine.ProductName")</span><span class="text-price">@orderline.GetString("Ecom:Order:OrderLine.TotalPriceWithProductDiscounts.PriceFormatted")</span></div> 965 } 966 } 967 968 @* Delivery *@ 969 @if (!string.IsNullOrEmpty(GetString("Ecom:Order.ShippingMethodID"))) 970 { 971 if (GetDouble("Ecom:Order.ShippingFee.Price.Value") != 0.0) 972 { 973 <div class="d-flex justify-content-between"> 974 <span>@Translate("Delivery")</span> 975 <span>@GetString("Ecom:Order.ShippingFee.PriceFormatted")</span> 976 </div> 977 } 978 } 979 else 980 { 981 <div class="d-flex justify-content-between"> 982 <span>@Translate("Delivery")</span> 983 <span>@Translate("Calculated in next step")</span> 984 </div> 985 } 986 987 @* Payment *@ 988 @if (!string.IsNullOrEmpty(GetString("Ecom:Order.PaymentMethodID"))) 989 { 990 if (GetDouble("Ecom:Order.PaymentFee.Price.Value") != 0) 991 { 992 <div class="d-flex justify-content-between"> 993 <span>@Translate("Payment")</span> 994 <span class="text-price">@GetString("Ecom:Order.PaymentFee.PriceFormatted")</span> 995 </div> 996 } 997 } 998 else 999 { 1000 <div class="d-flex justify-content-between"> 1001 <span>@Translate("Payment")</span> 1002 <span>@Translate("Calculated in next step")</span> 1003 </div> 1004 } 1005 1006 @* Taxes *@ 1007 @if (GetDouble("Ecom:Order.Taxes.Total.Price.Value") != 0) 1008 { 1009 <div class="d-flex justify-content-between mb-2"> 1010 <span>@Translate("Sales tax")</span> 1011 <span>@GetString("Ecom:Order.Taxes.Total.PriceFormatted")</span> 1012 </div> 1013 } 1014 </div> 1015 <div class="fs-8 border-top pt-2 pt-lg-3"> 1016 <div class="d-flex justify-content-between fs-6 fw-bold"> 1017 <span>@Translate("Total")</span> 1018 @if (!neverShowVat && showPricesWithVat == "false") 1019 { 1020 <span class="text-price text-end"> 1021 <span class="fs-5 d-block">@GetString("Ecom:Order.Price.PriceFormatted")</span> 1022 <span class="fs-8 fw-normal d-block">@Translate("Excl. VAT")</span> 1023 </span> 1024 } 1025 else if (!neverShowVat && showPricesWithVat == "true") 1026 { 1027 <span class="text-price text-end"> 1028 <span class="fs-5 d-block">@GetString("Ecom:Order.Price.PriceFormatted")</span> 1029 <span class="fs-8 fw-normal d-block">@Translate("Incl. VAT")</span> 1030 </span> 1031 } 1032 else 1033 { 1034 <span class="text-price fs-5">@GetString("Ecom:Order.Price.PriceFormatted")</span> 1035 } 1036 </div> 1037 1038 @if (!neverShowVat) 1039 { 1040 <div class="d-flex justify-content-between"><span>@Translate("VAT")</span><span class="text-price">@GetString("Ecom:Order.Price.VATFormatted")</span></div> 1041 if (showPricesWithVat == "false") 1042 { 1043 <div class="d-flex justify-content-between"><span>@Translate("Total incl. VAT")</span><span class="text-price">@GetString("Ecom:Order.OrderLines.Total.PriceWithVAT")</span></div> 1044 } 1045 } 1046 1047 @if (GetDouble("Ecom:Order.TotalDiscount.Price.Value") != 0) 1048 { 1049 <div class="d-flex justify-content-between"><span>@Translate("Discount")</span><span class="text-price">@GetString("Ecom:Order.TotalDiscount.PriceFormatted")</span></div> 1050 } 1051 </div> 1052 </div> 1053 } 1054 1055 </div> 1056 1057 </div> 1058 } 1059 1060 1061 </div> 1062 1063 <script> 1064 function submitForm() { 1065 document.querySelector("#CurrentStep").name = "@GetString("CartV2.CurrentStepButtonName")"; 1066 swift.PageUpdater.Update(document.querySelector("#ordersubmit")); 1067 } 1068 </script> 1069