public async Task <OperationResult <CouponCodeDto> > GetCouponCodeAsync(string code) { var couponCode = await _couponCodeRepository.GetCouponAsync(code.ToUpper()); if (couponCode is null) { return(OperationResult <CouponCodeDto> .NotFound()); } return(OperationResult <CouponCodeDto> .Success(couponCode.ConvertToDto())); }
public async Task <OperationResult <SaleOrderDto> > CreateSaleAsync(CreateSaleInput input) { var validationResult = await _saleValidator.CreateSaleAsync(input); if (validationResult.IsSuccess) { IEnumerable <Product> products = _productRepository.GetAvailableProducts(input.Products.Select(x => x.ProductId)); Customer customer = await _customerRepository.GetCustomer(input.CustomerEmail); AddressCustomer addressCustomer = await _addressRepository.GetByCustomerAsync(input.CustomerEmail); Address address = addressCustomer.Addresses.Single(x => x.Id == input.AddressId); CouponCode couponCode = null; if (!string.IsNullOrWhiteSpace(input.CouponCode)) { couponCode = await _couponCodeRepository.GetCouponAsync(input.CouponCode); } Order order = new() { Status = OrderStatus.Created, CreationDate = DateTime.Now, CustomerEmail = input.CustomerEmail, Type = OrderType.ProductSale, TotalAmount = CalculateTotalAmount(couponCode, products, customer) }; order = await _orderRepository.CreateAsync(order); Sale sale = new() { CouponCode = input.CouponCode, OrderId = order.Id, Products = products.Select(x => x.Id), Status = SaleStatus.PendingPayment }; sale = await _saleRepository.CreateAsync(sale); SaleDetail saleDetail = new() { SaleId = sale.Id, Products = input.Products }; saleDetail = await _saleDetailRepository.CreateAsync(saleDetail); IPaymentProvider paymentProvider = _paymentProviderFactory.CreatePaymentProvider(input.PaymentProvider); Invoice invoice = await paymentProvider.CreateInvoice(order); invoice = await _invoiceRepository.CreateAsync(invoice); Delivery delivery = new() { AddressId = input.AddressId, OrderId = order.Id, Status = DeliveryStatus.Created }; delivery = await _deliveryRepository.CreateAsync(delivery); return(OperationResult <SaleOrderDto> .Success(new(sale.ConvertToDto(), order.ConvertToDto(), invoice.ConvertToDto()))); } return(OperationResult <SaleOrderDto> .Fail(validationResult)); } private static decimal CalculateTotalAmount(CouponCode couponCode, IEnumerable <Product> products, Customer customer) { decimal totalAmount = products.Sum(x => x.Price); if (couponCode is null) { return(totalAmount); } if (totalAmount < couponCode.MinAmount || totalAmount > couponCode.MaxAmount) { return(totalAmount); } if (DateTime.Today < couponCode.DateStart || DateTime.Today > couponCode.DateExpire) { return(totalAmount); } List <Product> productsToOff = new(); if (couponCode.Customers?.Contains(customer.Email) ?? false) { productsToOff.AddRange(products); } else { if (couponCode.Categories?.Any() ?? false) { productsToOff.AddRange(products.Where(x => couponCode.Categories.Contains(x.Category))); } if (couponCode.SubCategories?.Any() ?? false) { productsToOff.AddRange(products.Where(x => couponCode.SubCategories.Any(y => y.Category == x.Category && y.SubCategory == x.SubCategory))); } if (couponCode.Products?.Any() ?? false) { productsToOff.AddRange(products.Where(x => couponCode.Products.Contains(x.Id))); } } decimal valueOff = couponCode.Type switch { CouponCodeOffType.Percentage => (couponCode.Value / productsToOff.Sum(x => x.Price)) * 100, CouponCodeOffType.SpecificAmount => productsToOff.Sum(x => x.Price) - couponCode.Value, _ => throw new ArgumentException("CouponCodeOffType invalido.", nameof(couponCode)) }; return(totalAmount - valueOff); } } }
public async Task <ValidationResult> CreateSaleAsync(CreateSaleInput input) { ValidationResult validationResult = new(); if (!Enum.IsDefined(input.PaymentProvider)) { validationResult.Messages.Add(new(nameof(CreateSaleInput.PaymentProvider), "El proveedor de pago no es valido.")); } if (string.IsNullOrWhiteSpace(input.CustomerEmail)) { validationResult.Messages.Add(new(nameof(CreateSaleInput.CustomerEmail), "Debe indicar un cliente.")); } else { Customer customer = await _customerRepository.GetCustomer(input.CustomerEmail); if (customer is null) { validationResult.Messages.Add(new(nameof(CreateSaleInput.CustomerEmail), "No existe el cliente.")); } else { AddressCustomer addressCustomer = await _addressRepository.GetByCustomerAsync(input.CustomerEmail); Address address = addressCustomer.Addresses?.SingleOrDefault(x => x.Id == input.AddressId); if (address is null) { validationResult.Messages.Add(new(nameof(CreateSaleInput.AddressId), "La dirección no existe.")); } } } if (!string.IsNullOrWhiteSpace(input.CouponCode)) { CouponCode couponCode = await _couponCodeRepository.GetCouponAsync(input.CouponCode); if (couponCode is null) { validationResult.Messages.Add(new(nameof(CreateSaleInput.CouponCode), "El código de cupón no existe.")); } } if (input.Products is null) { validationResult.Messages.Add(new(nameof(CreateSaleInput.Products), "Debe seleccionar productos.")); } else { foreach (ProductDefinitive productDefinitive in input.Products) { Product product = await _productRepository.GetAsync(productDefinitive.ProductId); if (product is null) { validationResult.Messages.Add(new(nameof(CreateSaleInput.Products), $"El producto con Id {productDefinitive.ProductId} no existe.")); } else if (!product.IsActive) { validationResult.Messages.Add(new(nameof(CreateSaleInput.Products), $"El producto {product.Name} no esta activo.")); } else if (product.Stock <= 0) { validationResult.Messages.Add(new(nameof(CreateSaleInput.Products), $"El producto {product.Name} no tiene stock.")); } else { if (productDefinitive.Variants is not null) { IEnumerable <ProductVariant> variants = await _productVariantRepository.GetByProduct(product); if (variants is not null) { foreach (ProductVariantPair variantPair in productDefinitive.Variants) { ProductVariant productVariant = variants.SingleOrDefault(x => x.Name == variantPair.Name); if (productVariant is null) { validationResult.Messages.Add(new(nameof(CreateSaleInput.Products), $"El producto {product.Name} no tiene variaciones de {variantPair.Name}.")); } else if (!productVariant.Values.Contains(variantPair.Value)) { validationResult.Messages.Add(new(nameof(CreateSaleInput.Products), $"El producto {product.Name} no tiene una variación de {variantPair.Name} con el valor {variantPair.Value}.")); } } } } } } } return(validationResult); }
public async Task <ValidationResult> ValidateCreateCouponCodeAsync(CreateCouponCodeInput input) { ValidationResult validationResult = new(); if (string.IsNullOrWhiteSpace(input.Code)) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.Code), "Debe indicar un código.")); } else { if (input.Code.Length < 3) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.Code), "El código debe contener más de 3 caracteres.")); } else if (!input.Code.All(c => char.IsLetterOrDigit(c))) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.Code), "El código solo debe contener letras y numeros.")); } else { CouponCode couponCode = await _couponCodeRepository.GetCouponAsync(input.Code.ToUpper()); if (couponCode is not null) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.Code), "Ya existe un código con ese nombre.")); } } } if (!Enum.IsDefined(input.Type)) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.Type), "El tipo de código no existe.")); } if (input.Value <= 0) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.Value), "El valor del código debe ser mayor a cero.")); } if (input.Type == CouponCodeOffType.Percentage && input.Value > 100) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.Value), "Un código de tipo porcentaje no puede tener un valor mayor de 100.")); } if (input.MinAmount < 0) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.MinAmount), "El monto mínimo del código debe ser mayor o igual a cero.")); } if (input.MaxAmount.HasValue && input.MaxAmount.Value <= 0) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.MaxAmount), "El monto máximo del código debe ser mayor a cero.")); } if (input.MaxAmount.HasValue && input.MaxAmount.Value < input.MinAmount) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.MaxAmount), "El monto máximo del código no puede ser menor al monto mínimo.")); } if (input.DateStart.ToUniversalTime().Date < DateTime.Today) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.DateStart), "La fecha de inicio no puede ser anterior al día de hoy.")); } if (input.DateExpire.HasValue && input.DateExpire.Value.ToUniversalTime().Date < DateTime.Today) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.DateExpire), "La fecha de expiración no puede ser anterior al día de hoy.")); } if (input.DateExpire.HasValue && input.DateExpire.Value.ToUniversalTime().Date < input.DateStart.ToUniversalTime().Date) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.DateExpire), "La fecha de expiración no puedo ser anterior a la fecha de inicio.")); } if (input.Products?.Any() ?? false) { var products = _productRepository.GetAvailableProducts(input.Products); if (input.Products.Distinct().WhereIsNotEmply().Count() > products.Count()) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.Products), "Algunos productos no existen o no estan activos.")); } } if (input.Customers?.Any() ?? false) { foreach (var customerEmail in input.Customers.Distinct().WhereIsNotEmply()) { var customer = await _customerRepository.GetCustomer(customerEmail); if (customer is null) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.Customers), $"El cliente {customerEmail} no existe.")); } } } if (input.Categories?.Any() ?? false) { foreach (var categoryName in input.Categories.Distinct().WhereIsNotEmply()) { var category = await _productCategoryRepository.GetByNameAsync(categoryName); if (category is null) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.Categories), $"La categoria {categoryName} no existe.")); } } } if (input.SubCategories?.Any() ?? false) { var groups = input.SubCategories.GroupBy(x => x.Category); foreach (var group in groups) { var category = await _productCategoryRepository.GetByNameAsync(group.Key); if (category is null) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.SubCategories), $"La categoria {group.Key} no existe.")); } else { foreach (var item in group) { if (!category.SubCategories.Contains(item.SubCategory)) { validationResult.Messages.Add(new(nameof(CreateCouponCodeInput.SubCategories), $"La subcategoria {item.SubCategory} no existe en la categoria {category.Name}.")); } } } } } return(validationResult); }