using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Threading.Tasks; using AutoMapper; using gehGassi.Core.Interfaces; using gehGassi.Core.Services; using gehGassi.Domain.Common; using gehGassi.Domain.Shop; using gehGassi.Permissions; using gehGassi.Web.Auth; using gehGassi.Web.Auth.Attributes; using gehGassi.Web.Helper; using gehGassi.Web.Hubs; using gehGassi.Web.Models; using gehGassi.Web.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Routing; using Microsoft.AspNetCore.StaticFiles; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Options; using NetTopologySuite; using NetTopologySuite.Geometries; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Processing; namespace gehGassi.Web.Controllers { /// /// Controller für Shop-Funktionen /// [Authorize] public class ShopController : BaseController { private readonly IMapper _mapper; private readonly IStringLocalizer _localizer; private readonly IProductService _productService; private readonly ICustomerService _customerService; private readonly IShopCalculationService _shopCalculationService; private readonly ICountryService _countryService; private readonly ILanguageService _languageService; private readonly ICartService _cartService; private readonly ISystemHubSender _systemHubSender; private readonly IListingService _listingService; private readonly IShopSettingsService _shopSettingsService; private readonly IOrderService _orderService; private readonly IWebHostEnvironment _hostEnvironment; private readonly IPayPalService _payPalService; private readonly IOptions _shopOptions; private readonly IEmailSender _emailSender; private readonly IKlarnaService _klarnaService; private readonly IAdvertisementService _advertisementService; private readonly IBannerService _bannerService; private readonly IPinService _pinService; private readonly IGeoLocationService _geoLocationService; private readonly IInvoiceService _invoiceService; private readonly IWebHostEnvironment _environment; private readonly IUrlHelperFactory _urlHelperFactory; /// /// Erstellt eine Instanz /// /// Instanz eines IMapper /// Instanz eines IStringLocalizer /// Instanz eines IProductService /// Instanz eines ICustomerService /// Instanz eines IShopCalculationService /// Instanz eines ICountryService /// Instanz eines ILanguageService /// Instanz eines ICartService /// Instanz eines ISystemHubSender /// Instanz eines IListingService /// Instanz eines IShopSettingsService /// Instanz eines IOrderService /// Instanz des IWebHostEnvironment /// Instanz eines IPayPalService /// Instanz von ShopOptions /// Instanz eines IEmailSender /// Instanz eines IKlarnaService /// Instanz eines IAdvertisementService /// Instanz eines IBannerService /// Instanz eines IPinService /// Instanz eines IGeoLocationService /// Instanz eines IInvoiceService /// Instanz eines IWebHostEnvironment /// Instanz einer IUrlHelperFactory public ShopController(IMapper mapper, IStringLocalizer localizer, IProductService productService, ICustomerService customerService, IShopCalculationService shopCalculationService, ICountryService countryService, ILanguageService languageService, ICartService cartService, ISystemHubSender systemHubSender, IListingService listingService, IShopSettingsService shopSettingsService, IOrderService orderService, IWebHostEnvironment hostEnvironment, IPayPalService payPalService, IOptions shopOptions, IEmailSender emailSender, IKlarnaService klarnaService, IAdvertisementService advertisementService, IBannerService bannerService, IPinService pinService, IGeoLocationService geoLocationService, IInvoiceService invoiceService, IWebHostEnvironment environment, IUrlHelperFactory urlHelperFactory) { _mapper = mapper; _localizer = localizer; _productService = productService; _customerService = customerService; _shopCalculationService = shopCalculationService; _countryService = countryService; _languageService = languageService; _cartService = cartService; _systemHubSender = systemHubSender; _listingService = listingService; _shopSettingsService = shopSettingsService; _orderService = orderService; _hostEnvironment = hostEnvironment; _payPalService = payPalService; _shopOptions = shopOptions; _emailSender = emailSender; _klarnaService = klarnaService; _advertisementService = advertisementService; _bannerService = bannerService; _pinService = pinService; _geoLocationService = geoLocationService; _invoiceService = invoiceService; _environment = environment; _urlHelperFactory = urlHelperFactory; } #region Shop /// /// Anzeigen des Shops allgemein für Kunden /// /// [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] public async Task Index() { var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null) { var model = new ShopFilterVm() { Filter = string.Empty, Categories = new List() }; return View(model); } return RedirectToAction("Error", "Home"); } /// /// Abrufen der Produkte /// /// Filter-Model /// PartialView [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [HttpPost] public async Task GetProducts([FromBody] ShopFilterVm model) { var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null) { var allowedBranches = customer.BranchesJson; var resultListVm = new List(); //1. Listen var products = await _productService.GetListingProductsAsync(OrderSource.Customer, customer.Address.CountryCode, allowedBranches, model.Categories, model.Filter, SelectedLanguage, FallbackLanguage, false); var productsList = products.ToList().Select(item => _mapper.Map(item)).ToList(); foreach (var itemVm in productsList) { //Preise berechnen var priceCalcultation = await _shopCalculationService.CalculatePriceAsync(itemVm.Id, User.CustomerId().Value, 1); itemVm.Price = priceCalcultation.Price; itemVm.Price2 = priceCalcultation.Price2; itemVm.OldPrice = priceCalcultation.OldPrice; itemVm.OldPrice2 = priceCalcultation.OldPrice2; itemVm.PriceGross = priceCalcultation.PriceGross; itemVm.Price2Gross = priceCalcultation.Price2Gross; itemVm.OldPriceGross = priceCalcultation.OldPriceGross; itemVm.OldPrice2Gross = priceCalcultation.OldPrice2Gross; itemVm.Tax = priceCalcultation.TaxRate; } resultListVm.AddRange(productsList); //2. Werbungen products = await _productService.GetAdvertisementProductsAsync(OrderSource.Customer, customer.Address.CountryCode, model.Categories, model.Filter, SelectedLanguage, FallbackLanguage, false); productsList = products.ToList().Select(item => _mapper.Map(item)).ToList(); foreach (var productShopVm in productsList) { //Preise berechnen var priceCalcultation = await _shopCalculationService.CalculatePriceAsync(productShopVm.Id, User.CustomerId().Value, 1); productShopVm.Price = priceCalcultation.Price; productShopVm.Price2 = priceCalcultation.Price2; productShopVm.OldPrice = priceCalcultation.OldPrice; productShopVm.OldPrice2 = priceCalcultation.OldPrice2; productShopVm.PriceGross = priceCalcultation.PriceGross; productShopVm.Price2Gross = priceCalcultation.Price2Gross; productShopVm.OldPriceGross = priceCalcultation.OldPriceGross; productShopVm.OldPrice2Gross = priceCalcultation.OldPrice2Gross; productShopVm.Tax = priceCalcultation.TaxRate; } resultListVm.AddRange(productsList); //3. Banner products = await _productService.GetBannerProductsAsync(OrderSource.Customer, customer.Address.CountryCode, model.Categories, model.Filter, SelectedLanguage, FallbackLanguage, false); productsList = products.ToList().Select(item => _mapper.Map(item)).ToList(); foreach (var productShopVm in productsList) { //Preise berechnen var priceCalcultation = await _shopCalculationService.CalculatePriceAsync(productShopVm.Id, User.CustomerId().Value, 1); productShopVm.Price = priceCalcultation.Price; productShopVm.Price2 = priceCalcultation.Price2; productShopVm.OldPrice = priceCalcultation.OldPrice; productShopVm.OldPrice2 = priceCalcultation.OldPrice2; productShopVm.PriceGross = priceCalcultation.PriceGross; productShopVm.Price2Gross = priceCalcultation.Price2Gross; productShopVm.OldPriceGross = priceCalcultation.OldPriceGross; productShopVm.OldPrice2Gross = priceCalcultation.OldPrice2Gross; productShopVm.Tax = priceCalcultation.TaxRate; } resultListVm.AddRange(productsList); //4. Pins products = await _productService.GetPinProductsAsync(OrderSource.Customer, customer.Address.CountryCode, model.Categories, model.Filter, SelectedLanguage, FallbackLanguage, false); productsList = products.ToList().Select(item => _mapper.Map(item)).ToList(); foreach (var productShopVm in productsList) { //Preise berechnen var priceCalcultation = await _shopCalculationService.CalculatePriceAsync(productShopVm.Id, User.CustomerId().Value, 1); productShopVm.Price = priceCalcultation.Price; productShopVm.Price2 = priceCalcultation.Price2; productShopVm.OldPrice = priceCalcultation.OldPrice; productShopVm.OldPrice2 = priceCalcultation.OldPrice2; productShopVm.PriceGross = priceCalcultation.PriceGross; productShopVm.Price2Gross = priceCalcultation.Price2Gross; productShopVm.OldPriceGross = priceCalcultation.OldPriceGross; productShopVm.OldPrice2Gross = priceCalcultation.OldPrice2Gross; productShopVm.Tax = priceCalcultation.TaxRate; } resultListVm.AddRange(productsList); return PartialView("_GetProducts", resultListVm.OrderBy(c => c.DisplayOrder).ThenBy(c => c.Name).ToList()); } return PartialView("_Error"); } /// /// Gibt eine View für Produkte eines Produkttyps zurück /// /// Typ des Produkts /// PartialView [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] public async Task ShowProducts(ProductType productType) { var customer = await _customerService.GetAsync(User.CustomerId().Value); if(customer != null) { if (productType == ProductType.Listing) { var allowedBranches = customer.BranchesJson; var products = await _productService.GetListingProductsAsync(OrderSource.Customer, customer.Address.CountryCode, allowedBranches, SelectedLanguage, FallbackLanguage, false); var resultListVm = products.ToList().Select(item => _mapper.Map(item)).ToList(); foreach (var productShopVm in resultListVm) { //Preise berechnen var priceCalcultation = await _shopCalculationService.CalculatePriceAsync(productShopVm.Id, User.CustomerId().Value, 1); productShopVm.Price = priceCalcultation.Price; productShopVm.Price2 = priceCalcultation.Price2; productShopVm.OldPrice = priceCalcultation.OldPrice; productShopVm.OldPrice2 = priceCalcultation.OldPrice2; productShopVm.PriceGross = priceCalcultation.PriceGross; productShopVm.Price2Gross = priceCalcultation.Price2Gross; productShopVm.OldPriceGross = priceCalcultation.OldPriceGross; productShopVm.OldPrice2Gross = priceCalcultation.OldPrice2Gross; productShopVm.Tax = priceCalcultation.TaxRate; } return PartialView("_ShowProductsListing", resultListVm); } else if (productType == ProductType.Advertisement) { var products = await _productService.GetAdvertisementProductsAsync(OrderSource.Customer, customer.Address.CountryCode, SelectedLanguage, FallbackLanguage, false); var resultListVm = products.ToList().Select(item => _mapper.Map(item)).ToList(); foreach (var productShopVm in resultListVm) { //Preise berechnen var priceCalcultation = await _shopCalculationService.CalculatePriceAsync(productShopVm.Id, User.CustomerId().Value, 1); productShopVm.Price = priceCalcultation.Price; productShopVm.Price2 = priceCalcultation.Price2; productShopVm.OldPrice = priceCalcultation.OldPrice; productShopVm.OldPrice2 = priceCalcultation.OldPrice2; productShopVm.PriceGross = priceCalcultation.PriceGross; productShopVm.Price2Gross = priceCalcultation.Price2Gross; productShopVm.OldPriceGross = priceCalcultation.OldPriceGross; productShopVm.OldPrice2Gross = priceCalcultation.OldPrice2Gross; productShopVm.Tax = priceCalcultation.TaxRate; } return PartialView("_ShowProductsAdvertisement", resultListVm); } else if (productType == ProductType.Banner) { var products = await _productService.GetBannerProductsAsync(OrderSource.Customer, customer.Address.CountryCode, SelectedLanguage, FallbackLanguage, false); var resultListVm = products.ToList().Select(item => _mapper.Map(item)).ToList(); foreach (var productShopVm in resultListVm) { //Preise berechnen var priceCalcultation = await _shopCalculationService.CalculatePriceAsync(productShopVm.Id, User.CustomerId().Value, 1); productShopVm.Price = priceCalcultation.Price; productShopVm.Price2 = priceCalcultation.Price2; productShopVm.OldPrice = priceCalcultation.OldPrice; productShopVm.OldPrice2 = priceCalcultation.OldPrice2; productShopVm.PriceGross = priceCalcultation.PriceGross; productShopVm.Price2Gross = priceCalcultation.Price2Gross; productShopVm.OldPriceGross = priceCalcultation.OldPriceGross; productShopVm.OldPrice2Gross = priceCalcultation.OldPrice2Gross; productShopVm.Tax = priceCalcultation.TaxRate; } return PartialView("_ShowProductsBanner", resultListVm); } else if (productType == ProductType.Pin) { var products = await _productService.GetPinProductsAsync(OrderSource.Customer, customer.Address.CountryCode, SelectedLanguage, FallbackLanguage, false); var resultListVm = products.ToList().Select(item => _mapper.Map(item)).ToList(); foreach (var productShopVm in resultListVm) { //Preise berechnen var priceCalcultation = await _shopCalculationService.CalculatePriceAsync(productShopVm.Id, User.CustomerId().Value, 1); productShopVm.Price = priceCalcultation.Price; productShopVm.Price2 = priceCalcultation.Price2; productShopVm.OldPrice = priceCalcultation.OldPrice; productShopVm.OldPrice2 = priceCalcultation.OldPrice2; productShopVm.PriceGross = priceCalcultation.PriceGross; productShopVm.Price2Gross = priceCalcultation.Price2Gross; productShopVm.OldPriceGross = priceCalcultation.OldPriceGross; productShopVm.OldPrice2Gross = priceCalcultation.OldPrice2Gross; productShopVm.Tax = priceCalcultation.TaxRate; } return PartialView("_ShowProductsPin", resultListVm); } } return PartialView("_Error"); } /// /// Anzeigen der Details eines Produktes /// /// Id des Produktes /// PartialView [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] public async Task ShowDetails(int productId) { var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null) { var product = await _productService.GetWithNamesCountryAsync(productId, OrderSource.Customer, customer.Address.CountryCode, SelectedLanguage, FallbackLanguage, false); if (product != null) { var productVm = _mapper.Map(product); //Preise berechnen var priceCalcultation = await _shopCalculationService.CalculatePriceAsync(productVm.Id, User.CustomerId().Value, 1); productVm.Price = priceCalcultation.Price; productVm.Price2 = priceCalcultation.Price2; productVm.OldPrice = priceCalcultation.OldPrice; productVm.OldPrice2 = priceCalcultation.OldPrice2; productVm.PriceGross = priceCalcultation.PriceGross; productVm.Price2Gross = priceCalcultation.Price2Gross; productVm.OldPriceGross = priceCalcultation.OldPriceGross; productVm.OldPrice2Gross = priceCalcultation.OldPrice2Gross; productVm.Tax = priceCalcultation.TaxRate; switch (product.ProductType) { case ProductType.Physical: break; case ProductType.Download: break; case ProductType.Listing: return PartialView("_ShowDetailsListing", productVm); case ProductType.Advertisement: return PartialView("_ShowDetailsAdvertisement", productVm); case ProductType.Pin: return PartialView("_ShowDetailsPin", productVm); case ProductType.Banner: return PartialView("_ShowDetailsBanner", productVm); default: throw new ArgumentOutOfRangeException(); } } } return PartialView("_Error"); } #endregion #region Listing /// /// Anzeigen einer View für das Hinzufügen einer Listung zum Warenkorb /// /// Id des Produktes /// Partialview [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] public async Task AddListingToCart(int productId) { var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null) { var product = await _productService.GetWithNamesCountryAsync(productId, OrderSource.Customer, customer.Address.CountryCode, SelectedLanguage, FallbackLanguage, false); if (product != null) { var model = new ListingCartItemCrudVm { CartItemId = -1, CartId = -1, ProductId = product.Id, CustomerId = customer.Id, ProductName = product.Name, ListingType = (ListingTypeVm)product.ListingType, PriceType = (PriceTypeVm)product.PriceType, PriceAliquotType = (PriceAliquotTypeVm)product.PriceAliquotType, ProductStartType = (ProductStartTypeVm)product.ProductStartType, BranchId = product.BranchId, BranchName = product.BranchName, TextVms = new List(), CountryCode = customer.Address.CountryCode, State = customer.Address.State, ListingAddress = _mapper.Map(customer.Address) }; foreach (var language in _languageService.GetAllIso2()) { model.TextVms.Add(new ListingTextVm() { Id = model.CartItemId.ToString(), Language = language, Name = string.Empty, Description = string.Empty, ImageLanguage = string.Empty, Image2Language = string.Empty}); } var country = _countryService.GetCountry(model.CountryCode); model.CountryName = country != null ? country.Name : ""; var state = _countryService.GetState(model.CountryCode, model.State); model.StateName = state != null ? state.Name : ""; var listingCountry = _countryService.GetCountry(model.ListingAddress.CountryCode); model.ListingCountryName = listingCountry != null ? listingCountry.Name : ""; var listingState = _countryService.GetState(model.ListingAddress.CountryCode, model.ListingAddress.State); model.ListingStateName = listingState != null ? listingState.Name : ""; return PartialView("_AddListingToCart", model); } } return PartialView("_Error"); } /// /// Eine Listung zum Warenkorb hinzufügen /// /// Model /// JSON [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [ValidateAntiForgeryToken] [HttpPost] public async Task AddListingToCart(ListingCartItemCrudVm model) { var result = new ResponseVm { Success = false }; var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null && customer.Id == model.CustomerId) { //Prüfen ob eine Listung generell möglich wäre var availableResult = await _listingService.IsAvailableAsync(model.CustomerId, model.BranchId, (ListingType)model.ListingType, model.StartDate.Value, model.EndDate.Value, model.CountryCode, ""); if (availableResult.Valid) { //Prüfen ob exakt diese Listung bereits im Warenkorb ist... var cart = await _cartService.GetOrCreateCustomerAsync(customer.Id, customer.Address.CountryCode, customer.Address.CountryCode, User.Identity.Name); var product = await _productService.GetAsync(model.ProductId); var alreadyInCart = await _listingService.CheckListingInCartAsync(cart.Id, customer.Id, model.BranchId, (ListingType)model.ListingType, model.StartDate.Value, model.EndDate.Value, model.CountryCode, ""); if (!alreadyInCart) { //1. Anlegen Listung als Draft mit Bezug auf den Warenkorb. #region Listing anlegen var listing = _listingService.Create(); listing.CustomerId = customer.Id; listing.BranchId = model.BranchId; listing.ListingType = (ListingType)model.ListingType; listing.StartDate = model.StartDate.Value; listing.EndDate = model.EndDate.Value; listing.Status = ListingStatus.Draft; listing.CartId = cart.Id; listing.PaymentType = PaymentType.None; listing.PaymentStatus = PaymentStatus.None; listing.Url = model.Url; listing.GeoMode = GeoMode.None; listing.Address = new Address() { CountryCode = model.CountryCode, State = model.State }; listing.ListingAddress = _mapper.Map
(model.ListingAddress); listing.Created = DateTimeOffset.UtcNow; listing.UpdatedAt = DateTimeOffset.UtcNow; // Texte setzen foreach (var textVm in model.TextVms) { listing.Set("Name", textVm.Language, textVm.Name); listing.Set("Description", textVm.Language, textVm.Description); listing.Set("ImageLanguage", textVm.Language, textVm.ImageLanguage); listing.Set("Image2Language", textVm.Language, textVm.Image2Language); listing.Set("UrlLanguage", textVm.Language, textVm.UrlLanguage); if (!string.IsNullOrWhiteSpace(textVm.ImageLanguage)) { //Neue Bilddaten verwenden.... var extension = Path.GetExtension(textVm.ImageLanguage); var fileName = Path.GetFileName(textVm.ImageLanguage); var filenameToUse = FileServiceHelper.GetListingPath(listing.Id) + $"ls_{textVm.Language}-{Guid.NewGuid():N}{extension}"; listing.Set("ImageLanguage", textVm.Language, filenameToUse); //Kopieren var tempFile = await FileService.GetAsync(FileServiceHelper.TempContainer, textVm.ImageLanguage); await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile); //Thumbnails await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100); } if (!string.IsNullOrWhiteSpace(textVm.Image2Language)) { //Neue Bilddaten verwenden.... var extension = Path.GetExtension(textVm.Image2Language); var fileName = Path.GetFileName(textVm.Image2Language); var filenameToUse = FileServiceHelper.GetListingPath(listing.Id) + $"ls_{textVm.Language}-{Guid.NewGuid():N}{extension}"; listing.Set("Image2Language", textVm.Language, filenameToUse); //Kopieren var tempFile = await FileService.GetAsync(FileServiceHelper.TempContainer, textVm.Image2Language); await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile); //Thumbnails await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100); } } if (listing.GeoMode != GeoMode.Location) { var location = await _geoLocationService.GetLocationAsync(listing.Address, SelectedLanguage); if (location.Success) { var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326); var geoLocation = geometryFactory.CreatePoint(new Coordinate(location.Longitude, location.Latitude)); listing.Location = geoLocation; } await Task.Delay(1000); } var listingLocation = await _geoLocationService.GetLocationAsync(listing.ListingAddress, SelectedLanguage); if (listingLocation.Success) { var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326); var geoLocation = geometryFactory.CreatePoint(new Coordinate(listingLocation.Longitude, listingLocation.Latitude)); listing.ListingLocation = geoLocation; } _listingService.Add(listing); await _listingService.CommitAsync(User.Identity.Name); if (!string.IsNullOrWhiteSpace(model.Image)) { //Nun das Bild umbenennen und dann kopieren. Ebenso Thumbnails erstellen var extension = Path.GetExtension(model.Image); var fileName = Path.GetFileName(model.Image); var filenameToUse = FileServiceHelper.GetListingPath(listing.Id) + $"ls_{Guid.NewGuid():N}{extension}"; listing.Image = filenameToUse; await _listingService.CommitAsync(User.Identity.Name); //Kopieren var tempFile = await FileService.GetAsync(FileServiceHelper.TempContainer, model.Image); await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile); //Thumbnails await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100); //Altes Löschen await FileService.DeleteAsync(FileServiceHelper.TempContainer, model.Image); } if (!string.IsNullOrWhiteSpace(model.Image2)) { //Nun das Bild umbenennen und dann kopieren. Ebenso Thumbnails erstellen var extension = Path.GetExtension(model.Image2); var fileName = Path.GetFileName(model.Image2); var filenameToUse = FileServiceHelper.GetListingPath(listing.Id) + $"ls_{Guid.NewGuid():N}{extension}"; listing.Image2 = filenameToUse; await _listingService.CommitAsync(User.Identity.Name); //Kopieren var tempFile = await FileService.GetAsync(FileServiceHelper.TempContainer, model.Image2); await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile); //Thumbnails await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100); //Altes Löschen await FileService.DeleteAsync(FileServiceHelper.TempContainer, model.Image); } #endregion //2. Preis berechnen - hier aliquot var priceCalculation = await _shopCalculationService.CalculatePriceAsync(product.Id, customer.Id, product.PriceType, product.PriceAliquotType, listing.StartDate.Value, listing.EndDate.Value, 1); //3. Anlegen des Items im Warenkorb #region CartItem anlegen var cartItem = _cartService.CreateItem(); cartItem.CartId = cart.Id; cartItem.ProductId = product.Id; cartItem.ProductType = ProductType.Listing; cartItem.ItemId = listing.Id; cartItem.Quantity = 1; cartItem.Price = priceCalculation.Price; cartItem.PriceGross = priceCalculation.PriceGross; cartItem.Price2 = priceCalculation.Price2; cartItem.Price2Gross = priceCalculation.Price2Gross; cartItem.Total = priceCalculation.Total; cartItem.TotalGross = priceCalculation.TotalGross; cartItem.TaxRate = priceCalculation.TaxRate; cartItem.TaxRateValue = priceCalculation.TaxValue; cartItem.Created = DateTimeOffset.UtcNow; cartItem.LastUpdate = DateTimeOffset.UtcNow; _cartService.AddItem(cartItem); await _cartService.CommitAsync(User.Identity.Name); #endregion //3. CartItemId bei Listing nachsetzen listing.CartItemId = cartItem.Id; await _listingService.CommitAsync(User.Identity.Name); await _cartService.CalculateAsync(cart.Id, OrderSource.Customer, customer.Address.CountryCode, User.Identity.Name); var cartWithName = await _cartService.GetByCustomerWithNamesAsync(customer.Id, SelectedLanguage, FallbackLanguage); await _systemHubSender.CartChangedAsync(customer.UniqueId.Value, cartWithName.ItemCount); result.Success = true; result.Html = string.Empty; return Json(new { result.Success, result.Html, result.Data }); } else { result.ErrorMessage = _localizer["Err_Listing_AlreadyInCart"].Value; } } else { if (availableResult.ErrorCode == ListingValidationError.AlreadyBooked) result.ErrorMessage = _localizer["Err_Listing_AlreadyBooked"].Value; else result.ErrorMessage = String.Format(_localizer["Err_Listing_NotAvailable"].Value, availableResult.Booked, availableResult.Reserved); } } ModelState.Remove("CountryName"); var country = _countryService.GetCountry(model.CountryCode); model.CountryName = country != null ? country.Name : ""; ModelState.Remove("StateName"); var state = _countryService.GetState(model.CountryCode, model.State); model.StateName = state != null ? state.Name : ""; result.Html = await PartialView("_AddListingToCart", model).ToStringAsync(ControllerContext); return Json(result); } #endregion #region Werbung - Advertisement /// /// Anzeigen einer View für das Hinzufügen einer Werbung zum Warenkorb /// /// Id des Produktes /// Partialview [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] public async Task AddAdvertisementToCart(int productId) { var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null) { var product = await _productService.GetWithNamesCountryAsync(productId, OrderSource.Customer, customer.Address.CountryCode, SelectedLanguage, FallbackLanguage, false); if (product != null) { var model = new AdvertisementCartItemCrudVm { CartItemId = -1, CartId = -1, ProductId = product.Id, CustomerId = customer.Id, ProductName = product.Name, PriceType = (PriceTypeVm)product.PriceType, PriceAliquotType = (PriceAliquotTypeVm)product.PriceAliquotType, ProductStartType = (ProductStartTypeVm)product.ProductStartType, AdvertisementCategoryId = product.AdvertisementCategoryId, AdvertisementCategoryName = product.AdvertisementCategoryName, TextVms = new List(), CountryCode = customer.Address.CountryCode, State = customer.Address.State, Discount = 0 }; foreach (var language in _languageService.GetAllIso2()) { model.TextVms.Add(new AdvertisementTextVm() { Id = model.CartItemId.ToString(), Language = language, Name = string.Empty, Description = string.Empty, ImageLanguage = string.Empty, Image2Language = String.Empty}); } var country = _countryService.GetCountry(model.CountryCode); model.CountryName = country != null ? country.Name : ""; var state = _countryService.GetState(model.CountryCode, model.State); model.StateName = state != null ? state.Name : ""; return PartialView("_AddAdvertisementToCart", model); } } return PartialView("_Error"); } /// /// Eine Werbung zum Warenkorb hinzufügen /// /// Model /// JSON [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [ValidateAntiForgeryToken] [HttpPost] public async Task AddAdvertisementToCart(AdvertisementCartItemCrudVm model) { var result = new ResponseVm { Success = false }; var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null && customer.Id == model.CustomerId) { //Prüfen ob exakt diese Listung bereits im Warenkorb ist... var cart = await _cartService.GetOrCreateCustomerAsync(customer.Id, customer.Address.CountryCode, customer.Address.CountryCode, User.Identity.Name); var product = await _productService.GetAsync(model.ProductId); //1. Anlegen Werbung als Draft mit Bezug auf den Warenkorb. #region Werbung anlegen var advertisement = _advertisementService.Create(); advertisement.CustomerId = customer.Id; advertisement.AdvertisementCategoryId = model.AdvertisementCategoryId; advertisement.Discount = model.Discount; advertisement.StartDate = model.StartDate.Value; advertisement.EndDate = model.EndDate.Value; advertisement.Status = AdvertisementStatus.Draft; advertisement.CartId = cart.Id; advertisement.PaymentType = PaymentType.None; advertisement.PaymentStatus = PaymentStatus.None; advertisement.Url = model.Url; advertisement.GeoMode = GeoMode.None; advertisement.Address = new Address() { CountryCode = model.CountryCode, State = model.State }; advertisement.Created = DateTimeOffset.UtcNow; advertisement.UpdatedAt = DateTimeOffset.UtcNow; // Texte setzen foreach (var textVm in model.TextVms) { advertisement.Set("Name", textVm.Language, textVm.Name); advertisement.Set("Description", textVm.Language, textVm.Description); advertisement.Set("ImageLanguage", textVm.Language, textVm.ImageLanguage); advertisement.Set("Image2Language", textVm.Language, textVm.Image2Language); advertisement.Set("UrlLanguage", textVm.Language, textVm.UrlLanguage); if (!string.IsNullOrWhiteSpace(textVm.ImageLanguage)) { //Neue Bilddaten verwenden.... var extension = Path.GetExtension(textVm.ImageLanguage); var fileName = Path.GetFileName(textVm.ImageLanguage); var filenameToUse = FileServiceHelper.GetAdvertisementPath(advertisement.Id) + $"ad_{textVm.Language}-{Guid.NewGuid():N}{extension}"; advertisement.Set("ImageLanguage", textVm.Language, filenameToUse); //Kopieren var tempFile = await FileService.GetAsync(FileServiceHelper.TempContainer, textVm.ImageLanguage); await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile); //Thumbnails await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100); } if (!string.IsNullOrWhiteSpace(textVm.Image2Language)) { //Neue Bilddaten verwenden.... var extension = Path.GetExtension(textVm.Image2Language); var fileName = Path.GetFileName(textVm.Image2Language); var filenameToUse = FileServiceHelper.GetAdvertisementPath(advertisement.Id) + $"ad_{textVm.Language}-{Guid.NewGuid():N}{extension}"; advertisement.Set("Image2Language", textVm.Language, filenameToUse); //Kopieren var tempFile = await FileService.GetAsync(FileServiceHelper.TempContainer, textVm.Image2Language); await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile); //Thumbnails await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100); } } _advertisementService.Add(advertisement); await _advertisementService.CommitAsync(User.Identity.Name); if (!string.IsNullOrWhiteSpace(model.Image)) { //Nun das Bild umbenennen und dann kopieren. Ebenso Thumbnails erstellen var extension = Path.GetExtension(model.Image); var fileName = Path.GetFileName(model.Image); var filenameToUse = FileServiceHelper.GetAdvertisementPath(advertisement.Id) + $"ad_{Guid.NewGuid():N}{extension}"; advertisement.Image = filenameToUse; await _listingService.CommitAsync(User.Identity.Name); //Kopieren var tempFile = await FileService.GetAsync(FileServiceHelper.TempContainer, model.Image); await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile); //Thumbnails await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100); //Altes Löschen await FileService.DeleteAsync(FileServiceHelper.TempContainer, model.Image); } if (!string.IsNullOrWhiteSpace(model.Image2)) { //Nun das Bild umbenennen und dann kopieren. Ebenso Thumbnails erstellen var extension = Path.GetExtension(model.Image2); var fileName = Path.GetFileName(model.Image2); var filenameToUse = FileServiceHelper.GetAdvertisementPath(advertisement.Id) + $"ad_{Guid.NewGuid():N}{extension}"; advertisement.Image2 = filenameToUse; await _listingService.CommitAsync(User.Identity.Name); //Kopieren var tempFile = await FileService.GetAsync(FileServiceHelper.TempContainer, model.Image2); await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile); //Thumbnails await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100); //Altes Löschen await FileService.DeleteAsync(FileServiceHelper.TempContainer, model.Image2); } #endregion //2. Preis berechnen - hier aliquot var priceCalculation = await _shopCalculationService.CalculatePriceAsync(product.Id, customer.Id, product.PriceType, product.PriceAliquotType, advertisement.StartDate.Value, advertisement.EndDate.Value, 1); //3. Anlegen des Items im Warenkorb #region CartItem anlegen var cartItem = _cartService.CreateItem(); cartItem.CartId = cart.Id; cartItem.ProductId = product.Id; cartItem.ProductType = ProductType.Advertisement; cartItem.ItemId = advertisement.Id; cartItem.Quantity = 1; cartItem.Price = priceCalculation.Price; cartItem.PriceGross = priceCalculation.PriceGross; cartItem.Price2 = priceCalculation.Price2; cartItem.Price2Gross = priceCalculation.Price2Gross; cartItem.Total = priceCalculation.Total; cartItem.TotalGross = priceCalculation.TotalGross; cartItem.TaxRate = priceCalculation.TaxRate; cartItem.TaxRateValue = priceCalculation.TaxValue; cartItem.Created = DateTimeOffset.UtcNow; cartItem.LastUpdate = DateTimeOffset.UtcNow; _cartService.AddItem(cartItem); await _cartService.CommitAsync(User.Identity.Name); #endregion //3. CartItemId bei Listing nachsetzen advertisement.CartItemId = cartItem.Id; await _advertisementService.CommitAsync(User.Identity.Name); await _cartService.CalculateAsync(cart.Id, OrderSource.Customer, customer.Address.CountryCode, User.Identity.Name); var cartWithName = await _cartService.GetByCustomerWithNamesAsync(customer.Id, SelectedLanguage, FallbackLanguage); await _systemHubSender.CartChangedAsync(customer.UniqueId.Value, cartWithName.ItemCount); result.Success = true; result.Html = string.Empty; return Json(new { result.Success, result.Html, result.Data }); } ModelState.Remove("CountryName"); var country = _countryService.GetCountry(model.CountryCode); model.CountryName = country != null ? country.Name : ""; ModelState.Remove("StateName"); var state = _countryService.GetState(model.CountryCode, model.State); model.StateName = state != null ? state.Name : ""; result.Html = await PartialView("_AddAdvertisementToCart", model).ToStringAsync(ControllerContext); return Json(result); } #endregion #region Banner /// /// Anzeigen einer View für das Hinzufügen eines Banner zum Warenkorb /// /// Id des Produktes /// Partialview [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] public async Task AddBannerToCart(int productId) { var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null) { var product = await _productService.GetWithNamesCountryAsync(productId, OrderSource.Customer, customer.Address.CountryCode, SelectedLanguage, FallbackLanguage, false); if (product != null) { //Preise berechnen var priceCalcultation = await _shopCalculationService.CalculatePriceAsync(product.Id, User.CustomerId().Value, 1); var model = new BannerCartItemCrudVm { CartItemId = -1, CartId = -1, ProductId = product.Id, CustomerId = customer.Id, ProductName = product.Name, PriceType = (PriceTypeVm)product.PriceType, PriceAliquotType = (PriceAliquotTypeVm)product.PriceAliquotType, ProductStartType = (ProductStartTypeVm)product.ProductStartType, Budget = 1M, BannerSize = (BannerSizeVm)product.BannerSize, BannerLocation = (BannerLocationVm)product.BannerLocation, TextVms = new List(), CountryCode = customer.Address.CountryCode, State = customer.Address.State, Price = priceCalcultation.Price, PriceGross = priceCalcultation.PriceGross, Price2 = priceCalcultation.Price2, Price2Gross = priceCalcultation.Price2Gross, Tax = priceCalcultation.TaxRate }; foreach (var language in _languageService.GetAllIso2()) { model.TextVms.Add(new BannerTextVm() { Id = model.CartItemId.ToString(), Language = language, Name = string.Empty, ImageLanguage = string.Empty }); } var country = _countryService.GetCountry(model.CountryCode); model.CountryName = country != null ? country.Name : ""; var state = _countryService.GetState(model.CountryCode, model.State); model.StateName = state != null ? state.Name : ""; return PartialView("_AddBannerToCart", model); } } return PartialView("_Error"); } /// /// Einen Banner zum Warenkorb hinzufügen /// /// Model /// JSON [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [ValidateAntiForgeryToken] [HttpPost] public async Task AddBannerToCart(BannerCartItemCrudVm model) { var result = new ResponseVm { Success = false }; var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null && customer.Id == model.CustomerId) { //Prüfen ob exakt diese Listung bereits im Warenkorb ist... var cart = await _cartService.GetOrCreateCustomerAsync(customer.Id, customer.Address.CountryCode, customer.Address.CountryCode, User.Identity.Name); var product = await _productService.GetAsync(model.ProductId); //1. Anlegen Werbung als Draft mit Bezug auf den Warenkorb. #region Banner anlegen var clickPrices = await _shopCalculationService.CalculatePriceAsync(product.Id, customer.Id, 1); var banner = _bannerService.Create(); banner.CustomerId = customer.Id; banner.BannerLocation = product.BannerLocation; banner.BannerSize = product.BannerSize; banner.CurrentViews = 0; banner.CurrentClicks = 0; banner.BudgetUsed = 0m; banner.Budget = model.Budget; banner.PriceView = clickPrices.PriceGross; banner.PriceClick = clickPrices.Price2Gross; banner.StartDate = model.StartDate.Value; banner.EndDate = null; banner.Status = BannerStatus.Draft; banner.CartId = cart.Id; banner.PaymentType = PaymentType.None; banner.PaymentStatus = PaymentStatus.None; banner.Url = model.Url; banner.GeoMode = GeoMode.None; banner.Address = new Address() { CountryCode = model.CountryCode, State = model.State }; banner.Created = DateTimeOffset.UtcNow; banner.UpdatedAt = DateTimeOffset.UtcNow; // Texte setzen foreach (var textVm in model.TextVms) { banner.Set("Name", textVm.Language, textVm.Name); banner.Set("ImageLanguage", textVm.Language, textVm.ImageLanguage); banner.Set("UrlLanguage", textVm.Language, textVm.UrlLanguage); if (!string.IsNullOrWhiteSpace(textVm.ImageLanguage)) { //Neue Bilddaten verwenden.... var extension = Path.GetExtension(textVm.ImageLanguage); var fileName = Path.GetFileName(textVm.ImageLanguage); var filenameToUse = FileServiceHelper.GetBannerPath(banner.Id) + $"bn_{textVm.Language}-{Guid.NewGuid():N}{extension}"; banner.Set("ImageLanguage", textVm.Language, filenameToUse); //Kopieren var tempFile = await FileService.GetAsync(FileServiceHelper.TempContainer, textVm.ImageLanguage); await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile); //Thumbnails switch (banner.BannerSize) { //Thumbnails case BannerSize.Standard or BannerSize.Large: await GenerateBannerThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 320); break; case BannerSize.MediumRectangular: await GenerateBannerThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 300); break; } } } _bannerService.Add(banner); await _bannerService.CommitAsync(User.Identity.Name); if (!string.IsNullOrWhiteSpace(model.Image)) { //Nun das Bild umbenennen und dann kopieren. Ebenso Thumbnails erstellen var extension = Path.GetExtension(model.Image); var fileName = Path.GetFileName(model.Image); var filenameToUse = FileServiceHelper.GetBannerPath(banner.Id) + $"bn_{Guid.NewGuid():N}{extension}"; banner.Image = filenameToUse; await _bannerService.CommitAsync(User.Identity.Name); //Kopieren var tempFile = await FileService.GetAsync(FileServiceHelper.TempContainer, model.Image); await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile); //Thumbnails switch (banner.BannerSize) { //Thumbnails case BannerSize.Standard or BannerSize.Large: await GenerateBannerThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 320); break; case BannerSize.MediumRectangular: await GenerateBannerThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 300); break; } //Altes Löschen await FileService.DeleteAsync(FileServiceHelper.TempContainer, model.Image); } #endregion //2. Preis berechnen - hier aliquot var priceCalculation = await _shopCalculationService.CalculatePriceBannerAsync(product.Id, customer.Id, cart.BillingCountryCode, 1, model.Budget); //3. Anlegen des Items im Warenkorb #region CartItem anlegen var cartItem = _cartService.CreateItem(); cartItem.CartId = cart.Id; cartItem.ProductId = product.Id; cartItem.ProductType = ProductType.Banner; cartItem.ItemId = banner.Id; cartItem.Quantity = 1; cartItem.Price = priceCalculation.Price; cartItem.PriceGross = priceCalculation.PriceGross; cartItem.Price2 = priceCalculation.Price2; cartItem.Price2Gross = priceCalculation.Price2Gross; cartItem.Total = priceCalculation.Total; cartItem.TotalGross = priceCalculation.TotalGross; cartItem.TaxRate = priceCalculation.TaxRate; cartItem.TaxRateValue = priceCalculation.TaxValue; cartItem.Created = DateTimeOffset.UtcNow; cartItem.LastUpdate = DateTimeOffset.UtcNow; _cartService.AddItem(cartItem); await _cartService.CommitAsync(User.Identity.Name); #endregion //3. CartItemId bei Listing nachsetzen banner.CartItemId = cartItem.Id; await _bannerService.CommitAsync(User.Identity.Name); await _cartService.CalculateAsync(cart.Id, OrderSource.Customer, customer.Address.CountryCode, User.Identity.Name); var cartWithName = await _cartService.GetByCustomerWithNamesAsync(customer.Id, SelectedLanguage, FallbackLanguage); await _systemHubSender.CartChangedAsync(customer.UniqueId.Value, cartWithName.ItemCount); result.Success = true; result.Html = string.Empty; return Json(new { result.Success, result.Html, result.Data }); } ModelState.Remove("CountryName"); var country = _countryService.GetCountry(model.CountryCode); model.CountryName = country != null ? country.Name : ""; ModelState.Remove("StateName"); var state = _countryService.GetState(model.CountryCode, model.State); model.StateName = state != null ? state.Name : ""; result.Html = await PartialView("_AddBannerToCart", model).ToStringAsync(ControllerContext); return Json(result); } #endregion #region Pin /// /// Anzeigen einer View für das Hinzufügen eines Pins zum Warenkorb /// /// Id des Produktes /// Partialview [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] public async Task AddPinToCart(int productId) { var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null) { var product = await _productService.GetWithNamesCountryAsync(productId, OrderSource.Customer, customer.Address.CountryCode, SelectedLanguage, FallbackLanguage, false); if (product != null) { var geoResult = await _geoLocationService.GetLocationAsync(customer.Address, SelectedLanguage); var model = new PinCartItemCrudVm { CartItemId = -1, CartId = -1, ProductId = product.Id, CustomerId = customer.Id, ProductName = product.Name, PriceType = (PriceTypeVm)product.PriceType, PriceAliquotType = (PriceAliquotTypeVm)product.PriceAliquotType, ProductStartType = (ProductStartTypeVm)product.ProductStartType, Lat = 0, Lng = 0, Radius = product.PinRadius, PinRadius = product.PinRadius, PinPercentPerKm = product.PinPercentPerKm, TextVms = new List() }; if (geoResult.Success) { model.Lat = geoResult.Latitude; model.Lng = geoResult.Longitude; } foreach (var language in _languageService.GetAllIso2()) { model.TextVms.Add(new PinTextVm() { Id = model.CartItemId.ToString(), Language = language, Name = string.Empty, Description = string.Empty, ImageLanguage = string.Empty }); } return PartialView("_AddPinToCart", model); } } return PartialView("_Error"); } /// /// Einen Pin zum Warenkorb hinzufügen /// /// Model /// JSON [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [ValidateAntiForgeryToken] [HttpPost] public async Task AddPinToCart(PinCartItemCrudVm model) { var result = new ResponseVm { Success = false }; var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null && customer.Id == model.CustomerId) { var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326); //Prüfen ob exakt diese Listung bereits im Warenkorb ist... var cart = await _cartService.GetOrCreateCustomerAsync(customer.Id, customer.Address.CountryCode, customer.Address.CountryCode, User.Identity.Name); var product = await _productService.GetAsync(model.ProductId); //1. Anlegen Listung als Draft mit Bezug auf den Warenkorb. #region Listing anlegen var pin = _pinService.Create(); pin.CustomerId = customer.Id; pin.StartDate = model.StartDate.Value; pin.EndDate = model.EndDate.Value; pin.Status = PinStatus.Draft; pin.Radius = model.Radius; pin.Location = geometryFactory.CreatePoint(new Coordinate(model.Lng, model.Lat)); pin.CartId = cart.Id; pin.PaymentType = PaymentType.None; pin.PaymentStatus = PaymentStatus.None; pin.Url = model.Url; pin.Created = DateTimeOffset.UtcNow; pin.UpdatedAt = DateTimeOffset.UtcNow; // Texte setzen foreach (var textVm in model.TextVms) { pin.Set("Name", textVm.Language, textVm.Name); pin.Set("Description", textVm.Language, textVm.Description); pin.Set("ImageLanguage", textVm.Language, textVm.ImageLanguage); pin.Set("UrlLanguage", textVm.Language, textVm.UrlLanguage); if (!string.IsNullOrWhiteSpace(textVm.ImageLanguage)) { //Neue Bilddaten verwenden.... var extension = Path.GetExtension(textVm.ImageLanguage); var fileName = Path.GetFileName(textVm.ImageLanguage); var filenameToUse = FileServiceHelper.GetPinPath(pin.Id) + $"pin_{textVm.Language}-{Guid.NewGuid():N}{extension}"; pin.Set("ImageLanguage", textVm.Language, filenameToUse); //Kopieren var tempFile = await FileService.GetAsync(FileServiceHelper.TempContainer, textVm.ImageLanguage); await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile); //Thumbnails await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100); } } _pinService.Add(pin); await _pinService.CommitAsync(User.Identity.Name); if (!string.IsNullOrWhiteSpace(model.Image)) { //Nun das Bild umbenennen und dann kopieren. Ebenso Thumbnails erstellen var extension = Path.GetExtension(model.Image); var fileName = Path.GetFileName(model.Image); var filenameToUse = FileServiceHelper.GetPinPath(pin.Id) + $"pin_{Guid.NewGuid():N}{extension}"; pin.Image = filenameToUse; await _listingService.CommitAsync(User.Identity.Name); //Kopieren var tempFile = await FileService.GetAsync(FileServiceHelper.TempContainer, model.Image); await FileService.StoreAsync(FileServiceHelper.DocumentContainer, filenameToUse, tempFile); //Thumbnails await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 400); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 200); await GenerateThumbnailByWidth(FileServiceHelper.DocumentContainer, filenameToUse, 100); //Altes Löschen await FileService.DeleteAsync(FileServiceHelper.TempContainer, model.Image); } #endregion //2. Preis berechnen - hier aliquot var priceCalculation = await _shopCalculationService.CalculatePriceAsync(product.Id, customer.Id, product.PriceType, product.PriceAliquotType, pin.StartDate.Value, pin.EndDate.Value, 1); //2.1 einen Aufschlag hinzufügen wenn mehr KM als enthalten angegeben wurde.... if (pin.Radius > product.PinRadius && product.PinPercentPerKm > 0) { var diff = (decimal)(pin.Radius - product.PinRadius); var markup = product.PinPercentPerKm * diff; priceCalculation = await _shopCalculationService.AddMarkupAsync(priceCalculation, markup, product.Id, cart.BillingCountryCode); } //3. Anlegen des Items im Warenkorb #region CartItem anlegen var cartItem = _cartService.CreateItem(); cartItem.CartId = cart.Id; cartItem.ProductId = product.Id; cartItem.ProductType = ProductType.Pin; cartItem.ItemId = pin.Id; cartItem.Quantity = 1; cartItem.Price = priceCalculation.Price; cartItem.PriceGross = priceCalculation.PriceGross; cartItem.Price2 = priceCalculation.Price2; cartItem.Price2Gross = priceCalculation.Price2Gross; cartItem.Total = priceCalculation.Total; cartItem.TotalGross = priceCalculation.TotalGross; cartItem.TaxRate = priceCalculation.TaxRate; cartItem.TaxRateValue = priceCalculation.TaxValue; cartItem.Created = DateTimeOffset.UtcNow; cartItem.LastUpdate = DateTimeOffset.UtcNow; _cartService.AddItem(cartItem); await _cartService.CommitAsync(User.Identity.Name); #endregion //3. CartItemId bei Listing nachsetzen pin.CartItemId = cartItem.Id; await _pinService.CommitAsync(User.Identity.Name); await _cartService.CalculateAsync(cart.Id, OrderSource.Customer, customer.Address.CountryCode, User.Identity.Name); var cartWithName = await _cartService.GetByCustomerWithNamesAsync(customer.Id, SelectedLanguage, FallbackLanguage); await _systemHubSender.CartChangedAsync(customer.UniqueId.Value, cartWithName.ItemCount); result.Success = true; result.Html = string.Empty; return Json(new { result.Success, result.Html, result.Data }); } result.Html = await PartialView("_AddPinToCart", model).ToStringAsync(ControllerContext); return Json(result); } #endregion #region Cart /// /// Suchen des Warenkorbs des angemeldeten Kunden. /// Wenn keiner existiert, wird einer angelegt /// /// JSON [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public async Task GetOrCreateCart() { var result = new ResponseVm { Success = false, Data = "0", ErrorMessage = string.Empty, Html = string.Empty }; var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null) { var cart = await _cartService.GetOrCreateCustomerAsync(customer.Id, customer.Address.CountryCode, customer.Address.CountryCode, User.Identity.Name); var cartWithNames = await _cartService.GetByCustomerWithNamesAsync(customer.Id, SelectedLanguage, FallbackLanguage); result.Success = true; result.Data = $"{cartWithNames.ItemCount}"; } return Json(result); } /// /// Entfernen eines Artikels aus einem Warenkorb /// /// Id des Artikels im Warenkorb /// JSON [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [HttpPost] public async Task RemoveItemFromCart(long cartItemId) { var result = new ResponseVm { Success = false }; var customer = await _customerService.GetAsync(User.CustomerId().Value); var cartItem = await _cartService.GetItemAsync(cartItemId); if (customer != null && cartItem != null) { var cart = await _cartService.GetAsync(cartItem.CartId); if (cart != null && cart.CustomerId == customer.Id) { await RemoveCartItemAsync(cartItem); await _cartService.CommitAsync(User.Identity.Name); //Warenkorb neu berechnen await _cartService.CalculateAsync(cart.Id, cart.OrderSource, customer.Address.CountryCode, User.Identity.Name); var cartWithName = await _cartService.GetByCustomerWithNamesAsync(customer.Id, SelectedLanguage, FallbackLanguage); await _systemHubSender.CartChangedAsync(customer.UniqueId.Value, cartWithName.ItemCount); result.Success = true; result.Html = string.Empty; return Json(new { result.Success, result.Html, result.Data }); } } return Json(result); } /// /// Leeren des Warenkorbes eines Kunden /// /// UniqueId des Kunden /// JSON [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [CustomerAuthorize("customerUniqueId")] [HttpPost] public async Task ClearCart(Guid customerUniqueId) { var result = new ResponseVm { Success = false }; var customer = await _customerService.GetByUniqueIdAsync(customerUniqueId); if (customer != null && customer.Id == User.CustomerId().Value) { var cart = await _cartService.GetOrCreateCustomerAsync(customer.Id, customer.Address.CountryCode, customer.Address.CountryCode, User.Identity.Name); await _cartService.ClearAsync(cart.Id, true, User.Identity.Name); //Warenkorb neu berechnen await _cartService.CalculateAsync(cart.Id, cart.OrderSource, customer.Address.CountryCode, User.Identity.Name); var cartWithName = await _cartService.GetByCustomerWithNamesAsync(customer.Id, SelectedLanguage, FallbackLanguage); await _systemHubSender.CartChangedAsync(customer.UniqueId.Value, cartWithName.ItemCount); result.Success = true; result.Html = string.Empty; return Json(new { result.Success, result.Html, result.Data }); } return Json(result); } /// /// Anzeigen des Warenkorbs /// /// Direktes Anzeigen der Bestätigung /// [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public async Task ShowCart(bool showConfirmation = false) { var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null) { ViewBag.ShowConfirmation = showConfirmation; return View(customer.UniqueId.Value); } return RedirectToAction("Error", "Home"); } /// /// Anzeige Warenkorb Übersicht /// /// Partialview [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [CustomerAuthorize("customerUniqueId")] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public async Task CartOverview(Guid customerUniqueId) { var customer = await _customerService.GetByUniqueIdAsync(customerUniqueId); if (customer != null && customer.Id == User.CustomerId()) { var cart = await _cartService.GetOrCreateCustomerAsync(customer.Id, customer.Address.CountryCode, customer.Address.CountryCode, User.Identity.Name); var checkoutAddress = HttpContext.Session.Get(ShopSessionConstants.CheckoutAddress); if (checkoutAddress == null) { cart.BillingCountryCode = customer.Address.CountryCode; cart.DeliveryCountryCode = customer.Address.CountryCode; await ValidateCartAsync(cart.Id); await RecalculateCartAsync(cart.Id); } var cartWithNames = await _cartService.GetByCustomerWithNamesAsync(customer.Id, SelectedLanguage, FallbackLanguage); var cartItemsWithNames = await _cartService.GetItemsWithNamesAsync(cart.Id, SelectedLanguage, FallbackLanguage); var model = _mapper.Map(cartWithNames); model.BillingCountryName = _countryService.GetCountry(model.BillingCountryCode).Name; model.DeliveryCountryName = _countryService.GetCountry(model.DeliveryCountryCode).Name; model.CartItems = new List(); if (cartItemsWithNames.Any()) { model.CartItems = _mapper.Map>(cartItemsWithNames); } foreach (var cartItemListVm in model.CartItems) { if (cartItemListVm.ProductType == ProductTypeVm.Listing) { var listing = await _listingService.GetByCartItemAsync(cartItemListVm.Id); if (listing != null) { var country = _countryService.GetCountry(listing.Address.CountryCode); cartItemListVm.ProductSpecialInfo = $"{country.Name} | {listing.StartDate.Value.Date.ToShortDateString()} - {listing.EndDate.Value.Date.ToShortDateString()}"; } } else if (cartItemListVm.ProductType == ProductTypeVm.Advertisement) { var advertisement = await _advertisementService.GetByCartItemAsync(cartItemListVm.Id); if (advertisement != null) { var country = _countryService.GetCountry(advertisement.Address.CountryCode); cartItemListVm.ProductSpecialInfo = $"{country.Name} | {advertisement.StartDate.Value.Date.ToShortDateString()} - {advertisement.EndDate.Value.Date.ToShortDateString()}"; } } else if (cartItemListVm.ProductType == ProductTypeVm.Banner) { var banner = await _bannerService.GetByCartItemAsync(cartItemListVm.Id); if (banner != null) { var country = _countryService.GetCountry(banner.Address.CountryCode); cartItemListVm.ProductSpecialInfo = $"{country.Name} | {banner.StartDate.Value.Date.ToShortDateString()}"; } } else if (cartItemListVm.ProductType == ProductTypeVm.Pin) { var pin = await _pinService.GetByCartItemAsync(cartItemListVm.Id); if (pin != null) { cartItemListVm.ProductSpecialInfo = $"Lat: {pin.Location.Y.ToString("N6")} Lng: {pin.Location.X.ToString("N6")} Rad: {pin.Radius.ToString("N2")}km | {pin.StartDate.Value.Date.ToShortDateString()} - {pin.EndDate.Value.Date.ToShortDateString()}"; } } } return PartialView("_CartOverview", model); } return PartialView("_Error"); } #endregion #region Checkout /// /// Anzeige der Adresse /// /// /// [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [CustomerAuthorize("customerUniqueId")] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public async Task CheckoutAddress(Guid customerUniqueId) { var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null && customer.Id == User.CustomerId()) { var cart = await _cartService.GetOrCreateCustomerAsync(customer.Id, customer.Address.CountryCode, customer.Address.CountryCode, User.Identity.Name); if (cart != null) { var cartWithNames = await _cartService.GetByCustomerWithNamesAsync(customer.Id, SelectedLanguage, FallbackLanguage); if (cartWithNames.ItemCount > 0) { var checkoutAddress = HttpContext.Session.Get(ShopSessionConstants.CheckoutAddress); if (checkoutAddress == null) { checkoutAddress = _mapper.Map(customer); checkoutAddress.OrderSource = OrderSourceVm.Customer; checkoutAddress.DeliveryAddressIsBilling = true; checkoutAddress.DeliveryAddress.DeliveryAddressIsBilling = checkoutAddress.DeliveryAddressIsBilling; checkoutAddress.DeliveryAddress.CountryCode = checkoutAddress.BillingAddress.CountryCode; checkoutAddress.DeliveryAddress.State = checkoutAddress.BillingAddress.State; checkoutAddress.ShowForm = false; HttpContext.Session.Set(ShopSessionConstants.CheckoutAddress, checkoutAddress); } checkoutAddress.BillingCountryName = _countryService.GetCountry(checkoutAddress.BillingAddress.CountryCode).Name; checkoutAddress.BillingStateName = _countryService.GetState(checkoutAddress.BillingAddress.CountryCode, checkoutAddress.BillingAddress.State).Name; checkoutAddress.DeliveryCountryName = _countryService.GetCountry(checkoutAddress.DeliveryAddress.CountryCode).Name; checkoutAddress.DeliveryStateName = _countryService.GetState(checkoutAddress.DeliveryAddress.CountryCode, checkoutAddress.DeliveryAddress.State).Name; return PartialView("_CheckoutAddress", checkoutAddress); } } } return PartialView("_Error"); } /// /// Ändern der Bestell-Adressen /// /// Model /// JSON [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [ValidateAntiForgeryToken] [HttpPost] public async Task CheckoutAddress(CheckoutAddressVm model) { var result = new ResponseVm { Success = false }; if (ModelState.IsValid) { var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null && customer.Id == User.CustomerId()) { var checkoutAddress = HttpContext.Session.Get(ShopSessionConstants.CheckoutAddress); if (checkoutAddress != null) { checkoutAddress = model; HttpContext.Session.Set(ShopSessionConstants.CheckoutAddress, checkoutAddress); result.Data = string.Empty; var cart = await _cartService.GetOrCreateCustomerAsync(customer.Id, customer.Address.CountryCode, customer.Address.CountryCode, User.Identity.Name); var billingCountryCode = checkoutAddress.BillingAddress.CountryCode; var deliveryCountryCode = checkoutAddress.BillingAddress.CountryCode; if (checkoutAddress.DeliveryAddressIsBilling == false) deliveryCountryCode = checkoutAddress.DeliveryAddress.CountryCode; if (cart.BillingCountryCode != billingCountryCode || cart.DeliveryCountryCode != deliveryCountryCode) { cart.BillingCountryCode = billingCountryCode; cart.DeliveryCountryCode = deliveryCountryCode; await _cartService.CommitAsync(User.Identity.Name); //1. prüfen ob Produkte raus müssen... var validationResult = await ValidateCartAsync(cart.Id); //2. neu berechnen var calculationResult = await RecalculateCartAsync(cart.Id); var itemCount = (await _cartService.GetItemsAsync(cart.Id)).Count; var cartChangedResult = new CartChangedResult { ItemCount = itemCount, ValidationList = validationResult, RecalculationResult = calculationResult }; result.Data = cartChangedResult.ToCamelCaseJson(); if (cartChangedResult.ValidationList.Count > 0) { await _systemHubSender.CartChangedAsync(customer.UniqueId.Value, itemCount); } } result.Success = true; result.Html = string.Empty; return Json(new { result.Success, result.Html, result.Data }); } } } ModelState.Remove("BillingCountryName"); var billingCountry = _countryService.GetCountry(model.BillingAddress.CountryCode); model.BillingCountryName = billingCountry != null ? billingCountry.Name : ""; ModelState.Remove("BillingStateName"); var billingState = _countryService.GetState(model.BillingAddress.CountryCode, model.BillingAddress.State); model.BillingStateName = billingState != null ? billingState.Name : ""; ModelState.Remove("DeliveryCountryName"); var deliveryCountry = _countryService.GetCountry(model.DeliveryAddress.CountryCode); model.DeliveryCountryName = deliveryCountry != null ? deliveryCountry.Name : ""; ModelState.Remove("DeliveryStateName"); var deliveryState = _countryService.GetState(model.DeliveryAddress.CountryCode, model.DeliveryAddress.State); model.DeliveryStateName = deliveryState != null ? deliveryState.Name : ""; result.Html = await PartialView("_CheckoutAddress", model).ToStringAsync(ControllerContext); return Json(result); } /// /// Anzeige der Zahlungsmethoden /// /// /// [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [CustomerAuthorize("customerUniqueId")] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public async Task CheckoutPayment(Guid customerUniqueId) { var customer = await _customerService.GetByUniqueIdAsync(customerUniqueId); if (customer != null && customer.Id == User.CustomerId()) { var cart = await _cartService.GetOrCreateCustomerAsync(customer.Id, customer.Address.CountryCode, customer.Address.CountryCode, User.Identity.Name); if (cart != null) { var cartWithNames = await _cartService.GetByCustomerWithNamesAsync(customer.Id, SelectedLanguage, FallbackLanguage); if (cartWithNames.ItemCount > 0) { var checkoutAddress = HttpContext.Session.Get(ShopSessionConstants.CheckoutAddress); if (checkoutAddress != null) { var checkoutPayment = HttpContext.Session.Get(ShopSessionConstants.CheckoutPayment); if (checkoutPayment == null) { checkoutPayment = new CheckoutPaymentVm() { PaymentType = PaymentTypeVm.None }; var shopSettings = await _shopSettingsService.GetAsync(); checkoutPayment.PaymentOnInvoice = shopSettings.PaymentOnInvoice; checkoutPayment.PayPalEnabled = shopSettings.PayPalEnabled; checkoutPayment.KlarnaEnabled = shopSettings.KlarnaEnabled; if (shopSettings.PaymentOnInvoice == false) checkoutPayment.PaymentOnInvoice = customer.PaymentOnInvoice; HttpContext.Session.Set(ShopSessionConstants.CheckoutPayment, checkoutPayment); } else { var shopSettings = await _shopSettingsService.GetAsync(); checkoutPayment.PaymentOnInvoice = shopSettings.PaymentOnInvoice; checkoutPayment.PayPalEnabled = shopSettings.PayPalEnabled; checkoutPayment.KlarnaEnabled = shopSettings.KlarnaEnabled; if (shopSettings.PaymentOnInvoice == false) checkoutPayment.PaymentOnInvoice = customer.PaymentOnInvoice; if (checkoutPayment.PaymentType == PaymentTypeVm.Invoice && checkoutPayment.PaymentOnInvoice == false) checkoutPayment.PaymentType = PaymentTypeVm.None; if (checkoutPayment.PaymentType == PaymentTypeVm.PayPal && checkoutPayment.PayPalEnabled == false) checkoutPayment.PaymentType = PaymentTypeVm.None; if (checkoutPayment.PaymentType == PaymentTypeVm.Klarna && checkoutPayment.KlarnaEnabled == false) checkoutPayment.PaymentType = PaymentTypeVm.None; HttpContext.Session.Set(ShopSessionConstants.CheckoutPayment, checkoutPayment); } return PartialView("_CheckoutPayment", checkoutPayment); } } } } return PartialView("_Error"); } /// /// auswhl der Zahlungsmethode /// /// Model /// JSON [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [ValidateAntiForgeryToken] [HttpPost] public async Task CheckoutPayment(CheckoutPaymentVm model) { var result = new ResponseVm { Success = false }; if (ModelState.IsValid) { if (model.PaymentType != PaymentTypeVm.None) { var checkoutPayment = HttpContext.Session.Get(ShopSessionConstants.CheckoutPayment); if (checkoutPayment != null) { checkoutPayment = model; HttpContext.Session.Set(ShopSessionConstants.CheckoutPayment, checkoutPayment); result.Data = string.Empty; result.Success = true; result.Html = string.Empty; return Json(new { result.Success, result.Html, result.Data }); } } else { ModelState.AddModelError("PaymentType", _localizer["Err_Checkout_PaymentType"]); } } result.Html = await PartialView("_CheckoutPayment", model).ToStringAsync(ControllerContext); return Json(result); } /// /// Anzeige der Zusammenfassung und Validierung der Bestellung /// /// /// [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [CustomerAuthorize("customerUniqueId")] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public async Task CheckoutOrder(Guid customerUniqueId) { var customer = await _customerService.GetByUniqueIdAsync(customerUniqueId); if (customer != null && customer.Id == User.CustomerId()) { var checkoutAddress = HttpContext.Session.Get(ShopSessionConstants.CheckoutAddress); var checkoutPayment = HttpContext.Session.Get(ShopSessionConstants.CheckoutPayment); if (checkoutAddress != null && checkoutPayment != null) { var cart = await _cartService.GetOrCreateCustomerAsync(customer.Id, customer.Address.CountryCode, customer.Address.CountryCode, User.Identity.Name); var validationList = await ValidateCartAsync(cart.Id); var recalculationResult = await RecalculateCartAsync(cart.Id); var cartWithNames = await _cartService.GetByCustomerWithNamesAsync(customer.Id, SelectedLanguage, FallbackLanguage); var cartItemsWithNames = await _cartService.GetItemsWithNamesAsync(cart.Id, SelectedLanguage, FallbackLanguage); var cartModel = _mapper.Map(cartWithNames); cartModel.BillingCountryName = _countryService.GetCountry(cartModel.BillingCountryCode).Name; cartModel.DeliveryCountryName = _countryService.GetCountry(cartModel.DeliveryCountryCode).Name; cartModel.CartItems = new List(); if (cartItemsWithNames.Any()) { cartModel.CartItems = _mapper.Map>(cartItemsWithNames); } foreach (var cartItemListVm in cartModel.CartItems) { if (cartItemListVm.ProductType == ProductTypeVm.Listing) { var listing = await _listingService.GetByCartItemAsync(cartItemListVm.Id); if (listing != null) { var country = _countryService.GetCountry(listing.Address.CountryCode); cartItemListVm.ProductSpecialInfo = $"{country.Name} | {listing.StartDate.Value.Date.ToShortDateString()} - {listing.EndDate.Value.Date.ToShortDateString()}"; } } else if (cartItemListVm.ProductType == ProductTypeVm.Advertisement) { var advertisement = await _advertisementService.GetByCartItemAsync(cartItemListVm.Id); if (advertisement != null) { var country = _countryService.GetCountry(advertisement.Address.CountryCode); cartItemListVm.ProductSpecialInfo = $"{country.Name} | {advertisement.StartDate.Value.Date.ToShortDateString()} - {advertisement.EndDate.Value.Date.ToShortDateString()}"; } } else if (cartItemListVm.ProductType == ProductTypeVm.Banner) { var banner = await _bannerService.GetByCartItemAsync(cartItemListVm.Id); if (banner != null) { var country = _countryService.GetCountry(banner.Address.CountryCode); cartItemListVm.ProductSpecialInfo = $"{country.Name} | {banner.StartDate.Value.Date.ToShortDateString()}"; } } else if (cartItemListVm.ProductType == ProductTypeVm.Pin) { var pin = await _pinService.GetByCartItemAsync(cartItemListVm.Id); if (pin != null) { cartItemListVm.ProductSpecialInfo = $"Lat: {pin.Location.Y.ToString("N6")} Lng: {pin.Location.X.ToString("N6")} Rad: {pin.Radius.ToString("N2")}km | {pin.StartDate.Value.Date.ToShortDateString()} - {pin.EndDate.Value.Date.ToShortDateString()}"; } } } ViewBag.ValidationList = validationList; ViewBag.RecalculationResult = recalculationResult; ViewBag.CartModel = cartModel; ViewBag.AddressModel = checkoutAddress; ViewBag.PaymentModel = checkoutPayment; var model = new CheckoutOrderVm() { CustomerUniqueId = customerUniqueId, AcceptTermsAndConditions = false, AcceptGdpr = false }; return PartialView("_CheckoutOrder", model); } } return PartialView("_Error"); } /// /// Bestellung durchführen.... /// /// Model /// JSON [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [CustomerAuthorize("CustomerUniqueId")] [ValidateAntiForgeryToken] [HttpPost] public async Task CheckoutOrder(CheckoutOrderVm model) { var result = new ResponseVm { Success = false }; var checkoutAddress = HttpContext.Session.Get(ShopSessionConstants.CheckoutAddress); var checkoutPayment = HttpContext.Session.Get(ShopSessionConstants.CheckoutPayment); if (ModelState.IsValid) { var customer = await _customerService.GetByUniqueIdAsync(model.CustomerUniqueId.Value); if (customer != null && customer.Id == User.CustomerId()) { if (checkoutPayment != null && checkoutAddress != null) { var cart = await _cartService.GetOrCreateCustomerAsync(customer.Id, checkoutAddress.BillingAddress.CountryCode, checkoutAddress.DeliveryAddress.CountryCode, User.Identity.Name); var cartItems = await _cartService.GetItemsAsync(cart.Id); //Jetzt Bestellung durchführen... var billingAddress = new OrderAddress() { Title = checkoutAddress.Title, FirstName = checkoutAddress.FirstName, LastName = checkoutAddress.LastName, Company = checkoutAddress.Company, Vat = checkoutAddress.Vat, AddressLine1 = checkoutAddress.BillingAddress.AddressLine1, AddressLine2 = checkoutAddress.BillingAddress.AddressLine2, City = checkoutAddress.BillingAddress.City, Zip = checkoutAddress.BillingAddress.Zip, State = checkoutAddress.BillingAddress.State, CountryCode = checkoutAddress.BillingAddress.CountryCode }; var deliveryAddress = new OrderAddress() { Title = checkoutAddress.DeliveryTitle, FirstName = checkoutAddress.DeliveryFirstName, LastName = checkoutAddress.DeliveryLastName, Company = checkoutAddress.DeliveryCompany, Vat = checkoutAddress.DeliveryVat, AddressLine1 = checkoutAddress.DeliveryAddress.AddressLine1, AddressLine2 = checkoutAddress.DeliveryAddress.AddressLine2, City = checkoutAddress.DeliveryAddress.City, Zip = checkoutAddress.DeliveryAddress.Zip, State = checkoutAddress.DeliveryAddress.State, CountryCode = checkoutAddress.DeliveryAddress.CountryCode }; if (checkoutAddress.DeliveryAddressIsBilling) { deliveryAddress = new OrderAddress() { Title = checkoutAddress.Title, FirstName = checkoutAddress.FirstName, LastName = checkoutAddress.LastName, Company = checkoutAddress.Company, Vat = checkoutAddress.Vat, AddressLine1 = checkoutAddress.BillingAddress.AddressLine1, AddressLine2 = checkoutAddress.BillingAddress.AddressLine2, City = checkoutAddress.BillingAddress.City, Zip = checkoutAddress.BillingAddress.Zip, State = checkoutAddress.BillingAddress.State, CountryCode = checkoutAddress.BillingAddress.CountryCode }; } Order order = null; if (HttpContext.Session.Get(ShopSessionConstants.CheckoutOrderId) != null) { var orderId = HttpContext.Session.Get(ShopSessionConstants.CheckoutOrderId); order = await _orderService.UpdateAsync(orderId, cart, cartItems, (PaymentType)checkoutPayment.PaymentType, PaymentStatus.Pending, ShipmentType.Postal, ShipmentStatus.NotYetShipped, deliveryAddress, billingAddress, checkoutAddress.DeliveryAddressIsBilling, SelectedLanguage, FallbackLanguage, User.Identity.Name); } else { order = await _orderService.CreateAsync(cart, cartItems, (PaymentType)checkoutPayment.PaymentType, PaymentStatus.Pending, ShipmentType.Postal, ShipmentStatus.NotYetShipped, deliveryAddress, billingAddress, checkoutAddress.DeliveryAddressIsBilling, SelectedLanguage, FallbackLanguage, User.Identity.Name); } //Listungen reservieren, wenn welche dabei sind await _listingService.SetStatusByOrderAsync(order.Id, ListingStatus.Reserverd, DateTimeOffset.UtcNow.AddHours(1)); await _listingService.CommitAsync(User.Identity.Name); HttpContext.Session.Set(ShopSessionConstants.CheckoutOrderId, order.Id); if (checkoutPayment.PaymentType == PaymentTypeVm.Invoice) { bool isDigitalOnly = await _orderService.IsDigitaglOnlyAsync(order.Id); order.PaymentInfo = $"{DateTime.UtcNow}: Payment on invoice granted." + System.Environment.NewLine + order.PaymentInfo; if (isDigitalOnly) { order.ShipmentStatus = ShipmentStatus.Delivered; order.ShipmentDate = DateTimeOffset.UtcNow; order.OrderStatus = OrderStatus.Processing; } await _orderService.CommitAsync("invoice"); //Listungen auf zu bezahlen setzen await _listingService.SetStatusByOrderAsync(order.Id, ListingStatus.ToPay, null); await _listingService.CommitAsync(User.Identity.Name); //Werbungen auf zu bezahlen setzen await _advertisementService.SetStatusByOrderAsync(order.Id, AdvertisementStatus.ToPay); await _advertisementService.CommitAsync(User.Identity.Name); //Banner auf zu bezahlen setzen await _bannerService.SetStatusByOrderAsync(order.Id, BannerStatus.ToPay); await _bannerService.CommitAsync(User.Identity.Name); //Banner auf zu bezahlen setzen await _pinService.SetStatusByOrderAsync(order.Id, PinStatus.ToPay); await _pinService.CommitAsync(User.Identity.Name); var fileName = $"{order.Number}.pdf"; var file = ControllerContext.GetPdfWithHeaderAndFooter(_urlHelperFactory, _environment, "Print", "InvoiceProforma", new { orderId = order.Id, language = SelectedLanguage }); //Emails senden await SendOrderConfirmationAsync(order.Id, fileName, file); await SendOrderConfirmationCustomerAsync(order.Id, fileName, file); result.Success = true; result.Data = string.Empty; //Aufräumen HttpContext.Session.Remove(ShopSessionConstants.CheckoutAddress); HttpContext.Session.Remove(ShopSessionConstants.CheckoutPayment); await _cartService.ClearAsync(cart.Id, false, User.Identity.Name); await _systemHubSender.CartChangedAsync(customer.UniqueId.Value, 0); result.Html = string.Empty; return Json(new { result.Success, result.Html, result.Data }); } else if (checkoutPayment.PaymentType == PaymentTypeVm.PayPal) { //Nun PayPal-Order anlegen und einen Redirect veranlassen var shopSettings = await _shopSettingsService.GetAsync(); var successUrl = Url.Action("PayPalSuccess", "Shop", new { ouid = order.UniqueId }, HttpContext.Request.Scheme); var cancelUrl = Url.Action("PayPalCancel", "Shop", new { ouid = order.UniqueId }, HttpContext.Request.Scheme); var redirectUrl = await _payPalService.CreateOrderAsync(order.Id, shopSettings.PayPalClientId, shopSettings.PayPalSecret, successUrl, cancelUrl); if (!string.IsNullOrWhiteSpace(redirectUrl)) { result.Success = true; result.Data = redirectUrl; result.Html = string.Empty; return Json(new { result.Success, result.Html, result.Data }); } else { order.OrderStatus = OrderStatus.Cancelled; order.PaymentInfo = $"{DateTime.UtcNow}: PayPal order cancelled." + System.Environment.NewLine + order.PaymentInfo; await _orderService.CommitAsync("paypal"); await _listingService.SetStatusByOrderAsync(order.Id, ListingStatus.Cancelled, null); await _listingService.CommitAsync(User.Identity.Name); await _advertisementService.SetStatusByOrderAsync(order.Id, AdvertisementStatus.Cancelled); await _advertisementService.CommitAsync(User.Identity.Name); await _bannerService.SetStatusByOrderAsync(order.Id, BannerStatus.Cancelled); await _bannerService.CommitAsync(User.Identity.Name); await _pinService.SetStatusByOrderAsync(order.Id, PinStatus.Cancelled); await _pinService.CommitAsync(User.Identity.Name); HttpContext.Session.Remove(ShopSessionConstants.CheckoutOrderId); ModelState.AddModelError("", _localizer["PayPal_Payment_Declined"]); } } else if (checkoutPayment.PaymentType == PaymentTypeVm.Klarna) { //Nun Klarna Order anlegen und Widget anzeigen var shopSettings = await _shopSettingsService.GetAsync(); var termsUrl = Url.Action("TermsAndConditions", "Shop", null, HttpContext.Request.Scheme); var checkoutUrl = Url.Action("ShowCart", "Shop", null, HttpContext.Request.Scheme); var confirmationUrl = Url.Action("KlarnaConfirmation", "Shop", new { ouid = order.UniqueId }, HttpContext.Request.Scheme); var pushUrl = Url.Action("KlarnaPush", "Shop", new { ouid = order.UniqueId }, HttpContext.Request.Scheme); var klarnaOrder = await _klarnaService.CreateOrderAsync(order.Id, shopSettings.KlarnaClientId, shopSettings.KlarnaSecret, termsUrl, checkoutUrl, confirmationUrl, pushUrl); if (klarnaOrder != null) { result.Success = true; result.Data = "klarna"; result.Html = klarnaOrder.HtmlSnippet; return Json(new { result.Success, result.Html, result.Data }); } else { order.OrderStatus = OrderStatus.Cancelled; order.PaymentInfo = $"{DateTime.UtcNow}: Klarna order cancelled." + System.Environment.NewLine + order.PaymentInfo; await _orderService.CommitAsync("klarna"); await _listingService.SetStatusByOrderAsync(order.Id, ListingStatus.Cancelled, null); await _listingService.CommitAsync(User.Identity.Name); await _advertisementService.SetStatusByOrderAsync(order.Id, AdvertisementStatus.Cancelled); await _advertisementService.CommitAsync(User.Identity.Name); await _bannerService.SetStatusByOrderAsync(order.Id, BannerStatus.Cancelled); await _bannerService.CommitAsync(User.Identity.Name); await _pinService.SetStatusByOrderAsync(order.Id, PinStatus.Cancelled); await _pinService.CommitAsync(User.Identity.Name); HttpContext.Session.Remove(ShopSessionConstants.CheckoutOrderId); ModelState.AddModelError("", _localizer["Klarna_Payment_Declined"]); } } } } } var customer2 = await _customerService.GetByUniqueIdAsync(model.CustomerUniqueId.Value); var cart2 = await _cartService.GetOrCreateCustomerAsync(customer2.Id, customer2.Address.CountryCode, customer2.Address.CountryCode, User.Identity.Name); var validationList = await ValidateCartAsync(cart2.Id); var recalculationResult = await RecalculateCartAsync(cart2.Id); var cartWithNames = await _cartService.GetByCustomerWithNamesAsync(customer2.Id, SelectedLanguage, FallbackLanguage); var cartItemsWithNames = await _cartService.GetItemsWithNamesAsync(cart2.Id, SelectedLanguage, FallbackLanguage); var cartModel = _mapper.Map(cartWithNames); cartModel.BillingCountryName = _countryService.GetCountry(cartModel.BillingCountryCode).Name; cartModel.DeliveryCountryName = _countryService.GetCountry(cartModel.DeliveryCountryCode).Name; cartModel.CartItems = new List(); if (cartItemsWithNames.Any()) { cartModel.CartItems = _mapper.Map>(cartItemsWithNames); } foreach (var cartItemListVm in cartModel.CartItems) { if (cartItemListVm.ProductType == ProductTypeVm.Listing) { var listing = await _listingService.GetByCartItemAsync(cartItemListVm.Id); if (listing != null) { var country = _countryService.GetCountry(listing.Address.CountryCode); cartItemListVm.ProductSpecialInfo = $"{country.Name} | {listing.StartDate.Value.Date.ToShortDateString()} - {listing.EndDate.Value.Date.ToShortDateString()}"; } } else if (cartItemListVm.ProductType == ProductTypeVm.Advertisement) { var advertisement = await _advertisementService.GetByCartItemAsync(cartItemListVm.Id); if (advertisement != null) { var country = _countryService.GetCountry(advertisement.Address.CountryCode); cartItemListVm.ProductSpecialInfo = $"{country.Name} | {advertisement.StartDate.Value.Date.ToShortDateString()} - {advertisement.EndDate.Value.Date.ToShortDateString()}"; } } else if (cartItemListVm.ProductType == ProductTypeVm.Banner) { var banner = await _bannerService.GetByCartItemAsync(cartItemListVm.Id); if (banner != null) { var country = _countryService.GetCountry(banner.Address.CountryCode); cartItemListVm.ProductSpecialInfo = $"{country.Name} | {banner.StartDate.Value.Date.ToShortDateString()}"; } } else if (cartItemListVm.ProductType == ProductTypeVm.Pin) { var pin = await _pinService.GetByCartItemAsync(cartItemListVm.Id); if (pin != null) { cartItemListVm.ProductSpecialInfo = $"Lat: {pin.Location.Y.ToString("N6")} Lng: {pin.Location.X.ToString("N6")} Rad: {pin.Radius.ToString("N2")}km | {pin.StartDate.Value.Date.ToShortDateString()} - {pin.EndDate.Value.Date.ToShortDateString()}"; } } } ViewBag.ValidationList = validationList; ViewBag.RecalculationResult = recalculationResult; ViewBag.CartModel = cartModel; ViewBag.AddressModel = checkoutAddress; ViewBag.PaymentModel = checkoutPayment; result.Html = await PartialView("_CheckoutOrder", model).ToStringAsync(ControllerContext); return Json(result); } /// /// Anzeige der Bestellbestätigung /// /// /// [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [CustomerAuthorize("customerUniqueId")] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public async Task CheckoutConfirmation(Guid customerUniqueId) { var checkoutOrderId = HttpContext.Session.Get(ShopSessionConstants.CheckoutOrderId); var customer = await _customerService.GetByUniqueIdAsync(customerUniqueId); if (customer != null && customer.Id == User.CustomerId()) { HttpContext.Session.Remove(ShopSessionConstants.CheckoutOrderId); var order = await _orderService.GetAsync(checkoutOrderId); if (order != null) { ViewBag.Customer = customer; var model = _mapper.Map(order); if (order.PaymentType == PaymentType.Klarna) return PartialView("_CheckoutConfirmationKlarna", model); return PartialView("_CheckoutConfirmation", model); } } return PartialView("_Error"); } #endregion #region PayPal /// /// Abhandeln einer Authorisierten Bestellung via PayPal /// /// UniqueId der Bestellung /// Bestell-ID PayPal /// Id des Payers auf PayPal /// View [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public async Task PayPalSuccess(Guid ouid, string token, string payerId) { var shopSettings = await _shopSettingsService.GetAsync(); var errorMessage = string.Empty; var order = await _orderService.GetByPayPalIdAsync(token); if (order != null && order.OrderStatus == OrderStatus.Pending && order.PaymentStatus == PaymentStatus.Pending && order.PaymentType == PaymentType.PayPal) { order.PaymentStatus = PaymentStatus.Authorized; order.PaymentInfo = $"{DateTime.UtcNow}: PayPal order authorized." + System.Environment.NewLine + order.PaymentInfo; order.LastUpdate = DateTimeOffset.UtcNow; await _orderService.CommitAsync("paypal"); HttpContext.Session.Remove(ShopSessionConstants.CheckoutOrderId); var success = await _payPalService.AuthorizeOrderAsync(token, shopSettings.PayPalClientId, shopSettings.PayPalSecret); if (success) { bool isDigitalOnly = await _orderService.IsDigitaglOnlyAsync(order.Id); order.PaymentStatus = PaymentStatus.Paid; order.PaymentDate = DateTime.UtcNow; order.PaymentInfo = $"{DateTime.UtcNow}: PayPal order paid." + System.Environment.NewLine + order.PaymentInfo; if (isDigitalOnly) { order.ShipmentDate = DateTimeOffset.UtcNow; order.ShipmentStatus = ShipmentStatus.Delivered; order.OrderStatus = OrderStatus.Complete; } order.LastUpdate = DateTimeOffset.UtcNow; await _orderService.CommitAsync("paypal"); var invoice = await _invoiceService.CreateAsync(order.Id); _invoiceService.Add(invoice); await _invoiceService.CommitAsync("paypal"); //Listungen setzen.... await _listingService.SetStatusByOrderAsync(order.Id, ListingStatus.Booked, null); await _listingService.SetPaymentStatusByOrderAsync(order.Id, PaymentStatus.Paid); await _listingService.CommitAsync(User.Identity.Name); //Werbungen setzen.... await _advertisementService.SetStatusByOrderAsync(order.Id, AdvertisementStatus.Booked); await _advertisementService.SetPaymentStatusByOrderAsync(order.Id, PaymentStatus.Paid); await _advertisementService.CommitAsync(User.Identity.Name); //Banner setzen.... await _bannerService.SetStatusByOrderAsync(order.Id, BannerStatus.Booked); await _bannerService.SetPaymentStatusByOrderAsync(order.Id, PaymentStatus.Paid); await _bannerService.CommitAsync(User.Identity.Name); //Pin setzen.... await _pinService.SetStatusByOrderAsync(order.Id, PinStatus.Booked); await _pinService.SetPaymentStatusByOrderAsync(order.Id, PaymentStatus.Paid); await _pinService.CommitAsync(User.Identity.Name); var fileName = $"{invoice.Number}.pdf"; var file = ControllerContext.GetPdfWithHeaderAndFooter(_urlHelperFactory, _environment, "Print", "Invoice", new { orderId = order.Id, language = SelectedLanguage }); await SendOrderConfirmationAsync(order.Id, fileName, file); await SendOrderConfirmationCustomerAsync(order.Id, fileName, file); //Aufräumen HttpContext.Session.Remove(ShopSessionConstants.CheckoutAddress); HttpContext.Session.Remove(ShopSessionConstants.CheckoutPayment); var customer = await _customerService.GetAsync(order.CustomerId.Value); var cart = await _cartService.GetByCustomerAsync(customer.Id); await _cartService.ClearAsync(cart.Id, false, User.Identity.Name); await _systemHubSender.CartChangedAsync(customer.UniqueId.Value, 0); HttpContext.Session.Set(ShopSessionConstants.CheckoutOrderId, order.Id); return RedirectToAction("ShowCart", new{showConfirmation = true}); } else { order.OrderStatus = OrderStatus.Cancelled; order.PaymentInfo = $"{DateTime.UtcNow}: PayPal order cancelled." + System.Environment.NewLine + order.PaymentInfo; order.LastUpdate = DateTimeOffset.UtcNow; await _orderService.CommitAsync("paypal"); await _listingService.SetStatusByOrderAsync(order.Id, ListingStatus.Cancelled, null); await _listingService.CommitAsync(User.Identity.Name); await _advertisementService.SetStatusByOrderAsync(order.Id, AdvertisementStatus.Cancelled); await _advertisementService.CommitAsync(User.Identity.Name); await _bannerService.SetStatusByOrderAsync(order.Id, BannerStatus.Cancelled); await _bannerService.CommitAsync(User.Identity.Name); await _pinService.SetStatusByOrderAsync(order.Id, PinStatus.Cancelled); await _pinService.CommitAsync(User.Identity.Name); errorMessage = _localizer["PayPal_Payment_Declined"]; } } else { errorMessage = _localizer["PayPal_Order_NotFound"]; } return View("PayPalError", errorMessage); } /// /// Abbrechen einer Bestellung via PayPal /// /// UniqueId der Bestellung /// Bestell-ID PayPal /// View [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public async Task PayPalCancel(Guid ouid, string token) { var order = await _orderService.GetByPayPalIdAsync(token); if (order != null && order.OrderStatus == OrderStatus.Pending) { order.PaymentStatus = PaymentStatus.Pending; order.PaymentInfo = $"{DateTime.UtcNow}: PayPal order cancelled." + System.Environment.NewLine + order.PaymentInfo; order.LastUpdate = DateTimeOffset.UtcNow; await _orderService.CommitAsync("paypal"); } else { HttpContext.Session.Remove(ShopSessionConstants.CheckoutOrderId); var errorMessage = _localizer["PayPal_Order_NotFound"]; return View("PayPalError", errorMessage); } return View(); } #endregion #region Klarna /// /// Abhandeln einer Authorisierten Bestellung via Klarna /// /// UniqueId der Bestellung /// View [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public async Task KlarnaConfirmation(Guid ouid) { var errorMessage = string.Empty; var order = await _orderService.GetByUniqueIdAsync(ouid); if (order != null && order.OrderStatus == OrderStatus.Pending && order.PaymentStatus == PaymentStatus.Pending && order.PaymentType == PaymentType.Klarna) { var shopSettings = await _shopSettingsService.GetAsync(); var klarnaOrder = await _klarnaService.GetOrderAsync(order.KlarnaOrderId, shopSettings.KlarnaClientId, shopSettings.KlarnaSecret); if (klarnaOrder != null) { order.PaymentStatus = PaymentStatus.Authorized; order.PaymentInfo = $"{DateTime.UtcNow}: Klarna order authorized." + System.Environment.NewLine + order.PaymentInfo; order.LastUpdate = DateTimeOffset.UtcNow; await _orderService.CommitAsync("klarna"); //Den Erfolg anzeigen, aber darauf hinweisen, dass wir noch auf die endgültige Bestätigung von Klarna warten //Aufräumen HttpContext.Session.Remove(ShopSessionConstants.CheckoutAddress); HttpContext.Session.Remove(ShopSessionConstants.CheckoutPayment); var customer = await _customerService.GetAsync(order.CustomerId.Value); var cart = await _cartService.GetByCustomerAsync(customer.Id); await _cartService.ClearAsync(cart.Id, false, User.Identity.Name); await _systemHubSender.CartChangedAsync(customer.UniqueId.Value, 0); HttpContext.Session.Set(ShopSessionConstants.CheckoutOrderId, order.Id); return RedirectToAction("ShowCart", new { showConfirmation = true }); } else { order.OrderStatus = OrderStatus.Cancelled; order.PaymentInfo = $"{DateTime.UtcNow}: Klarna order cancelled." + System.Environment.NewLine + order.PaymentInfo; order.LastUpdate = DateTimeOffset.UtcNow; await _orderService.CommitAsync("klarna"); await _listingService.SetStatusByOrderAsync(order.Id, ListingStatus.Cancelled, null); await _listingService.CommitAsync(User.Identity.Name); await _advertisementService.SetStatusByOrderAsync(order.Id, AdvertisementStatus.Cancelled); await _advertisementService.CommitAsync(User.Identity.Name); await _bannerService.SetStatusByOrderAsync(order.Id, BannerStatus.Cancelled); await _bannerService.CommitAsync(User.Identity.Name); await _pinService.SetStatusByOrderAsync(order.Id, PinStatus.Cancelled); await _pinService.CommitAsync(User.Identity.Name); errorMessage = _localizer["Klarna_Payment_Declined"]; } } else { errorMessage = _localizer["Klarna_Order_NotFound"]; } return View("KlarnaError", errorMessage); } /// /// Push-Benachrichtigung von Klarna für den Erfolg der Zahlungsauthorisierung /// /// Unique-ID der Bestellung /// HTTP OK [AllowAnonymous] [HttpPost] public async Task KlarnaPush(string ouid) { if (!string.IsNullOrWhiteSpace(ouid)) { if (Guid.TryParse(ouid, out var uniqueId)) { var order = await _orderService.GetByUniqueIdAsync(uniqueId); if (order != null && order.OrderStatus == OrderStatus.Pending && order.PaymentStatus == PaymentStatus.Authorized && order.PaymentType == PaymentType.Klarna) { var shopSettings = await _shopSettingsService.GetAsync(); var klarnaOrder = await _klarnaService.GetManagementOrderAsync(order.KlarnaOrderId, shopSettings.KlarnaClientId, shopSettings.KlarnaSecret); if (klarnaOrder.Status == Klarna.OrderManagement.Order.StatusEnum.AUTHORIZEDEnum) { //Jetzt bestätigen! var success = await _klarnaService.AcknowledgeOrderAsync(order.KlarnaOrderId, shopSettings.KlarnaClientId, shopSettings.KlarnaSecret); if (success) { bool isDigitalOnly = await _orderService.IsDigitaglOnlyAsync(order.Id); order.PaymentStatus = PaymentStatus.Paid; order.PaymentDate = DateTime.UtcNow; order.PaymentInfo = $"{DateTime.UtcNow}: Klarna order paid." + System.Environment.NewLine + order.PaymentInfo; if (isDigitalOnly) { order.ShipmentDate = DateTimeOffset.UtcNow; order.ShipmentStatus = ShipmentStatus.Delivered; order.OrderStatus = OrderStatus.Complete; order.KlarnaShipmentSentDate = DateTimeOffset.UtcNow; await _klarnaService.CaptureOrderAsync(order.Id, shopSettings.KlarnaClientId, shopSettings.KlarnaSecret); } order.LastUpdate = DateTimeOffset.UtcNow; await _orderService.CommitAsync("klarna"); var invoice = await _invoiceService.CreateAsync(order.Id); _invoiceService.Add(invoice); await _invoiceService.CommitAsync("klarna"); //Listungen setzen.... await _listingService.SetStatusByOrderAsync(order.Id, ListingStatus.Booked, null); await _listingService.SetPaymentStatusByOrderAsync(order.Id, PaymentStatus.Paid); await _listingService.CommitAsync("klarna"); //Werbungen setzen.... await _advertisementService.SetStatusByOrderAsync(order.Id, AdvertisementStatus.Booked); await _advertisementService.SetPaymentStatusByOrderAsync(order.Id, PaymentStatus.Paid); await _advertisementService.CommitAsync("klarna"); //Banner setzen.... await _bannerService.SetStatusByOrderAsync(order.Id, BannerStatus.Booked); await _bannerService.SetPaymentStatusByOrderAsync(order.Id, PaymentStatus.Paid); await _bannerService.CommitAsync("klarna"); //Pin setzen.... await _pinService.SetStatusByOrderAsync(order.Id, PinStatus.Booked); await _pinService.SetPaymentStatusByOrderAsync(order.Id, PaymentStatus.Paid); await _pinService.CommitAsync("klarna"); var fileName = $"{invoice.Number}.pdf"; var file = ControllerContext.GetPdfWithHeaderAndFooter(_urlHelperFactory, _environment, "Print", "Invoice", new { orderId = order.Id, language = SelectedLanguage }); await SendOrderConfirmationAsync(order.Id, fileName, file); await SendOrderConfirmationCustomerAsync(order.Id, fileName, file); } } } } } return new OkResult(); } #endregion #region TermsAndConditions und Privacy /// /// Anzeigen der AGB als PDF /// /// [AllowAnonymous] public IActionResult TermsAndConditions() { var rootPath = _hostEnvironment.WebRootPath; var fileName = $"TermsAndConditions_{SelectedLanguage}.pdf"; var path = Path.Combine(rootPath, $"app_files\\downloads\\{fileName}"); if (!System.IO.File.Exists(path)) { fileName = $"TermsAndConditions_{FallbackLanguage}.pdf"; path = Path.Combine(rootPath, $"app_files\\downloads\\{fileName}"); } var file = System.IO.File.ReadAllBytes(path); return File(file, GetMimeMapping(path)); } /// /// Anzeigen der Datenschutzbestimmungen als PDF /// /// [AllowAnonymous] public IActionResult Privacy() { var rootPath = _hostEnvironment.WebRootPath; var fileName = $"Privacy_{SelectedLanguage}.pdf"; var path = Path.Combine(rootPath, $"app_files\\downloads\\{fileName}"); if (!System.IO.File.Exists(path)) { fileName = $"Privacy_{FallbackLanguage}.pdf"; path = Path.Combine(rootPath, $"app_files\\downloads\\{fileName}"); } var file = System.IO.File.ReadAllBytes(path); return File(file, GetMimeMapping(path)); } #endregion #region Helper /// /// Berechnet den Preis für ein Produkt aliquot für die Anzeige beim Hinzufügen im Warenkorb /// /// Model /// JSON [Authorize(Policy = Policies.CustomerOnly)] [HasPermission(Permission.ShopAccess)] [HttpPost] public async Task GetAliquotPrice(CalculatePriceVm model) { var result = new PriceCalculation(); var customer = await _customerService.GetAsync(User.CustomerId().Value); if (customer != null && customer.Id == model.CustomerId) { var product = await _productService.GetAsync(model.ProductId); if (product != null) { result = await _shopCalculationService.CalculatePriceAsync(product.Id, customer.Id, product.PriceType, product.PriceAliquotType, model.StartDate, model.EndDate, model.Quantity); } } return Json(result); } #endregion #region Private /// /// Entfernen eines Artikels aus dem Warenkorb - Hilfsfunktion /// /// /// private async Task RemoveCartItemAsync(CartItem cartItem) { //Wenn es ein zugeordnetes Produkt gibt (Listung usw.) dieses suchen und löschen if (cartItem.ProductType == ProductType.Listing) { var listing = await _listingService.GetAsync(cartItem.ItemId); if (listing != null) { _listingService.Remove(listing); } } else if (cartItem.ProductType == ProductType.Advertisement) { var advertisement = await _advertisementService.GetAsync(cartItem.ItemId); if (advertisement != null) { _advertisementService.Remove(advertisement); } } else if (cartItem.ProductType == ProductType.Banner) { var banner = await _bannerService.GetAsync(cartItem.ItemId); if (banner != null) { _bannerService.Remove(banner); } } else if (cartItem.ProductType == ProductType.Pin) { var pin = await _pinService.GetAsync(cartItem.ItemId); if (pin != null) { _pinService.Remove(pin); } } //Dann CartItem löschen await _cartService.DeleteCartItemAsync(cartItem.Id); } /// /// Prüfen des Warenkorbs ob Produkte enthalten sind die auf Grund von Änderungen der Rechnungs- /// oder Lieferadresse nicht mehr enthalten sein dürfen /// /// Id des Warenkorbs /// Liste von entfernten Produkten oder leer wenn keine Änderungen private async Task> ValidateCartAsync(long cartId) { var resultList = new List(); var cart = await _cartService.GetAsync(cartId); if (cart != null) { var cartItems = await _cartService.GetItemsAsync(cart.Id); foreach (var cartItem in cartItems) { //Zuerst Zielland prüfen var productCountry = await _productService.GetCountryAsync(cartItem.ProductId, cart.BillingCountryCode); if (productCountry != null) { if (productCountry.NotAvailable) { var product = await _productService.GetAsync(cartItem.ProductId); resultList.Add(string.Format(_localizer["Err_Product_Country_NotAvailable"].Value, product.Name)); await RemoveCartItemAsync(cartItem); continue; } } //Nun noch je Produkt prüfen. wichti für Listungen wenn diese in der Zwischenzeit nicht mehr verfügbar sein sollten switch (cartItem.ProductType) { case ProductType.Physical: break; case ProductType.Download: break; case ProductType.Listing: var listing = await _listingService.GetAsync(cartItem.ItemId); var availableResult = await _listingService.IsAvailableAsync(listing.CustomerId, listing.BranchId, (ListingType)listing.ListingType, listing.StartDate.Value, listing.EndDate.Value, listing.Address.CountryCode, listing.Id); if (availableResult.Valid == false) { var product = await _productService.GetAsync(cartItem.ProductId); resultList.Add(string.Format(_localizer["Err_Product_Country_NoMoreAvailable"].Value, product.Name)); await RemoveCartItemAsync(cartItem); continue; } break; case ProductType.Advertisement: break; case ProductType.Pin: break; case ProductType.Banner: break; default: throw new ArgumentOutOfRangeException(); } } await _cartService.CommitAsync(User.Identity.Name); } return resultList; } /// /// Neuberechnen des Warenkorbes - Länderänderungen werden berücksichtigt /// /// Id des Warenkorbes /// RecalculationResult private async Task RecalculateCartAsync(long cartId) { var result = new RecalculationResult(); var cart = await _cartService.GetAsync(cartId); if (cart != null) { var totalGrossOld = cart.TotalGross; var shipmentGrossOld = cart.ShipmentGross; var cartItems = await _cartService.GetItemsAsync(cart.Id); foreach (var cartItem in cartItems) { switch (cartItem.ProductType) { case ProductType.Physical: break; case ProductType.Download: break; case ProductType.Listing: var listing = await _listingService.GetAsync(cartItem.ItemId); var productListing = await _productService.GetAsync(cartItem.ProductId); var priceCalculationListing = await _shopCalculationService.CalculatePriceAsync(productListing.Id, cart.CustomerId.Value, productListing.PriceType, productListing.PriceAliquotType, listing.StartDate.Value, listing.EndDate.Value, cart.BillingCountryCode,1); cartItem.Price = priceCalculationListing.Price; cartItem.PriceGross = priceCalculationListing.PriceGross; cartItem.Price2 = priceCalculationListing.Price2; cartItem.Price2Gross = priceCalculationListing.Price2Gross; cartItem.Total = priceCalculationListing.Total; cartItem.TotalGross = priceCalculationListing.TotalGross; cartItem.TaxRate = priceCalculationListing.TaxRate; cartItem.TaxRateValue = priceCalculationListing.TaxValue; break; case ProductType.Advertisement: var advertisement = await _advertisementService.GetAsync(cartItem.ItemId); var productAdvertisement = await _productService.GetAsync(cartItem.ProductId); var priceCalculationAdvertisement = await _shopCalculationService.CalculatePriceAsync(productAdvertisement.Id, cart.CustomerId.Value, productAdvertisement.PriceType, productAdvertisement.PriceAliquotType, advertisement.StartDate.Value, advertisement.EndDate.Value, cart.BillingCountryCode, 1); cartItem.Price = priceCalculationAdvertisement.Price; cartItem.PriceGross = priceCalculationAdvertisement.PriceGross; cartItem.Price2 = priceCalculationAdvertisement.Price2; cartItem.Price2Gross = priceCalculationAdvertisement.Price2Gross; cartItem.Total = priceCalculationAdvertisement.Total; cartItem.TotalGross = priceCalculationAdvertisement.TotalGross; cartItem.TaxRate = priceCalculationAdvertisement.TaxRate; cartItem.TaxRateValue = priceCalculationAdvertisement.TaxValue; break; case ProductType.Pin: var pin = await _pinService.GetAsync(cartItem.ItemId); var productPin = await _productService.GetAsync(cartItem.ProductId); var priceCalculationPin = await _shopCalculationService.CalculatePriceAsync(productPin.Id, cart.CustomerId.Value, productPin.PriceType, productPin.PriceAliquotType, pin.StartDate.Value, pin.EndDate.Value, cart.BillingCountryCode, 1); if (pin.Radius > productPin.PinRadius && productPin.PinPercentPerKm > 0) { var diff = (decimal)(pin.Radius - productPin.PinRadius); var markup = productPin.PinPercentPerKm * diff; priceCalculationPin = await _shopCalculationService.AddMarkupAsync(priceCalculationPin, markup, productPin.Id, cart.BillingCountryCode); } cartItem.Price = priceCalculationPin.Price; cartItem.PriceGross = priceCalculationPin.PriceGross; cartItem.Price2 = priceCalculationPin.Price2; cartItem.Price2Gross = priceCalculationPin.Price2Gross; cartItem.Total = priceCalculationPin.Total; cartItem.TotalGross = priceCalculationPin.TotalGross; cartItem.TaxRate = priceCalculationPin.TaxRate; cartItem.TaxRateValue = priceCalculationPin.TaxValue; break; case ProductType.Banner: var banner = await _bannerService.GetAsync(cartItem.ItemId); var productBanner = await _productService.GetAsync(cartItem.ProductId); var priceCalculationBanner = await _shopCalculationService.CalculatePriceBannerAsync(productBanner.Id, cart.CustomerId.Value, cart.BillingCountryCode, 1, banner.Budget); cartItem.Price = priceCalculationBanner.Price; cartItem.PriceGross = priceCalculationBanner.PriceGross; cartItem.Price2 = priceCalculationBanner.Price2; cartItem.Price2Gross = priceCalculationBanner.Price2Gross; cartItem.Total = priceCalculationBanner.Total; cartItem.TotalGross = priceCalculationBanner.TotalGross; cartItem.TaxRate = priceCalculationBanner.TaxRate; cartItem.TaxRateValue = priceCalculationBanner.TaxValue; var clickPrices = await _shopCalculationService.CalculatePriceAsync(productBanner.Id, cart.CustomerId.Value, cart.BillingCountryCode, 1); banner.PriceView = clickPrices.PriceGross; banner.PriceClick = clickPrices.Price2Gross; break; default: throw new ArgumentOutOfRangeException(); } } await _cartService.CommitAsync(User.Identity.Name); var cartRecalculated = await _cartService.CalculateAsync(cart.Id, OrderSource.Customer, cart.DeliveryCountryCode, User.Identity.Name); result.TotalGross = cartRecalculated.TotalGross; result.TotalChanged = cartRecalculated.TotalGross != totalGrossOld; result.ShipmentGross = cartRecalculated.ShipmentGross; result.ShipmentChanged = cartRecalculated.ShipmentGross != shipmentGrossOld; } return result; } /// /// Gibt den Mimetype einer Datei zurück /// /// Dateiname /// Mimetype private string GetMimeMapping(string fileName) { new FileExtensionContentTypeProvider().TryGetContentType(fileName, out var contentType); return contentType ?? "application/octet-stream"; } /// /// Senden der Bestellbestätigung für den Shop-Besitzer /// /// Id der Bestellung /// Dateiname einer Datei die mitgesendet werden soll /// Datei die mitgesendet werden soll /// Task private async Task SendOrderConfirmationAsync(long orderId, string fileName, byte[] file) { var shopSettings = await _shopSettingsService.GetAsync(); var order = await _orderService.GetAsync(orderId); var orderVm = _mapper.Map(order); var orderItems = await _orderService.GetItemsAsync(order.Id); foreach (var orderItem in orderItems) { var orderItemVm = _mapper.Map(orderItem); orderVm.Items.Add(orderItemVm); } var currentCulture = CultureInfo.CurrentCulture; CultureInfo.CurrentCulture = new CultureInfo(SelectedLanguage); var body = await PartialView("mails/_Order", orderVm).ToStringAsync(ControllerContext); var targetEmail = shopSettings.OrderEmail; if(string.IsNullOrWhiteSpace(fileName)) await _emailSender.SendEmailAsync(targetEmail, $"gehGassi {_localizer["Mail_Order"].Value}: {order.Number}", body); else await _emailSender.SendEmailAsync(targetEmail, $"gehGassi {_localizer["Mail_Order"].Value}: {order.Number}", body, file, fileName); CultureInfo.CurrentCulture = currentCulture; } /// /// Senden der Bestellbestätigung für den Kunden /// /// Id der Bestellung /// Dateiname einer Datei die mitgesendet werden soll /// Datei die mitgesendet werden soll /// Task private async Task SendOrderConfirmationCustomerAsync(long orderId, string fileName, byte[] file) { var shopSettings = await _shopSettingsService.GetAsync(); var order = await _orderService.GetAsync(orderId); var customer = await _customerService.GetAsync(order.CustomerId.Value); var orderVm = _mapper.Map(order); var orderItems = await _orderService.GetItemsAsync(order.Id); foreach (var orderItem in orderItems) { var orderItemVm = _mapper.Map(orderItem); orderVm.Items.Add(orderItemVm); } var currentCulture = CultureInfo.CurrentCulture; CultureInfo.CurrentCulture = new CultureInfo(SelectedLanguage); var body = await PartialView("mails/_OrderCustomer", orderVm).ToStringAsync(ControllerContext); var targetEmail = customer.Contact.Email; if (string.IsNullOrWhiteSpace(fileName)) await _emailSender.SendEmailAsync(targetEmail, $"gehGassi {_localizer["Mail_Order"].Value}: {order.Number}", body); else await _emailSender.SendEmailAsync(targetEmail, $"gehGassi {_localizer["Mail_Order"].Value}: {order.Number}", body, file, fileName); CultureInfo.CurrentCulture = currentCulture; } #endregion #region Banner Thumbnails /// /// Erstellt ein Thumbnail basierend auf der Breite /// /// Container /// Dateiname /// Größe für Breite und Höhe /// Task internal async Task GenerateBannerThumbnailByWidth(string container, string filename, int size) { try { using (var imgStream = await FileService.GetAsStreamAsync(container, filename)) { using (var img = await Image.LoadAsync(imgStream)) { img.Mutate(x => x.Resize(new ResizeOptions() { Mode = ResizeMode.Max, Size = new Size(size) })); var format = img.DetectEncoder(filename); await using (var memStream = new MemoryStream()) { await img.SaveAsync(memStream, format); memStream.Position = 0; await FileService.StoreAsync(container, $"thumbnails/banner/{size}/{filename}", memStream); } } } } catch { } } /// /// Löschen eines Thumbnails für ein Bild /// /// Container /// Dateiname /// Größe für Breite und Höhe /// Task internal async Task RemoveBannerThumbnail(string container, string fileName, int size) { try { var file = await FileService.GetAsync(container, $"thumbnails/banner/{size}/{fileName}"); if (file != null) { await FileService.DeleteAsync(container, $"thumbnails/banner/{size}/{fileName}"); } } catch { } } #endregion } /// /// Ergebis der Neuberechnung des Carts /// public class RecalculationResult { /// /// Hat sich die Summe in Warenkorb geändert? /// public bool TotalChanged { get; set; } /// /// Gesamt-Preis Brutto /// public decimal TotalGross { get; set; } /// /// Haben sich die Versandkosten geändert? /// public bool ShipmentChanged { get; set; } /// /// Versandkosten Brutto /// public decimal ShipmentGross { get; set; } } /// /// Ergebnis das nach der Änderung des Carts gesendet wird /// public class CartChangedResult { /// /// Anzahl der verbliebenen Artikel im Warenkorb /// public int ItemCount { get; set; } /// /// Liste der entfernten Produkte /// public List ValidationList { get; set; } /// /// Ergebnis der neuberechnung des Cart /// public RecalculationResult RecalculationResult { get; set; } /// /// Erstellt eine Instanz /// public CartChangedResult() { ItemCount = 0; ValidationList = new List(); RecalculationResult = new RecalculationResult(); } } }