All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.commerce.frontend.internal.cart.CommerceCartResource Maven / Gradle / Ivy

/**
 * SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
 * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
 */

package com.liferay.commerce.frontend.internal.cart;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

import com.liferay.commerce.constants.CommercePriceConstants;
import com.liferay.commerce.constants.CommerceWebKeys;
import com.liferay.commerce.context.CommerceContext;
import com.liferay.commerce.context.CommerceContextFactory;
import com.liferay.commerce.currency.model.CommerceMoney;
import com.liferay.commerce.currency.util.CommercePriceFormatter;
import com.liferay.commerce.discount.CommerceDiscountValue;
import com.liferay.commerce.exception.CommerceOrderValidatorException;
import com.liferay.commerce.frontend.helper.ProductHelper;
import com.liferay.commerce.frontend.internal.cart.model.Cart;
import com.liferay.commerce.frontend.internal.cart.model.Coupon;
import com.liferay.commerce.frontend.internal.cart.model.OrderStatusInfo;
import com.liferay.commerce.frontend.internal.cart.model.Product;
import com.liferay.commerce.frontend.internal.cart.model.Summary;
import com.liferay.commerce.frontend.model.PriceModel;
import com.liferay.commerce.frontend.model.ProductSettingsModel;
import com.liferay.commerce.model.CommerceOrder;
import com.liferay.commerce.model.CommerceOrderItem;
import com.liferay.commerce.order.CommerceOrderHttpHelper;
import com.liferay.commerce.order.CommerceOrderValidatorRegistry;
import com.liferay.commerce.order.CommerceOrderValidatorResult;
import com.liferay.commerce.price.CommerceOrderItemPrice;
import com.liferay.commerce.price.CommerceOrderPrice;
import com.liferay.commerce.price.CommerceOrderPriceCalculation;
import com.liferay.commerce.pricing.constants.CommercePricingConstants;
import com.liferay.commerce.product.model.CommerceChannel;
import com.liferay.commerce.product.service.CommerceChannelLocalService;
import com.liferay.commerce.product.util.CPInstanceHelper;
import com.liferay.commerce.service.CommerceOrderItemService;
import com.liferay.commerce.service.CommerceOrderService;
import com.liferay.commerce.util.CommerceOrderItemQuantityFormatter;
import com.liferay.commerce.util.CommerceUtil;
import com.liferay.petra.string.StringPool;
import com.liferay.portal.kernel.exception.PortalException;
import com.liferay.portal.kernel.language.Language;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.service.ServiceContext;
import com.liferay.portal.kernel.service.ServiceContextFactory;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.LocaleUtil;
import com.liferay.portal.kernel.util.Portal;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.workflow.WorkflowConstants;

import java.math.BigDecimal;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

/**
 * @author Marco Leo
 * @author Alessio Antonio Rendina
 */
@Component(service = CommerceCartResource.class)
public class CommerceCartResource {

	@Path("/order/{orderId}/coupon-code/{couponCode}")
	@POST
	@Produces(MediaType.APPLICATION_JSON)
	public Response applyCouponCode(
		@PathParam("orderId") long commerceOrderId,
		@PathParam("couponCode") String couponCode,
		@Context HttpServletRequest httpServletRequest) {

		Coupon coupon = null;

		try {
			CommerceOrder commerceOrder =
				_commerceOrderService.getCommerceOrder(commerceOrderId);

			CommerceChannel commerceChannel =
				_commerceChannelLocalService.getCommerceChannelByOrderGroupId(
					commerceOrder.getGroupId());

			CommerceContext commerceContext = _commerceContextFactory.create(
				commerceOrder.getCompanyId(), commerceChannel.getGroupId(),
				_portal.getUserId(httpServletRequest),
				commerceOrder.getCommerceOrderId(),
				commerceOrder.getCommerceAccountId());

			_commerceOrderService.applyCouponCode(
				commerceOrder.getCommerceOrderId(), couponCode,
				commerceContext);

			coupon = new Coupon(couponCode);
		}
		catch (Exception exception) {
			_log.error(exception);

			coupon = new Coupon(
				StringUtil.split(exception.getLocalizedMessage()));
		}

		return _getResponse(coupon);
	}

