Skip to content

Commit

Permalink
Issue 8. Automatically update order totals when editing an order
Browse files Browse the repository at this point in the history
  • Loading branch information
RomanovM committed Jul 20, 2016
1 parent 6087aa0 commit 3306ce6
Show file tree
Hide file tree
Showing 24 changed files with 879 additions and 54 deletions.
7 changes: 6 additions & 1 deletion src/Libraries/Nop.Core/Domain/Orders/OrderSettings.cs
Expand Up @@ -24,7 +24,12 @@ public class OrderSettings : ISettings
/// Gets or sets a minimum order total amount
/// </summary>
public decimal MinOrderTotalAmount { get; set; }


/// <summary>
/// Gets or sets a value indicating whether automatically update order totals on editing an order in admin area
/// </summary>
public bool AutoUpdateOrderTotalsOnEditingOrder { get; set; }

/// <summary>
/// Gets or sets a value indicating whether anonymous checkout allowed
/// </summary>
Expand Down
12 changes: 10 additions & 2 deletions src/Libraries/Nop.Services/Catalog/IPriceCalculationService.cs
Expand Up @@ -135,8 +135,16 @@ public partial interface IPriceCalculationService
out decimal discountAmount,
out List<Discount> appliedDiscounts);



/// <summary>
/// Gets the shopping cart item sub total with overriden price
/// </summary>
/// <param name="updatedShoppingCartItem">The updated shopping cart item</param>
/// <param name="price">Overriden price</param>
/// <param name="discountAmount">Applied discount amount</param>
/// <param name="appliedDiscounts">Applied discounts</param>
/// <returns></returns>
decimal GetSubTotalWithOverridenPrice(ShoppingCartItem updatedShoppingCartItem, decimal price,
out decimal discountAmount, out List<Discount> appliedDiscounts);

/// <summary>
/// Gets the product cost (one item)
Expand Down
41 changes: 40 additions & 1 deletion src/Libraries/Nop.Services/Catalog/PriceCalculationService.cs
Expand Up @@ -739,9 +739,48 @@ protected virtual IList<Discount> GetAllowedDiscounts(Product product, Customer
}
return subTotal;
}



/// <summary>
/// Gets the shopping cart item sub total with overriden price
/// </summary>
/// <param name="updatedShoppingCartItem">The updated shopping cart item</param>
/// <param name="price">Overriden price</param>
/// <param name="discountAmount">Applied discount amount</param>
/// <param name="appliedDiscounts">Applied discounts</param>
/// <returns></returns>
public virtual decimal GetSubTotalWithOverridenPrice(ShoppingCartItem updatedShoppingCartItem, decimal price,
out decimal discountAmount, out List<Discount> appliedDiscounts)
{
discountAmount = GetDiscountAmount(updatedShoppingCartItem.Product, updatedShoppingCartItem.Customer, price, out appliedDiscounts);
var priceWithDiscount = price - discountAmount;

if (priceWithDiscount < decimal.Zero)
priceWithDiscount = decimal.Zero;

//rounding
if (_shoppingCartSettings.RoundPricesDuringCalculation)
priceWithDiscount = RoundingHelper.RoundPrice(priceWithDiscount);

//discount
if (appliedDiscounts == null)
appliedDiscounts = new List<Discount>();
if (appliedDiscounts.Count == 1)
{
//we can properly use "MaximumDiscountedQuantity" property only for one discount (not cumulative ones)
var oneAndOnlyDiscount = appliedDiscounts.First();
if (oneAndOnlyDiscount.MaximumDiscountedQuantity.HasValue &&
updatedShoppingCartItem.Quantity > oneAndOnlyDiscount.MaximumDiscountedQuantity.Value)
{
//we cannot apply discount for all shopping cart items
return priceWithDiscount * oneAndOnlyDiscount.MaximumDiscountedQuantity.Value +
price * (updatedShoppingCartItem.Quantity - oneAndOnlyDiscount.MaximumDiscountedQuantity.Value);
}
}

return priceWithDiscount * updatedShoppingCartItem.Quantity;
}

