private async Task <decimal> ApplyDiscount(User user, Cart cart)
        {
            decimal discount = 0;

            if (!string.IsNullOrWhiteSpace(cart.CouponCode))
            {
                var cartInfoForCoupon = new CartInfoForCoupon
                {
                    Items = cart.Items.Select(x => new CartItemForCoupon {
                        ProductId = x.ProductId, Quantity = x.Quantity
                    }).ToList()
                };
                var couponValidationResult = await _couponService.Validate(cart.CouponCode, cartInfoForCoupon);

                if (couponValidationResult.Succeeded)
                {
                    discount = couponValidationResult.DiscountAmount;
                    _couponService.AddCouponUsage(user.Id, couponValidationResult.CouponId);
                }
                else
                {
                    throw new ApplicationException($"Unable to apply coupon {cart.CouponCode}. {couponValidationResult.ErrorMessage}");
                }
            }

            return(discount);
        }
        public async Task <Result <Order> > CreateOrder(User user, string paymentMethod, decimal paymentFeeAmount, string shippingMethodName, Address billingAddress, Address shippingAddress, OrderStatus orderStatus = OrderStatus.New)
        {
            var cart = _cartRepository
                       .Query()
                       .Include(c => c.Items).ThenInclude(x => x.Product)
                       .Where(x => x.UserId == user.Id && x.IsActive).FirstOrDefault();

            if (cart == null)
            {
                return(Result.Fail <Order>($"Cart of user {user.Id} cannot be found"));
            }

            var checkingDiscountResult = await CheckForDiscountIfAny(user, cart);

            if (!checkingDiscountResult.Succeeded)
            {
                return(Result.Fail <Order>(checkingDiscountResult.ErrorMessage));
            }

            var validateShippingMethodResult = await ValidateShippingMethod(shippingMethodName, shippingAddress, cart);

            if (!validateShippingMethodResult.Success)
            {
                return(Result.Fail <Order>(validateShippingMethodResult.Error));
            }

            var shippingMethod = validateShippingMethodResult.Value;

            var orderBillingAddress = new OrderAddress()
            {
                AddressLine1      = billingAddress.AddressLine1,
                AddressLine2      = billingAddress.AddressLine2,
                ContactName       = billingAddress.ContactName,
                CountryId         = billingAddress.CountryId,
                StateOrProvinceId = billingAddress.StateOrProvinceId,
                DistrictId        = billingAddress.DistrictId,
                City    = billingAddress.City,
                ZipCode = billingAddress.ZipCode,
                Phone   = billingAddress.Phone
            };

            var orderShippingAddress = new OrderAddress()
            {
                AddressLine1      = shippingAddress.AddressLine1,
                AddressLine2      = shippingAddress.AddressLine2,
                ContactName       = shippingAddress.ContactName,
                CountryId         = shippingAddress.CountryId,
                StateOrProvinceId = shippingAddress.StateOrProvinceId,
                DistrictId        = shippingAddress.DistrictId,
                City    = shippingAddress.City,
                ZipCode = shippingAddress.ZipCode,
                Phone   = shippingAddress.Phone
            };

            var order = new Order
            {
                CreatedOn        = DateTimeOffset.Now,
                CreatedById      = user.Id,
                BillingAddress   = orderBillingAddress,
                ShippingAddress  = orderShippingAddress,
                PaymentMethod    = paymentMethod,
                PaymentFeeAmount = paymentFeeAmount
            };

            foreach (var cartItem in cart.Items)
            {
                if (cartItem.Product.StockTrackingIsEnabled && cartItem.Product.StockQuantity < cartItem.Quantity)
                {
                    return(Result.Fail <Order>($"There are only {cartItem.Product.StockQuantity} items available for {cartItem.Product.Name}"));
                }

                var taxPercent = await _taxService.GetTaxPercent(cartItem.Product.TaxClassId, shippingAddress.CountryId, shippingAddress.StateOrProvinceId, shippingAddress.ZipCode);

                var productPrice = cartItem.Product.Price;
                if (cart.IsProductPriceIncludeTax)
                {
                    productPrice = productPrice / (1 + (taxPercent / 100));
                }

                var orderItem = new OrderItem
                {
                    Product      = cartItem.Product,
                    ProductPrice = productPrice,
                    Quantity     = cartItem.Quantity,
                    TaxPercent   = taxPercent,
                    TaxAmount    = cartItem.Quantity * (productPrice * taxPercent / 100)
                };

                var discountedItem = checkingDiscountResult.DiscountedProducts.FirstOrDefault(x => x.Id == cartItem.ProductId);
                if (discountedItem != null)
                {
                    orderItem.DiscountAmount = discountedItem.DiscountAmount;
                }

                order.AddOrderItem(orderItem);
                if (cartItem.Product.StockTrackingIsEnabled)
                {
                    cartItem.Product.StockQuantity = cartItem.Product.StockQuantity - cartItem.Quantity;
                }
            }

            order.OrderStatus          = orderStatus;
            order.CouponCode           = checkingDiscountResult.CouponCode;
            order.CouponRuleName       = cart.CouponRuleName;
            order.DiscountAmount       = checkingDiscountResult.DiscountAmount;
            order.ShippingFeeAmount    = shippingMethod.Price;
            order.ShippingMethod       = shippingMethod.Name;
            order.TaxAmount            = order.OrderItems.Sum(x => x.TaxAmount);
            order.SubTotal             = order.OrderItems.Sum(x => x.ProductPrice * x.Quantity);
            order.SubTotalWithDiscount = order.SubTotal - checkingDiscountResult.DiscountAmount;
            order.OrderTotal           = order.SubTotal + order.TaxAmount + order.ShippingFeeAmount + order.PaymentFeeAmount - order.DiscountAmount;
            _orderRepository.Add(order);

            cart.IsActive = false;

            var vendorIds = cart.Items.Where(x => x.Product.VendorId.HasValue).Select(x => x.Product.VendorId.Value).Distinct();

            if (vendorIds.Any())
            {
                order.IsMasterOrder = true;
            }

            foreach (var vendorId in vendorIds)
            {
                var subOrder = new Order
                {
                    CreatedOn       = DateTimeOffset.Now,
                    CreatedById     = user.Id,
                    BillingAddress  = orderBillingAddress,
                    ShippingAddress = orderShippingAddress,
                    VendorId        = vendorId,
                    Parent          = order
                };

                foreach (var cartItem in cart.Items.Where(x => x.Product.VendorId == vendorId))
                {
                    var taxPercent = await _taxService.GetTaxPercent(cartItem.Product.TaxClassId, shippingAddress.CountryId, shippingAddress.StateOrProvinceId, shippingAddress.ZipCode);

                    var productPrice = cartItem.Product.Price;
                    if (cart.IsProductPriceIncludeTax)
                    {
                        productPrice = productPrice / (1 + (taxPercent / 100));
                    }

                    var orderItem = new OrderItem
                    {
                        Product      = cartItem.Product,
                        ProductPrice = productPrice,
                        Quantity     = cartItem.Quantity,
                        TaxPercent   = taxPercent,
                        TaxAmount    = cartItem.Quantity * (productPrice * taxPercent / 100)
                    };

                    if (cart.IsProductPriceIncludeTax)
                    {
                        orderItem.ProductPrice = orderItem.ProductPrice - orderItem.TaxAmount;
                    }

                    subOrder.AddOrderItem(orderItem);
                }

                subOrder.SubTotal   = subOrder.OrderItems.Sum(x => x.ProductPrice * x.Quantity);
                subOrder.TaxAmount  = subOrder.OrderItems.Sum(x => x.TaxAmount);
                subOrder.OrderTotal = subOrder.SubTotal + subOrder.TaxAmount + subOrder.ShippingFeeAmount - subOrder.DiscountAmount;
                _orderRepository.Add(subOrder);
            }

            using (var transaction = _orderRepository.BeginTransaction())
            {
                _orderRepository.SaveChanges();
                _couponService.AddCouponUsage(user.Id, order.Id, checkingDiscountResult);
                _orderRepository.SaveChanges();
                transaction.Commit();
            }

            // await _orderEmailService.SendEmailToUser(user, order);
            return(Result.Ok(order));
        }
        public async Task CreateOrder(User user, Address billingAddress, Address shippingAddress)
        {
            var cart = _cartRepository
                       .Query()
                       .Include(c => c.Items).ThenInclude(x => x.Product)
                       .Where(x => x.UserId == user.Id && x.IsActive).FirstOrDefault();

            if (cart == null)
            {
                throw new ApplicationException($"Cart of user {user.Id} can no be found");
            }

            decimal discount = 0;

            if (!string.IsNullOrWhiteSpace(cart.CouponCode))
            {
                var cartInfoForCoupon = new CartInfoForCoupon
                {
                    Items = cart.Items.Select(x => new CartItemForCoupon {
                        ProductId = x.ProductId, Quantity = x.Quantity
                    }).ToList()
                };
                var couponValidationResult = await _couponService.Validate(cart.CouponCode, cartInfoForCoupon);

                if (couponValidationResult.Succeeded)
                {
                    discount = couponValidationResult.DiscountAmount;
                    _couponService.AddCouponUsage(user.Id, couponValidationResult.CouponId);
                }
                else
                {
                    throw new ApplicationException($"Unable to apply coupon {cart.CouponCode}. {couponValidationResult.ErrorMessage}");
                }
            }

            var orderBillingAddress = new OrderAddress()
            {
                AddressLine1      = billingAddress.AddressLine1,
                ContactName       = billingAddress.ContactName,
                CountryId         = billingAddress.CountryId,
                StateOrProvinceId = billingAddress.StateOrProvinceId,
                DistrictId        = billingAddress.DistrictId,
                Phone             = billingAddress.Phone
            };

            var orderShippingAddress = new OrderAddress()
            {
                AddressLine1      = shippingAddress.AddressLine1,
                ContactName       = shippingAddress.ContactName,
                CountryId         = shippingAddress.CountryId,
                StateOrProvinceId = shippingAddress.StateOrProvinceId,
                DistrictId        = shippingAddress.DistrictId,
                Phone             = shippingAddress.Phone
            };

            var order = new Order
            {
                CreatedOn       = DateTimeOffset.Now,
                CreatedById     = user.Id,
                BillingAddress  = orderBillingAddress,
                ShippingAddress = orderShippingAddress
            };

            foreach (var cartItem in cart.Items)
            {
                var orderItem = new OrderItem
                {
                    Product      = cartItem.Product,
                    ProductPrice = cartItem.Product.Price,
                    Quantity     = cartItem.Quantity
                };
                order.AddOrderItem(orderItem);
            }

            order.CouponCode           = cart.CouponCode;
            order.CouponRuleName       = cart.CouponRuleName;
            order.Discount             = discount;
            order.SubTotal             = order.OrderItems.Sum(x => x.ProductPrice * x.Quantity);
            order.SubTotalWithDiscount = order.SubTotal - discount;
            _orderRepository.Add(order);

            cart.IsActive = false;

            var vendorIds = cart.Items.Where(x => x.Product.VendorId.HasValue).Select(x => x.Product.VendorId.Value).Distinct();

            foreach (var vendorId in vendorIds)
            {
                var subOrder = new Order
                {
                    CreatedOn       = DateTimeOffset.Now,
                    CreatedById     = user.Id,
                    BillingAddress  = orderBillingAddress,
                    ShippingAddress = orderShippingAddress,
                    VendorId        = vendorId,
                    Parent          = order
                };

                foreach (var cartItem in cart.Items.Where(x => x.Product.VendorId == vendorId))
                {
                    var orderItem = new OrderItem
                    {
                        Product      = cartItem.Product,
                        ProductPrice = cartItem.Product.Price,
                        Quantity     = cartItem.Quantity
                    };

                    subOrder.AddOrderItem(orderItem);
                }

                subOrder.SubTotal = subOrder.OrderItems.Sum(x => x.ProductPrice * x.Quantity);
                _orderRepository.Add(subOrder);
            }

            _orderRepository.SaveChange();
        }