	@Path("/order/{orderId}/coupon-code")
	@POST
	@Produces(MediaType.APPLICATION_JSON)
	public Response removeCouponCode(
		@PathParam("orderId") long commerceOrderId,
		@Context HttpServletRequest httpServletRequest) {

		Coupon coupon = null;

		try {
			CommerceOrder commerceOrder =
				_commerceOrderService.getCommerceOrder(commerceOrderId);

			CommerceChannel commerceChannel =
				_commerceChannelLocalService.getCommerceChannelByOrderGroupId(
					commerceOrder.getGroupId());

			CommerceContext commerceContext = _commerceContextFactory.create(
				commerceOrder.getCompanyId(), commerceChannel.getGroupId(),
				_portal.getUserId(httpServletRequest),
				commerceOrder.getCommerceOrderId(),
				commerceOrder.getCommerceAccountId());

			_commerceOrderService.applyCouponCode(
				commerceOrder.getCommerceOrderId(), null, commerceContext);

			coupon = new Coupon(StringPool.BLANK);
		}
		catch (Exception exception) {
			_log.error(exception);

			coupon = new Coupon(
				StringUtil.split(exception.getLocalizedMessage()));
		}

		return _getResponse(coupon);
	}

	@Path("/cart-item")
	@POST
	@Produces(MediaType.APPLICATION_JSON)
	public Response updateOrderItem(
		@FormParam("groupId") long groupId,
		@FormParam("languageId") String languageId,
		@FormParam("commerceAccountId") long commerceAccountId,
		@FormParam("quantity") String quantity,
		@FormParam("productId") long cpInstanceId,
		@FormParam("options") String options,
		@FormParam("orderId") long orderId,
		@FormParam("unitOfMeasureKey") String unitOfMeasureKey,
		@Context HttpServletRequest httpServletRequest) {

		Cart cart = null;

		try {
			CommerceContext commerceContext = _commerceContextFactory.create(
				_portal.getCompanyId(httpServletRequest),
				_commerceChannelLocalService.
					getCommerceChannelGroupIdBySiteGroupId(groupId),
				_portal.getUserId(httpServletRequest), orderId,
				commerceAccountId);

			httpServletRequest.setAttribute(
				CommerceWebKeys.COMMERCE_CONTEXT, commerceContext);

			CommerceOrder commerceOrder =
				_commerceOrderService.fetchCommerceOrder(orderId);

			if (commerceOrder == null) {
				commerceOrder =
					_commerceOrderHttpHelper.getCurrentCommerceOrder(
						httpServletRequest);
			}

			if (commerceOrder == null) {
				commerceOrder = _commerceOrderHttpHelper.addCommerceOrder(
					httpServletRequest);
			}

			commerceContext = _commerceContextFactory.create(
				_portal.getCompanyId(httpServletRequest),
				commerceOrder.getGroupId(),
				_portal.getUserId(httpServletRequest),
				commerceOrder.getCommerceOrderId(), commerceAccountId);

			httpServletRequest.setAttribute(
				CommerceWebKeys.COMMERCE_CONTEXT, commerceContext);

			ServiceContext serviceContext = ServiceContextFactory.getInstance(
				CommerceOrderItem.class.getName(), httpServletRequest);

			CommerceOrderItem commerceOrderItem =
				_commerceOrderItemService.addOrUpdateCommerceOrderItem(
					commerceOrder.getCommerceOrderId(), cpInstanceId, options,
					_commerceOrderItemQuantityFormatter.parse(
						quantity, LocaleUtil.fromLanguageId(languageId)),
					0, BigDecimal.ZERO, unitOfMeasureKey, commerceContext,
					serviceContext);

			cart = _getCart(
				commerceOrderItem.getCommerceOrderId(),
				_getDetailsURL(commerceOrder, groupId, httpServletRequest),
				LocaleUtil.fromLanguageId(languageId), commerceContext, true);
		}
		catch (Exception exception) {
			if (exception instanceof CommerceOrderValidatorException) {
				cart = new Cart(
					_getCommerceOrderValidatorResultsMessages(
						(CommerceOrderValidatorException)exception));
			}
			else {
				cart = new Cart(
					StringUtil.split(exception.getLocalizedMessage()));
			}
		}

		return _getResponse(cart);
	}