/// <summary>
/// Gets the product cost (one item)
/// </summary>
Expand Down
Expand Up @@ -6013,6 +6013,7 @@ protected virtual void InstallSettings()
MinOrderSubtotalAmount = 0,
MinOrderSubtotalAmountIncludingTax = false,
MinOrderTotalAmount = 0,
AutoUpdateOrderTotalsOnEditingOrder = true,
AnonymousCheckoutAllowed = true,
TermsOfServiceOnShoppingCartPage = true,
TermsOfServiceOnOrderConfirmPage = false,
Expand Down
1 change: 1 addition & 0 deletions src/Libraries/Nop.Services/Nop.Services.csproj
Expand Up @@ -250,6 +250,7 @@
<Compile Include="Logging\ClearLogTask.cs" />
<Compile Include="Media\AzurePictureService.cs" />
<Compile Include="Media\ResizeType.cs" />
<Compile Include="Orders\UpdateOrderParameters.cs" />
<Compile Include="Orders\ICustomNumberFormatter.cs" />
<Compile Include="Orders\IReturnRequestService.cs" />
<Compile Include="Orders\IRewardPointService.cs" />
Expand Down
5 changes: 4 additions & 1 deletion src/Libraries/Nop.Services/Orders/GiftCardService.cs
Expand Up @@ -71,6 +71,7 @@ public virtual GiftCard GetGiftCardById(int giftCardId)
/// Gets all gift cards
/// </summary>
/// <param name="purchasedWithOrderId">Associated order ID; null to load all records</param>
/// <param name="usedWithOrderId">The order ID in which the gift card was used; null to load all records</param>
/// <param name="createdFromUtc">Created date from (UTC); null to load all records</param>
/// <param name="createdToUtc">Created date to (UTC); null to load all records</param>
/// <param name="isGiftCardActivated">Value indicating whether gift card is activated; null to load all records</param>
Expand All @@ -79,7 +80,7 @@ public virtual GiftCard GetGiftCardById(int giftCardId)
/// <param name="pageIndex">Page index</param>
/// <param name="pageSize">Page size</param>
/// <returns>Gift cards</returns>
public virtual IPagedList<GiftCard> GetAllGiftCards(int? purchasedWithOrderId = null,
public virtual IPagedList<GiftCard> GetAllGiftCards(int? purchasedWithOrderId = null, int? usedWithOrderId = null,
DateTime? createdFromUtc = null, DateTime? createdToUtc = null,
bool? isGiftCardActivated = null, string giftCardCouponCode = null,
string recipientName = null,
Expand All @@ -88,6 +89,8 @@ public virtual GiftCard GetGiftCardById(int giftCardId)
var query = _giftCardRepository.Table;
if (purchasedWithOrderId.HasValue)
query = query.Where(gc => gc.PurchasedWithOrderItem != null && gc.PurchasedWithOrderItem.OrderId == purchasedWithOrderId.Value);
if (usedWithOrderId.HasValue)
query = query.Where(gc => gc.GiftCardUsageHistory.Any(history => history.UsedWithOrderId == usedWithOrderId));
if (createdFromUtc.HasValue)
query = query.Where(gc => createdFromUtc.Value <= gc.CreatedOnUtc);
if (createdToUtc.HasValue)
Expand Down
3 changes: 2 additions & 1 deletion src/Libraries/Nop.Services/Orders/IGiftCardService.cs
Expand Up @@ -28,6 +28,7 @@ public partial interface IGiftCardService
/// Gets all gift cards
/// </summary>
/// <param name="purchasedWithOrderId">Associated order ID; null to load all records</param>
/// <param name="usedWithOrderId">The order ID in which the gift card was used; null to load all records</param>
/// <param name="createdFromUtc">Created date from (UTC); null to load all records</param>
/// <param name="createdToUtc">Created date to (UTC); null to load all records</param>
/// <param name="isGiftCardActivated">Value indicating whether gift card is activated; null to load all records</param>
Expand All @@ -36,7 +37,7 @@ public partial interface IGiftCardService
/// <param name="pageIndex">Page index</param>
/// <param name="pageSize">Page size</param>
/// <returns>Gift cards</returns>
IPagedList<GiftCard> GetAllGiftCards(int? purchasedWithOrderId = null,
IPagedList<GiftCard> GetAllGiftCards(int? purchasedWithOrderId = null, int? usedWithOrderId = null,
DateTime? createdFromUtc = null, DateTime? createdToUtc = null,
bool? isGiftCardActivated = null, string giftCardCouponCode = null,
string recipientName = null,
Expand Down
6 changes: 6 additions & 0 deletions src/Libraries/Nop.Services/Orders/IOrderProcessingService.cs
Expand Up @@ -25,6 +25,12 @@ public partial interface IOrderProcessingService
/// <returns>Place order result</returns>
PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentRequest);

/// <summary>
/// Update order totals
/// </summary>
/// <param name="updateOrderParameters">Parameters for the updating order</param>
void UpdateOrderTotals(UpdateOrderParameters updateOrderParameters);

/// <summary>
/// Deletes an order
/// </summary>
Expand Down
Expand Up @@ -65,8 +65,9 @@ public partial interface IOrderTotalCalculationService
/// Gets a value indicating whether shipping is free
/// </summary>
/// <param name="cart">Cart</param>
/// <param name="subTotal">Subtotal amount; pass null to calculate subtotal</param>
/// <returns>A value indicating whether shipping is free</returns>
bool IsFreeShipping(IList<ShoppingCartItem> cart);
bool IsFreeShipping(IList<ShoppingCartItem> cart, decimal? subTotal = null);

/// <summary>
/// Gets shopping cart shipping total
Expand Down Expand Up @@ -161,6 +162,12 @@ public partial interface IOrderTotalCalculationService



/// <summary>
/// Update order totals
/// </summary>
/// <param name="updateOrderParameters">Parameters for the updating order</param>
/// <param name="restoredCart">Shopping cart</param>
void UpdateOrderTotals(UpdateOrderParameters updateOrderParameters, IList<ShoppingCartItem> restoredCart);

/// <summary>
/// Converts existing reward points to amount
Expand Down
6 changes: 6 additions & 0 deletions src/Libraries/Nop.Services/Orders/IRewardPointService.cs
Expand Up @@ -41,5 +41,11 @@ public partial interface IRewardPointService
/// <param name="storeId">Store identifier; pass </param>
/// <returns>Balance</returns>
int GetRewardPointsBalance(int customerId, int storeId);

/// <summary>
/// Updates the reward point history entry
/// </summary>
/// <param name="rewardPointsHistory">Reward point history entry</param>
void UpdateRewardPointsHistoryEntry(RewardPointsHistory rewardPointsHistory);
}
}
112 changes: 112 additions & 0 deletions src/Libraries/Nop.Services/Orders/OrderProcessingService.cs
Expand Up @@ -1395,6 +1395,118 @@ public virtual PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentR
return result;
}

