Error executing template "Designs/Swift/eCom7/CartV2/Step/Cart.cshtml"
System.ArgumentNullException: Value cannot be null. (Parameter 'currency')
   at System.ArgumentNullException.Throw(String paramName)
   at Dynamicweb.Ecommerce.International.CurrencyService.Format(Currency currency, Double value, Boolean showSymbol)
   at CompiledRazorTemplates.Dynamic.RazorEngine_d0d43acceebd424eb5edcd7e62445be1.RenderOrderSummary(Boolean renderVoucher)
   at CompiledRazorTemplates.Dynamic.RazorEngine_d0d43acceebd424eb5edcd7e62445be1.ExecuteAsync()
   at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag)
   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>> @using Dynamicweb @using Dynamicweb.Environment @functions { string googleTagManagerID = ""; string googleAnalyticsMeasurementID = ""; bool allowTracking = true; } @{ var themeRaw = Pageview.CurrentParagraph.Item["Theme"]?.ToString(); string theme = !string.IsNullOrEmpty(themeRaw) ? " theme " + themeRaw.Replace(" ", "").Trim().ToLower() : ""; googleTagManagerID = Pageview.AreaSettings.GetString("GoogleTagManagerID"); googleAnalyticsMeasurementID = Pageview.AreaSettings.GetString("GoogleAnalyticsMeasurementID"); if (CookieManager.IsCookieManagementActive) { var cookieOptInLevel = CookieManager.GetCookieOptInLevel(); allowTracking = cookieOptInLevel == CookieOptInLevel.All || (cookieOptInLevel == CookieOptInLevel.Functional && CookieManager.GetCookieOptInCategories().Contains("Statistical")); } } <div class="grid gap-0" id="Cart"> <header class="g-col-12"> @RenderPageHeader() </header> <div class="g-col-12 g-col-lg-8 pe-lg-5 pb-md-5"> @RenderErrors() <form name="ordersubmit" id="ordersubmit" method="post" autocomplete="off"> <header class="py-2 pt-lg-5 border-bottom d-none d-lg-block"> <div class="grid" style="line-height: 1;"> <div class="g-col-2">@Translate("Product")</div> <div class="g-col-9 grid"> <div class="g-col-2 g-start-8">@Translate("Quantity")</div> </div> <div class="g-col-1 text-end">@Translate("Total")</div> </div> </header> @RenderOrderLinesForTracking() @RenderOrderLines() <div class="d-none d-lg-block"> @RenderCartNavigation() </div> </form> </div> <aside class="g-col-12 g-col-lg-4 position-relative"> <div class="p-3 p-lg-5 pb-lg-4@(theme)"> <header> <h4 class="fs-6 fw-normal mb-2">@Translate("Order summary")</h4> </header> @RenderOrderSummary() <div class="d-block d-lg-none"> @RenderCartNavigation() </div> </div> </aside> </div> @functions { string RenderPageHeader() { <div class="pb-3 pb-lg-0 pt-3 pt-lg-5"> <h1 class="h3 mb-2">@Translate("Shopping Cart")</h1> <p class="mb-0"><span>@Translate("Items in your shopping cart"):</span> <span>@GetString("Ecom:Order.OrderLines.TotalProductQuantity")</span></p> </div> return string.Empty; } string RenderOrderLinesForTracking() { if ((!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) || !string.IsNullOrWhiteSpace(googleTagManagerID)) && allowTracking) { <script> gtag("event", "view_cart", { @* currency: "@GetString("Ecom:Order.Currency.Code")", *@ value: @GetDouble("Ecom:Order.Price.PriceWithVAT.Value").ToString("0.00", System.Globalization.CultureInfo.InvariantCulture), items: [ @foreach (LoopItem orderline in GetLoop("OrderLines")) { <text> { item_id: "@orderline.GetString("Ecom:Order:OrderLine.ProductID")", item_name: "@Dynamicweb.Core.Encoders.HtmlEncoder.JavaScriptStringEncode(orderline.GetString("Ecom:Order:OrderLine.ProductName"))", @* currency: "@orderline.GetString("Ecom:Order:OrderLine.UnitPrice.CurrencyCode")", *@ price: @orderline.GetDouble("Ecom:Order:OrderLine.UnitPrice.Price.Value").ToString("0.00", System.Globalization.CultureInfo.InvariantCulture), quantity: @orderline.GetDouble("Ecom:Order:OrderLine.Quantity").ToString("0.00", System.Globalization.CultureInfo.InvariantCulture) },</text> } ] }); </script> } return string.Empty; } string RenderOrderLines() { <text> @foreach (LoopItem orderline in GetLoop("OrderLines")) { @RenderOrderLineItem(orderline) } </text> <script> function debounce(func, wait, immediate) { var timeout; return function () { var context = this, args = arguments; var later = function () { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; var UpdateQuantity = debounce(function (input, stock) { var inputValue = parseFloat(input.value); var stock = parseFloat(stock); if (inputValue <= stock) { input.classList.remove("is-invalid"); input.closest(".js-input-group").querySelector(".js-not-enough-stock").classList.add("d-none"); document.querySelector("#ordersubmit").submit(); } else { input.value = stock; input.classList.add("is-invalid"); input.closest(".js-input-group").querySelector(".js-not-enough-stock").classList.remove("d-none"); } }, 300); </script> return string.Empty; } string RenderCartNavigation() { bool anonymousUser = Pageview.User == null; string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; int currentUserId = Dynamicweb.Core.Converter.ToInt32(GetGlobalValue("Global:Extranet.UserID")); var shopPageId = GetPageIdByNavigationTag("Shop"); var cart = Dynamicweb.Frontend.ContentViewModelFactory.CreateParagraphInfoViewModel(Pageview.CurrentParagraph)?.Item ?? null; var checkoutAnonymousLink = cart.GetLink("CheckoutAnonymousPageLink") is object ? cart.GetLink("CheckoutAnonymousPageLink").Url : string.Empty; var checkoutSignedInLink = cart.GetLink("CheckoutSignedInPageLink") is object ? cart.GetLink("CheckoutSignedInPageLink").Url : string.Empty; string checkoutLink = currentUserId == 0 ? checkoutAnonymousLink : checkoutSignedInLink; var quoteCheckoutLink = cart.GetLink("QuoteCheckoutPageLink") is object ? cart.GetLink("QuoteCheckoutPageLink").Url : string.Empty; <div class="align-items-center d-grid d-lg-flex gap-2 justify-content-lg-end mt-lg-4"> <a href="Default.aspx?ID=@shopPageId" class="btn btn-link link-secondary text-decoration-none me-lg-3 order-last order-lg-first swift_cartbackbutton"> <span class="d-flex align-items-center justify-content-center position-relative"> <span class="icon-2 me-1 position-absolute position-lg-static start-0"> @ReadFile(iconPath + "chevron-left.svg") </span> <span>@Translate("Continue shopping")</span> </span> </a> @if (!string.IsNullOrEmpty(quoteCheckoutLink) && !anonymousUser) { <a href="@quoteCheckoutLink" class="btn btn-secondary"> <span class="d-flex align-items-center justify-content-center position-relative"> <span>@Translate("Request quote")</span> <span class="icon-2 ms-1 position-absolute position-lg-static end-0"> @ReadFile(iconPath + "chevron-right.svg") </span> </span> </a> } <a href="@checkoutLink" class="btn btn-primary" id="GoToCheckoutButton"> <span class="d-flex align-items-center justify-content-center position-relative"> <span>@Translate("Checkout")</span> <span class="icon-2 ms-1 position-absolute position-lg-static end-0"> @ReadFile(iconPath + "chevron-right.svg") </span> </span> </a> </div> return string.Empty; } } @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @using Dynamicweb.Ecommerce.Orders @functions { string RenderErrors(){ if (GetLoop("ValidationErrors").Count() != 0) { <div class="alert alert-warning" role="alert"> <ul class="m-0 list-unstyled"> @foreach (LoopItem item in GetLoop("ValidationErrors")) { <li>@item.GetValue("Ecom:Cart.ValidationError.ErrorMessage")</li> } </ul> </div> } return string.Empty; } } @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @functions { string RenderOrderLineItem(LoopItem orderline) { string googleTagManagerID = Pageview.AreaSettings.GetString("GoogleTagManagerID"); string googleAnalyticsMeasurementID = Pageview.AreaSettings.GetString("GoogleAnalyticsMeasurementID"); bool allowTracking = true; if (CookieManager.IsCookieManagementActive) { var cookieOptInLevel = CookieManager.GetCookieOptInLevel(); allowTracking = cookieOptInLevel == CookieOptInLevel.All || (cookieOptInLevel == CookieOptInLevel.Functional && CookieManager.GetCookieOptInCategories().Contains("Statistical")); } bool neverOutOfStock = orderline.GetBoolean("Ecom:Product.NeverOutOfStock"); int stockQuantity = neverOutOfStock ? 9999999 : orderline.GetInteger("Ecom:Product.Stock"); string name = orderline.GetString("Ecom:Order:OrderLine.ProductName"); string image = "/Admin/Public/GetImage.ashx?width=" + 180 + "&height=" + 180 + "&image=" + orderline.GetString("Ecom:Product.PrimaryImage") + "&format=webp"; string removeFromBasketLink = orderline.GetString("Ecom:Order:OrderLine.DeleteLink"); string priceTotalWithDiscounts = orderline.GetString("Ecom:Order:OrderLine.TotalPriceWithProductDiscounts.PriceFormatted"); string priceTotalWithDiscountsClean = orderline.GetString("Ecom:Order:OrderLine.TotalPriceWithProductDiscounts.Price"); string unitPrice = orderline.GetString("Ecom:Order:OrderLine.UnitPrice.PriceFormatted"); string unitPriceClean = orderline.GetDouble("Ecom:Order:OrderLine.UnitPrice.Price").ToString("0.00", System.Globalization.CultureInfo.InvariantCulture); string unitPriceCurrency = orderline.GetString("Ecom:Order:OrderLine.Price.CurrencyCode"); string discountPrice = orderline.GetString("Ecom:Order:OrderLine.UnitPriceWithProductDiscount.PriceFormatted"); string discountTotal = orderline.GetString("Ecom:Order:OrderLine.TotalDiscount.PriceFormatted"); string variantText = orderline.GetString("Ecom:Order:OrderLine.ProductVariantText"); var orderlineId = orderline.GetValue("Ecom:Order:OrderLine.Id"); var quantity = neverOutOfStock || stockQuantity >= orderline.GetDouble("Ecom:Order:OrderLine.Quantity") ? orderline.GetDouble("Ecom:Order:OrderLine.Quantity") : stockQuantity; var unitName = orderline.GetString("Ecom:Order:OrderLine.UnitName"); string primaryGroupId = orderline.GetString("Ecom:Order:OrderLine.PrimaryOrDefaultGroupId"); string productId = orderline.GetString("Ecom:Order:OrderLine.ProductID"); string variantId = orderline.GetString("Ecom:Order:OrderLine.ProductVariantID"); var stock = orderline.GetInteger("Ecom:Product.Stock"); string unitId = orderline.GetString("Ecom:Order:OrderLine.UnitID"); string minQty = orderline.GetDouble("Ecom:Product.PurchaseMinimumQuantity") != 1 ? "min=\"" + orderline.GetDouble("Ecom:Product.PurchaseMinimumQuantity").ToString() + "\"" : "min=\"1\""; string stepQty = orderline.GetDouble("Ecom:Product.PurchaseQuantityStep") > 1 ? orderline.GetDouble("Ecom:Product.PurchaseQuantityStep").ToString() : "1"; string qtyValidCheck = stepQty != "1" ? "onkeyup=\"swift.Cart.QuantityValidate(event)\"" : ""; string link = "Default.aspx?ID=" + GetPageIdByNavigationTag("Shop"); link += $"&GroupID={primaryGroupId}"; link += $"&ProductID={productId}"; link += !string.IsNullOrEmpty(variantId) ? $"&VariantID={variantId}" : ""; bool isProduct = orderline.GetBoolean("Ecom:Order:OrderLine.IsProduct") || (orderline.GetInteger("Ecom:Order:OrderLine.Type") == 3 && !string.IsNullOrEmpty(orderline.GetString("Ecom:Order:OrderLine.ProductNumber"))); if (isProduct) { <article class="grid pt-3" style="row-gap: 0;" data-product-id="@productId" data-variant-id="@variantId" data-unit-id="@unitId" data-orderline-total-price="@priceTotalWithDiscountsClean" data-orderline-unit-price="@unitPriceClean"> <div class="g-col-3 g-col-lg-2"> <a href="@link" class="ratio ratio-1x1 d-block" title="@name"> <img class="cart-item-img" src="@image" style="object-fit: contain;" alt="@name"> </a> </div> <div class="g-col-9 g-col-lg-10"> <div class="grid" style="row-gap: 0.5rem;"> <div class="g-col-12 g-col-md-8 grid grid-7 grid-md-9" style="row-gap: 0.5rem;"> <div class="g-col-7"> @* Title *@ <h3 class="h6 fs-7 fs-md-6 mb-0"> <a href="@link" class="text-decoration-none" title="@name">@name</a> </h3> @* Variants *@ @if (!string.IsNullOrEmpty(variantText)) { <p class="mt-2 mb-0 fs-7 fs-md-6">@variantText</p> } @if (orderline.GetInteger("Ecom:Order:OrderLine.Type") == 3 && !string.IsNullOrEmpty(orderline.GetString("Ecom:Order:OrderLine.ProductNumber"))) { @* Free product notice *@ <p class="mt-2 mb-0 fs-7 fs-md-6 opacity-75">@Translate("Free product")</p> } else { @* Unit price *@ <p class="fs-7 fs-md-6 mt-2 mb-0"> @if (!string.IsNullOrEmpty(unitName)) { <span>@unitName: </span> } @if (discountPrice == unitPrice) { <span class="text-price">@unitPrice</span> } else { <span class="text-price">@discountPrice</span> <span class="text-decoration-line-through fs-7"> <span class="text-price">@unitPrice</span> </span> } </p> } </div> <div class="g-col-7 g-col-md-2"> @if (orderline.GetInteger("Ecom:Order:OrderLine.Type") != 3) { @* Quantity *@ <div class="js-input-group"> <label for="QuantityOrderLine@(orderlineId)" class="visually-hidden">@Translate("Quantity"):</label> <input type="number" id="QuantityOrderLine@(orderlineId)" step="@stepQty" @minQty class="form-control text-center swift_quantity-field" value="@quantity" name="QuantityOrderLine@(orderlineId)" onChange="UpdateQuantity(this, '@stockQuantity')" @qtyValidCheck style="max-width: 5.5rem;"> @if (stepQty != "1") { <div class="invalid-feedback d-none"> @Translate("Please select a quantity that is dividable by") @stepQty </div> } <div class="invalid-feedback js-not-enough-stock d-none"> @Translate("We do not have enough products in stock") </div> </div> } else { <span>@quantity</span> } </div> </div> <div class="g-col-12 g-col-md-4 text-end"> @* Total *@ <span class="h6 mb-0 d-block fs-7 fs-md-6"> <span class="text-price">@priceTotalWithDiscounts</span> </span> @if (orderline.GetDouble("Ecom:Order:OrderLine.TotalDiscount.Price.Value") != 0) { <span class="m-0 d-block fs-8"> <span class="text-price">@discountTotal</span> </span> } </div> <div class="g-col-12 g-col-md-4"> @{ string clickProductLink = string.Empty; if (!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) && allowTracking) { clickProductLink = "onclick=\"return removeProductLink('" + @productId + "', '" + @Dynamicweb.Core.Encoders.HtmlEncoder.JavaScriptStringEncode(name) + "', '" + @Dynamicweb.Core.Encoders.HtmlEncoder.JavaScriptStringEncode(variantText) + "', '" + @unitPriceCurrency + "', '" + @unitPriceClean + "', '" + @quantity.ToString().Replace(",", ".") + "')\""; } } <a href="@removeFromBasketLink" class="btn btn-link btn-sm p-0 m-0 fs-8" title="@Translate("Remove")" @clickProductLink>@Translate("Remove")</a> @if ((!string.IsNullOrWhiteSpace(googleAnalyticsMeasurementID) || !string.IsNullOrWhiteSpace(googleTagManagerID)) && allowTracking) { <script> function removeProductLink(productId, productName, productVariant, productCurrency, productPrice, productQuantity) { if (typeof gtag !== "undefined") { gtag("event", "remove_from_cart", { currency: productCurrency, value: productPrice, items: [ { item_id: productId, item_name: productName, item_variant: productVariant, currency: productCurrency, price: productPrice, item_list_id: "cart", item_list_name: "Cart", quantity: productQuantity } ] }); } } </script> } </div> @if (quantity > stock && stock >= 1) { <div class="g-col-12 g-col-md-8 text-end fs-8 pt-2 pt-lg-3"> <span title="@Translate("cart.NotAllInStock")"></span> @Translate("cart.NotAllInStock") (@stock) <a class="btn btn-link btn-sm p-0 m-0 fs-8" href="javascript:void(0);" onclick="javascript:document.getElementById('QuantityOrderLine@(orderlineId)').value='@stock';var element=document.getElementById('QuantityOrderLine@(orderlineId)');var event=new Event('change');element.dispatchEvent(event);">@Translate("Set to max stock")</a> <input type="hidden" name="AllInStock" value="false"/> </div> } </div> </div> @* Bottom border *@ <span class="g-col-12 mt-3"> <span class="d-none d-lg-block border-bottom"></span> </span> </article> } return string.Empty; } } @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @functions { string RenderOrderSummary(bool renderVoucher = true) { double totalPriceWithoutOrderDiscountsFeesAndTaxesValue = GetDouble("Ecom:Order.TotalPriceWithoutDiscountsFeesAndTaxes.Price.Value") + GetDouble("Ecom:Order.TotalProductDiscount.Price.Value"); var orderCurrency = Dynamicweb.Ecommerce.Services.Currencies.GetCurrency(GetString("Ecom:Order.Currency.Code")); string totalPriceWithoutOrderDiscountsFeesAndTaxes = Dynamicweb.Ecommerce.Services.Currencies.Format(orderCurrency, totalPriceWithoutOrderDiscountsFeesAndTaxesValue); string showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower(); bool neverShowVat = string.IsNullOrEmpty(showPricesWithVat); bool disableVouchers = Pageview.CurrentParagraph.Item["DisableVouchers"] != null ? (Boolean)Pageview.CurrentParagraph.Item["DisableVouchers"] : false; <div class="d-flex flex-column gap-2 gap-lg-3 pb-3 bottom-0 sticky-receipt theme" id="orderSummaryFooter"> @if (renderVoucher && !disableVouchers && Pageview.CurrentParagraph.Item.SystemName != "Swift_QuoteCheckoutApp") { // @RenderVoucherForm() } <div class="fs-8 border-top pt-2 pt-lg-3"> @* Subtotal *@ <div class="d-flex justify-content-between fw-bold"> <span>@Translate("Subtotal")</span> <span class="text-end"> <span class="d-block"> @if (GetDouble("Ecom:Order.TotalPriceWithoutDiscountsFeesAndTaxes.Price.Value") != totalPriceWithoutOrderDiscountsFeesAndTaxesValue) { <span class="text-price fw-normal text-decoration-line-through">@GetString("Ecom:Order.TotalPriceWithoutDiscountsFeesAndTaxes.PriceFormatted")</span> } <span class="text-price">@totalPriceWithoutOrderDiscountsFeesAndTaxes</span> </span> @if (!neverShowVat && showPricesWithVat == "false") { <span class="fs-8 fw-normal d-block">@Translate("Excl. VAT")</span> } else if (!neverShowVat) { <span class="fs-8 fw-normal d-block">@Translate("Incl. VAT")</span> } </span> </div> @* Discounts (only order discounts) *@ @foreach (LoopItem orderline in GetLoop("OrderLines")) { bool isDiscount = orderline.GetBoolean("Ecom:Order:OrderLine.IsDiscount"); bool isOrderDiscount = orderline.GetInteger("Ecom:Order:OrderLine.Type") == 1; if (isDiscount && isOrderDiscount) { <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> } } @* Delivery *@ @if (!string.IsNullOrEmpty(GetString("Ecom:Order.ShippingMethodID"))) { if (GetDouble("Ecom:Order.ShippingFee.Price.Value") != 0.0) { <div class="d-flex justify-content-between"> <span>@Translate("Delivery")</span> <span>@GetString("Ecom:Order.ShippingFee.PriceFormatted")</span> </div> } } else { <div class="d-flex justify-content-between"> <span>@Translate("Delivery")</span> <span>@Translate("Calculated in next step")</span> </div> } @* Payment *@ @if (!string.IsNullOrEmpty(GetString("Ecom:Order.PaymentMethodID"))) { if (GetDouble("Ecom:Order.PaymentFee.Price.Value") != 0) { <div class="d-flex justify-content-between"> <span>@Translate("Payment")</span> <span class="text-price">@GetString("Ecom:Order.PaymentFee.PriceFormatted")</span> </div> } } else { <div class="d-flex justify-content-between"> <span>@Translate("Payment")</span> <span>@Translate("Calculated in next step")</span> </div> } @* Taxes *@ @if (GetDouble("Ecom:Order.Taxes.Total.Price.Value") != 0) { <div class="d-flex justify-content-between mb-2"> <span>@Translate("Sales tax")</span> <span>@GetString("Ecom:Order.Taxes.Total.PriceFormatted")</span> </div> } </div> <div class="fs-8 border-top pt-2 pt-lg-3"> <div class="d-flex justify-content-between fs-6 fw-bold"> <span>@Translate("Total")</span> @if (!neverShowVat && showPricesWithVat == "false") { <span class="text-price text-end"> <span class="fs-5 d-block">@GetString("Ecom:Order.Price.PriceFormatted")</span> <span class="fs-8 fw-normal d-block">@Translate("Excl. VAT")</span> </span> } else if (!neverShowVat && showPricesWithVat == "true") { <span class="text-price text-end"> <span class="fs-5 d-block">@GetString("Ecom:Order.Price.PriceFormatted")</span> <span class="fs-8 fw-normal d-block">@Translate("Incl. VAT")</span> </span> } else { <span class="text-price fs-5">@GetString("Ecom:Order.Price.PriceFormatted")</span> } </div> @if (!neverShowVat) { <div class="d-flex justify-content-between"><span>@Translate("VAT")</span><span class="text-price">@GetString("Ecom:Order.Price.VATFormatted")</span></div> if (showPricesWithVat == "false") { <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> } } @if (GetDouble("Ecom:Order.TotalDiscount.Price.Value") != 0) { <div class="d-flex justify-content-between"><span>@Translate("Discount")</span><span class="text-price">@GetString("Ecom:Order.TotalDiscount.PriceFormatted")</span></div> } </div> </div> return string.Empty; } } @inherits Dynamicweb.Rendering.RazorTemplateBase<Dynamicweb.Rendering.RazorTemplateModel<Dynamicweb.Rendering.Template>> @using Dynamicweb.Ecommerce.Orders @functions { string RenderVoucherForm() { string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; string voucherCode = GetString("Ecom:Order.Customer.VoucherCode"); string voucherCodeError = GetString("Ecom:Cart.ValidationError.EcomOrderVoucherCode.ErrorMessage"); var errors = new List<string>(); string validState = ""; bool vouchersAppliedAsDiscounts = false; IEnumerable<string> codes = new List<string>(); Order order = new OrderService().GetById(GetString("Ecom:Order.ID")); if (!string.IsNullOrWhiteSpace(voucherCode)) { if (order.VoucherUseType.HasFlag(VoucherUseCategoryType.Discount)) { codes = voucherCode.Split(new string[] { ",", ";", " " }, StringSplitOptions.RemoveEmptyEntries); vouchersAppliedAsDiscounts = true; } else { codes = new string[] { voucherCode.Trim() }; } } if (!vouchersAppliedAsDiscounts) { foreach (string code in codes) { Dynamicweb.Ecommerce.Orders.Vouchers.Voucher vouch = Dynamicweb.Ecommerce.Services.Vouchers.GetVoucherByCode(code); if (vouch == null) { validState = "is-invalid"; errors.Add(Translate("Voucher") + " <span class='fw-bold'>" + code + "</span> " + Translate("not found")); continue; } if (vouch.DateUsed.HasValue) { validState = "is-invalid"; errors.Add(Translate("Voucher") + " <span class='fw-bold'>" + code + "</span> " + Translate("already used")); continue; } } } <div class="py-3 border-top" id="orderVoucherForm"> <form method="post" id="VoucherForm"> <div class="input-group input-primary-button-group has-validation"> <input type="text" class="form-control @(validState)" name="EcomOrderVoucherCodeField" placeholder="@Translate("Add voucher here")" id="EcomOrderVoucherCodeField" value="" aria-label="@Translate("Voucher input")" onkeyup="document.querySelector('#EcomOrderVoucherCode').value = this.value;"> <button class="btn btn-sm btn-primary d-inline-flex align-items-center justify-content-center" type="submit" id="EcomOrderVoucherApply" style="min-width: 100px;"> <span>@Translate("Apply")</span> </button> <div class="invalid-feedback"> @{ var errorMessage = string.Join(",", errors); } @errorMessage </div> </div> <input type="hidden" name="EcomOrderVoucherCode" id="EcomOrderVoucherCode" value="@voucherCode"> <label for="EcomOrderVoucherCodeField" class="visually-hidden">@Translate("Add voucher here")</label> </form> @if (!string.IsNullOrWhiteSpace(voucherCode) && vouchersAppliedAsDiscounts) { <div class="d-flex flex-wrap gap-2 pt-3"> @foreach (string code in codes) { <form method="post"> <input type="hidden" name="EcomOrderVoucherCode" value="@voucherCode.Replace(code + ",", "").Replace("," + code, "").Replace(code, "")"> <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);"> <span class="icon-2"> @ReadFile(iconPath + "tag.svg") </span> <span class="mx-2">@code</span> <button type="submit" class="text-reset bg-transparent border-0 p-0" aria-label="@Translate("Remove voucher")" id="RemoveVoucherButton"> <span class="icon-2"> @ReadFile(iconPath + "x.svg") </span> </button> </span> </form> } </div> } @voucherCodeError </div> return string.Empty; } }