	private Cart _getCart(
			long commerceOrderId, String detailsUrl, Locale locale,
			CommerceContext commerceContext, boolean valid)
		throws Exception {

		CommerceOrder commerceOrder = _commerceOrderService.getCommerceOrder(
			commerceOrderId);

		List product = _getProducts(
			commerceOrder, commerceContext, locale);

		if (valid && product.isEmpty()) {
			valid = false;
		}

		String orderStatusInfoLabel = WorkflowConstants.getStatusLabel(
			commerceOrder.getStatus());

		OrderStatusInfo orderStatusInfo = new OrderStatusInfo(
			commerceOrder.getOrderStatus(), orderStatusInfoLabel,
			_language.get(locale, orderStatusInfoLabel));

		return new Cart(
			detailsUrl, commerceOrderId, product,
			_getSummary(commerceOrder, locale, commerceContext), valid,
			orderStatusInfo);
	}

	private PriceModel _getCommerceOrderItemPriceModel(
			CommerceOrderItem commerceOrderItem,
			CommerceContext commerceContext, Locale locale)
		throws Exception {

		CommerceOrderItemPrice commerceOrderItemPrice =
			_commerceOrderPriceCalculation.getCommerceOrderItemPricePerUnit(
				commerceContext.getCommerceCurrency(), commerceOrderItem);

		return _getPriceModel(
			commerceOrderItemPrice.getUnitPrice(),
			commerceOrderItemPrice.getPromoPrice(),
			commerceOrderItemPrice.getDiscountAmount(),
			commerceOrderItemPrice.getDiscountPercentage(),
			commerceOrderItemPrice.getDiscountPercentageLevel1(),
			commerceOrderItemPrice.getDiscountPercentageLevel2(),
			commerceOrderItemPrice.getDiscountPercentageLevel3(),
			commerceOrderItemPrice.getDiscountPercentageLevel4(),
			commerceOrderItemPrice.getFinalPrice(), locale);
	}

	private String[] _getCommerceOrderValidatorResultsMessages(
		CommerceOrderValidatorException commerceOrderValidatorException) {

		String[] errorMessages = new String[0];

		List commerceOrderValidatorResults =
			commerceOrderValidatorException.getCommerceOrderValidatorResults();

		for (CommerceOrderValidatorResult commerceOrderValidatorResult :
				commerceOrderValidatorResults) {

			if (commerceOrderValidatorResult.hasMessageResult()) {
				errorMessages = ArrayUtil.append(
					errorMessages,
					commerceOrderValidatorResult.getLocalizedMessage());
			}
		}

		return errorMessages;
	}

	private String _getDetailsURL(
			CommerceOrder commerceOrder, long siteGroupId,
			HttpServletRequest httpServletRequest)
		throws PortalException {

		String commerceCartPortletURL =
			_commerceOrderHttpHelper.getCommerceCartPortletURL(
				siteGroupId, httpServletRequest, commerceOrder);

		if (Validator.isNull(commerceCartPortletURL)) {
			return _portal.getHomeURL(httpServletRequest);
		}

		return commerceCartPortletURL;
	}

	private String[] _getErrorMessages(
			Locale locale, CommerceOrderItem commerceOrderItem)
		throws Exception {

		String[] errorMessages = new String[0];

		List commerceOrderValidatorResults =
			_commerceOrderValidatorRegistry.validate(locale, commerceOrderItem);

		for (CommerceOrderValidatorResult commerceOrderValidatorResult :
				commerceOrderValidatorResults) {

			errorMessages = ArrayUtil.append(
				errorMessages,
				commerceOrderValidatorResult.getLocalizedMessage());
		}

		return errorMessages;
	}