/// <summary>
/// Update order totals
/// </summary>
/// <param name="updateOrderParameters">Parameters for the updating order</param>
public virtual void UpdateOrderTotals(UpdateOrderParameters updateOrderParameters)
{
if (!_orderSettings.AutoUpdateOrderTotalsOnEditingOrder)
return;

var updatedOrder = updateOrderParameters.UpdatedOrder;
var updatedOrderItem = updateOrderParameters.UpdatedOrderItem;

//restore shopping cart from order items
var restoredCart = updatedOrder.OrderItems.Select(orderItem => new ShoppingCartItem
{
Id = orderItem.Id,
AttributesXml = orderItem.AttributesXml,
Customer = updatedOrder.Customer,
Product = orderItem.Product,
Quantity = orderItem.Id == updatedOrderItem.Id ? updateOrderParameters.Quantity : orderItem.Quantity,
RentalEndDateUtc = orderItem.RentalEndDateUtc,
RentalStartDateUtc = orderItem.RentalStartDateUtc,
ShoppingCartType = ShoppingCartType.ShoppingCart,
StoreId = updatedOrder.StoreId
}).ToList();

//get shopping cart item which has been updated
var updatedShoppingCartItem = restoredCart.FirstOrDefault(shoppingCartItem => shoppingCartItem.Id == updatedOrderItem.Id);
var itemDeleted = updatedShoppingCartItem == null;

//validate shopping cart for warnings
updateOrderParameters.Warnings.AddRange(_shoppingCartService.GetShoppingCartWarnings(restoredCart, string.Empty, false));
if (!itemDeleted)
updateOrderParameters.Warnings.AddRange(_shoppingCartService.GetShoppingCartItemWarnings(updatedOrder.Customer, updatedShoppingCartItem.ShoppingCartType,
updatedShoppingCartItem.Product, updatedOrder.StoreId, updatedShoppingCartItem.AttributesXml, updatedShoppingCartItem.CustomerEnteredPrice,
updatedShoppingCartItem.RentalStartDateUtc, updatedShoppingCartItem.RentalEndDateUtc, updatedShoppingCartItem.Quantity, false));

_orderTotalCalculationService.UpdateOrderTotals(updateOrderParameters, restoredCart);

if (updateOrderParameters.PickupPoint != null)
{
updatedOrder.PickUpInStore = true;
updatedOrder.PickupAddress = new Address
{
Address1 = updateOrderParameters.PickupPoint.Address,
City = updateOrderParameters.PickupPoint.City,
Country = _countryService.GetCountryByTwoLetterIsoCode(updateOrderParameters.PickupPoint.CountryCode),
ZipPostalCode = updateOrderParameters.PickupPoint.ZipPostalCode,
CreatedOnUtc = DateTime.UtcNow,
};
updatedOrder.ShippingMethod = string.Format(_localizationService.GetResource("Checkout.PickupPoints.Name"), updateOrderParameters.PickupPoint.Name);
updatedOrder.ShippingRateComputationMethodSystemName = updateOrderParameters.PickupPoint.ProviderSystemName;
}

if (!itemDeleted)
{
updatedOrderItem.ItemWeight = _shippingService.GetShoppingCartItemWeight(updatedShoppingCartItem);
updatedOrderItem.OriginalProductCost = _priceCalculationService.GetProductCost(updatedShoppingCartItem.Product, updatedShoppingCartItem.AttributesXml);
updatedOrderItem.AttributeDescription = _productAttributeFormatter.FormatAttributes(updatedShoppingCartItem.Product,
updatedShoppingCartItem.AttributesXml, updatedOrder.Customer);

//gift cards
if (updatedShoppingCartItem.Product.IsGiftCard)
{
string giftCardRecipientName;
string giftCardRecipientEmail;
string giftCardSenderName;
string giftCardSenderEmail;
string giftCardMessage;
_productAttributeParser.GetGiftCardAttribute(updatedShoppingCartItem.AttributesXml, out giftCardRecipientName,
out giftCardRecipientEmail, out giftCardSenderName, out giftCardSenderEmail, out giftCardMessage);

for (var i = 0; i < updatedShoppingCartItem.Quantity; i++)
{
_giftCardService.InsertGiftCard(new GiftCard
{
GiftCardType = updatedShoppingCartItem.Product.GiftCardType,
PurchasedWithOrderItem = updatedOrderItem,
Amount = updatedShoppingCartItem.Product.OverriddenGiftCardAmount.HasValue ?
updatedShoppingCartItem.Product.OverriddenGiftCardAmount.Value : updatedOrderItem.UnitPriceExclTax,
IsGiftCardActivated = false,
GiftCardCouponCode = _giftCardService.GenerateGiftCardCode(),
RecipientName = giftCardRecipientName,
RecipientEmail = giftCardRecipientEmail,
SenderName = giftCardSenderName,
SenderEmail = giftCardSenderEmail,
Message = giftCardMessage,
IsRecipientNotified = false,
CreatedOnUtc = DateTime.UtcNow
});
}
}
}

_orderService.UpdateOrder(updatedOrder);

//discount usage history
var discountUsageHistoryForOrder = _discountService.GetAllDiscountUsageHistory(null, updatedOrder.Customer.Id, updatedOrder.Id);
foreach (var discount in updateOrderParameters.AppliedDiscounts)
{
if (!discountUsageHistoryForOrder.Where(history => history.DiscountId == discount.Id).Any())
_discountService.InsertDiscountUsageHistory(new DiscountUsageHistory
{
Discount = discount,
Order = updatedOrder,
CreatedOnUtc = DateTime.UtcNow
});
}

CheckOrderStatus(updatedOrder);
}

/// <summary>
/// Deletes an order
/// </summary>
Expand Down

0 comments on commit 3306ce6

Please sign in to comment.