Exemple #1
0
        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()));
        }
Exemple #2
0
        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);
        }
    }
}
Exemple #3
0
        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);
        }