	private PriceModel _getPriceModel(
			CommerceMoney unitPriceCommerceMoney,
			CommerceMoney promoPriceCommerceMoney,
			CommerceMoney discountAmountCommerceMoney,
			BigDecimal discountPercentage, BigDecimal discountPercentageLevel1,
			BigDecimal discountPercentageLevel2,
			BigDecimal discountPercentageLevel3,
			BigDecimal discountPercentageLevel4,
			CommerceMoney finalPriceCommerceMoney, Locale locale)
		throws Exception {

		PriceModel priceModel = null;

		if (unitPriceCommerceMoney.isPriceOnApplication()) {
			priceModel = new PriceModel(
				CommercePriceConstants.PRICE_VALUE_PRICE_ON_APPLICATION);
		}
		else {
			priceModel = new PriceModel(unitPriceCommerceMoney.format(locale));
		}

		if (promoPriceCommerceMoney != null) {
			if (promoPriceCommerceMoney.isPriceOnApplication()) {
				priceModel.setPromoPrice(
					CommercePriceConstants.PRICE_VALUE_PRICE_ON_APPLICATION);
			}
			else {
				priceModel.setPromoPrice(
					promoPriceCommerceMoney.format(locale));
			}
		}

		if (discountAmountCommerceMoney == null) {
			return priceModel;
		}

		BigDecimal discountAmount = discountAmountCommerceMoney.getPrice();

		if ((discountAmount == null) ||
			(discountAmount.compareTo(BigDecimal.ZERO) == 0)) {

			return priceModel;
		}

		priceModel.setDiscount(discountAmountCommerceMoney.format(locale));
		priceModel.setDiscountPercentage(
			_commercePriceFormatter.format(discountPercentage, locale));

		BigDecimal level1 = BigDecimal.ZERO;
		BigDecimal level2 = BigDecimal.ZERO;
		BigDecimal level3 = BigDecimal.ZERO;
		BigDecimal level4 = BigDecimal.ZERO;

		if (discountPercentageLevel1 != null) {
			level1 = discountPercentageLevel1;
		}

		if (discountPercentageLevel2 != null) {
			level2 = discountPercentageLevel2;
		}

		if (discountPercentageLevel3 != null) {
			level3 = discountPercentageLevel3;
		}

		if (discountPercentageLevel4 != null) {
			level4 = discountPercentageLevel4;
		}

		String[] discountPercentages = {
			level1.toString(), level2.toString(), level3.toString(),
			level4.toString()
		};

		priceModel.setDiscountPercentages(discountPercentages);

		priceModel.setFinalPrice(finalPriceCommerceMoney.format(locale));

		return priceModel;
	}

	private List _getProducts(
			CommerceOrder commerceOrder, CommerceContext commerceContext,
			Locale locale)
		throws Exception {

		List products = new ArrayList<>();

		List commerceOrderItems =
			commerceOrder.getCommerceOrderItems();

		for (CommerceOrderItem commerceOrderItem : commerceOrderItems) {
			PriceModel priceModel = _getCommerceOrderItemPriceModel(
				commerceOrderItem, commerceContext, locale);

			ProductSettingsModel productSettingsModel =
				_productHelper.getProductSettingsModel(
					commerceOrderItem.getCPDefinitionId());

			BigDecimal quantity = commerceOrderItem.getQuantity();

			Product product = new Product(
				commerceOrderItem.getCommerceOrderItemId(),
				commerceOrderItem.getParentCommerceOrderItemId(),
				commerceOrderItem.getCPInstanceId(),
				commerceOrderItem.getName(locale), priceModel,
				productSettingsModel, quantity.intValue(),
				commerceOrderItem.getSku(),
				_cpInstanceHelper.getCPInstanceThumbnailSrc(
					CommerceUtil.getCommerceAccountId(commerceContext),
					commerceOrderItem.getCPInstanceId()),
				commerceOrderItem.getUnitOfMeasureKey(),
				_getErrorMessages(locale, commerceOrderItem));

			long commerceOptionValueCPDefinitionId =
				commerceOrderItem.getCPDefinitionId();

			if (commerceOrderItem.hasParentCommerceOrderItem()) {
				commerceOptionValueCPDefinitionId =
					commerceOrderItem.
						getParentCommerceOrderItemCPDefinitionId();
			}

			product.setOptions(
				_cpInstanceHelper.getKeyValuePairs(
					commerceOptionValueCPDefinitionId,
					commerceOrderItem.getJson(), locale));

			products.add(product);
		}

		return _groupProductByOrderItemId(products);
	}