Exemple #4
0
        public async Task <Result <Order> > CreateOrder(long cartId, string paymentMethod, decimal paymentFeeAmount, string shippingMethodName, Address billingAddress, Address shippingAddress, OrderStatus orderStatus = OrderStatus.New)
        {
            var cart = _cartRepository
                       .Query()
                       .Include(c => c.Items).ThenInclude(x => x.Product)
                       .Where(x => x.Id == cartId).FirstOrDefault();

            if (cart == null)
            {
                return(Result.Fail <Order>($"Cart id {cartId} cannot be found"));
            }

            var checkingDiscountResult = await CheckForDiscountIfAny(cart);

            if (!checkingDiscountResult.Succeeded)
            {
                return(Result.Fail <Order>(checkingDiscountResult.ErrorMessage));
            }

            var validateShippingMethodResult = await ValidateShippingMethod(shippingMethodName, shippingAddress, cart);

            if (!validateShippingMethodResult.Success)
            {
                return(Result.Fail <Order>(validateShippingMethodResult.Error));
            }

            var shippingMethod = validateShippingMethodResult.Value;

            var orderBillingAddress = new OrderAddress()
            {
                AddressLine1      = billingAddress.AddressLine1,
                AddressLine2      = billingAddress.AddressLine2,
                ContactName       = billingAddress.ContactName,
                CountryId         = billingAddress.CountryId,
                StateOrProvinceId = billingAddress.StateOrProvinceId,
                DistrictId        = billingAddress.DistrictId,
                City    = billingAddress.City,
                ZipCode = billingAddress.ZipCode,
                Phone   = billingAddress.Phone
            };

            var orderShippingAddress = new OrderAddress()
            {
                AddressLine1      = shippingAddress.AddressLine1,
                AddressLine2      = shippingAddress.AddressLine2,
                ContactName       = shippingAddress.ContactName,
                CountryId         = shippingAddress.CountryId,
                StateOrProvinceId = shippingAddress.StateOrProvinceId,
                DistrictId        = shippingAddress.DistrictId,
                City    = shippingAddress.City,
                ZipCode = shippingAddress.ZipCode,
                Phone   = shippingAddress.Phone
            };

            var order = new Order
            {
                CustomerId        = cart.CustomerId,
                CreatedOn         = DateTimeOffset.Now,
                CreatedById       = cart.CreatedById,
                LatestUpdatedOn   = DateTimeOffset.Now,
                LatestUpdatedById = cart.CreatedById,
                BillingAddress    = orderBillingAddress,
                ShippingAddress   = orderShippingAddress,
                PaymentMethod     = paymentMethod,
                PaymentFeeAmount  = paymentFeeAmount
            };

            foreach (var cartItem in cart.Items)
            {
                //codigo origen, necesairio revisar validaciones para la compra tipo stock etc
                //if (!cartItem.Product.IsAllowToOrder || !cartItem.Product.IsPublished || cartItem.Product.IsDeleted)
                //{
                //    return Result.Fail<Order>($"The product {cartItem.Product.Name} is not available any more");
                //}

                //if (cartItem.Product.StockTrackingIsEnabled && cartItem.Product.StockQuantity < cartItem.Quantity)
                //{
                //    return Result.Fail<Order>($"There are only {cartItem.Product.StockQuantity} items available for {cartItem.Product.Name}");
                //}

                var taxPercent = await _taxService.GetTaxPercent(cartItem.Product.TaxClassId, shippingAddress.CountryId, shippingAddress.StateOrProvinceId, shippingAddress.ZipCode);

                var productPrice = cartItem.Product.Price;
                if (cart.IsProductPriceIncludeTax)
                {
                    productPrice = productPrice / (1 + (taxPercent / 100));
                }

                var orderItem = new OrderItem
                {
                    Product      = cartItem.Product,
                    ProductPrice = productPrice,
                    Quantity     = cartItem.Quantity,
                    TaxPercent   = taxPercent,
                    TaxAmount    = cartItem.Quantity * (productPrice * taxPercent / 100)
                };

                var discountedItem = checkingDiscountResult.DiscountedProducts.FirstOrDefault(x => x.Id == cartItem.ProductId);
                if (discountedItem != null)
                {
                    orderItem.DiscountAmount = discountedItem.DiscountAmount;
                }

                order.AddOrderItem(orderItem);
                if (cartItem.Product.StockTrackingIsEnabled)
                {
                    cartItem.Product.StockQuantity = cartItem.Product.StockQuantity - cartItem.Quantity;
                }
            }

            order.OrderStatus          = orderStatus;
            order.OrderNote            = cart.OrderNote;
            order.CouponCode           = checkingDiscountResult.CouponCode;
            order.CouponRuleName       = cart.CouponRuleName;
            order.DiscountAmount       = checkingDiscountResult.DiscountAmount;
            order.ShippingFeeAmount    = shippingMethod.Price;
            order.ShippingMethod       = shippingMethod.Name;
            order.TaxAmount            = order.OrderItems.Sum(x => x.TaxAmount);
            order.SubTotal             = order.OrderItems.Sum(x => x.ProductPrice * x.Quantity);
            order.SubTotalWithDiscount = order.SubTotal - checkingDiscountResult.DiscountAmount;
            order.OrderTotal           = order.SubTotal + order.TaxAmount + order.ShippingFeeAmount + order.PaymentFeeAmount - order.DiscountAmount;
            _orderRepository.Add(order);

            cart.IsActive = false;

            var vendorIds = cart.Items.Where(x => x.Product.VendorId.HasValue).Select(x => x.Product.VendorId.Value).Distinct();

            if (vendorIds.Any())
            {
                order.IsMasterOrder = true;
            }

            IList <Order> subOrders = new List <Order>();

            foreach (var vendorId in vendorIds)
            {
                var subOrder = new Order
                {
                    CustomerId        = cart.CustomerId,
                    CreatedOn         = DateTimeOffset.Now,
                    CreatedById       = cart.CreatedById,
                    LatestUpdatedOn   = DateTimeOffset.Now,
                    LatestUpdatedById = cart.CreatedById,
                    BillingAddress    = orderBillingAddress,
                    ShippingAddress   = orderShippingAddress,
                    VendorId          = vendorId,
                    Parent            = order
                };

                foreach (var cartItem in cart.Items.Where(x => x.Product.VendorId == vendorId))
                {
                    var taxPercent = await _taxService.GetTaxPercent(cartItem.Product.TaxClassId, shippingAddress.CountryId, shippingAddress.StateOrProvinceId, shippingAddress.ZipCode);

                    var productPrice = cartItem.Product.Price;
                    if (cart.IsProductPriceIncludeTax)
                    {
                        productPrice = productPrice / (1 + (taxPercent / 100));
                    }

                    var orderItem = new OrderItem
                    {
                        Product      = cartItem.Product,
                        ProductPrice = productPrice,
                        Quantity     = cartItem.Quantity,
                        TaxPercent   = taxPercent,
                        TaxAmount    = cartItem.Quantity * (productPrice * taxPercent / 100)
                    };

                    if (cart.IsProductPriceIncludeTax)
                    {
                        orderItem.ProductPrice = orderItem.ProductPrice - orderItem.TaxAmount;
                    }

                    subOrder.AddOrderItem(orderItem);
                }

                subOrder.SubTotal   = subOrder.OrderItems.Sum(x => x.ProductPrice * x.Quantity);
                subOrder.TaxAmount  = subOrder.OrderItems.Sum(x => x.TaxAmount);
                subOrder.OrderTotal = subOrder.SubTotal + subOrder.TaxAmount + subOrder.ShippingFeeAmount - subOrder.DiscountAmount;
                _orderRepository.Add(subOrder);
                subOrders.Add(subOrder);
            }

            using (var transaction = _orderRepository.BeginTransaction())
            {
                _orderRepository.SaveChanges();
                await PublishOrderCreatedEvent(order);

                foreach (var subOrder in subOrders)
                {
                    await PublishOrderCreatedEvent(subOrder);
                }

                _couponService.AddCouponUsage(cart.CustomerId, order.Id, checkingDiscountResult);
                _orderRepository.SaveChanges();
                transaction.Commit();
            }
            //aqui tenemos que borrar el carrito

            return(Result.Ok(order));
        }