	private Response _getResponse(Object object) {
		if (object == null) {
			return Response.status(
				Response.Status.NOT_FOUND
			).build();
		}

		try {
			String json = _OBJECT_MAPPER.writeValueAsString(object);

			return Response.ok(
				json, MediaType.APPLICATION_JSON
			).build();
		}
		catch (JsonProcessingException jsonProcessingException) {
			_log.error(jsonProcessingException);
		}

		return Response.status(
			Response.Status.NOT_FOUND
		).build();
	}

	private Summary _getSummary(
			CommerceOrder commerceOrder, Locale locale,
			CommerceContext commerceContext)
		throws Exception {

		CommerceOrderPrice commerceOrderPrice =
			_commerceOrderPriceCalculation.getCommerceOrderPrice(
				commerceOrder, commerceContext);

		if (commerceOrderPrice == null) {
			return null;
		}

		CommerceMoney subtotalCommerceMoney = commerceOrderPrice.getSubtotal();
		CommerceMoney totalCommerceMoney = commerceOrderPrice.getTotal();

		BigDecimal itemsQuantity =
			_commerceOrderItemService.getCommerceOrderItemsQuantity(
				commerceOrder.getCommerceOrderId());

		CommerceDiscountValue totalCommerceDiscountValue =
			commerceOrderPrice.getTotalDiscountValue();

		CommerceChannel commerceChannel =
			_commerceChannelLocalService.getCommerceChannelByOrderGroupId(
				commerceOrder.getGroupId());

		String priceDisplayType = commerceChannel.getPriceDisplayType();

		if (priceDisplayType.equals(
				CommercePricingConstants.TAX_INCLUDED_IN_PRICE)) {

			subtotalCommerceMoney =
				commerceOrderPrice.getSubtotalWithTaxAmount();
			totalCommerceMoney = commerceOrderPrice.getTotalWithTaxAmount();
			totalCommerceDiscountValue =
				commerceOrderPrice.getTotalDiscountValueWithTaxAmount();
		}

		Summary summary = new Summary(
			subtotalCommerceMoney.format(locale),
			totalCommerceMoney.format(locale), itemsQuantity.intValue());

		if (totalCommerceDiscountValue != null) {
			CommerceMoney discountAmountCommerceMoney =
				totalCommerceDiscountValue.getDiscountAmount();

			summary.setDiscount(discountAmountCommerceMoney.format(locale));
		}

		return summary;
	}

	private List _groupProductByOrderItemId(List products) {
		Map productMap = new HashMap<>();

		for (Product product : products) {
			productMap.put(product.getId(), product);
		}

		for (Product product : products) {
			long parentProductId = product.getParentProductId();

			if (parentProductId == 0) {
				continue;
			}

			Product parent = productMap.get(parentProductId);

			if (parent != null) {
				if (parent.getChildItems() == null) {
					parent.setChildItems(new ArrayList<>());
				}

				List childItems = parent.getChildItems();

				childItems.add(product);

				productMap.remove(product.getId());
			}
		}

		return new ArrayList(productMap.values());
	}

	private static final ObjectMapper _OBJECT_MAPPER = new ObjectMapper() {
		{
			configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);
			disable(SerializationFeature.INDENT_OUTPUT);
		}
	};

	private static final Log _log = LogFactoryUtil.getLog(
		CommerceCartResource.class);

	@Reference
	private CommerceChannelLocalService _commerceChannelLocalService;

	@Reference
	private CommerceContextFactory _commerceContextFactory;

	@Reference
	private CommerceOrderHttpHelper _commerceOrderHttpHelper;

	@Reference
	private CommerceOrderItemQuantityFormatter
		_commerceOrderItemQuantityFormatter;

	@Reference
	private CommerceOrderItemService _commerceOrderItemService;

	@Reference
	private CommerceOrderPriceCalculation _commerceOrderPriceCalculation;

	@Reference
	private CommerceOrderService _commerceOrderService;

	@Reference
	private CommerceOrderValidatorRegistry _commerceOrderValidatorRegistry;

	@Reference
	private CommercePriceFormatter _commercePriceFormatter;

	@Reference
	private CPInstanceHelper _cpInstanceHelper;

	@Reference
	private Language _language;

	@Reference
	private Portal _portal;

	@Reference
	private ProductHelper _productHelper;

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy