如何在Hybris店面中从购物车生成多个订单?

时间:2017-11-10 21:52:39

标签: e-commerce shopping-cart hybris

我正在与Hybris 6.3合作,我们为B2B实施生成了一个模块,我要求根据购物车中的产品,账单地址,付款,交付等将购物车内容分成不同的订单。必须共享相同的参数。

根据我们从客户那里收集到的要求,我们总结应用托运策略并不是我们在这里所需要的,因为它处理一个订单并将其拆分用于运输和交付目的,而不是我们的客户&#39 ; s需要购物车中的不同产品按一组共享属性进行分组,并为每组产品生成订单。

到目前为止,我已经确定负责将订单放在店面扩展名 DefaultCheckoutFacade 中的类,其中包含以下方法:

 @Override
 public OrderData placeOrder() throws InvalidCartException
 {
     final CartModel cartModel = getCart();
     if (cartModel != null)
     {
         if (cartModel.getUser().equals(getCurrentUserForCheckout()) || getCheckoutCustomerStrategy().isAnonymousCheckout())
         {
             beforePlaceOrder(cartModel);
             final OrderModel orderModel = placeOrder(cartModel);
             afterPlaceOrder(cartModel, orderModel);
             if (orderModel != null)
             {
                 return getOrderConverter().convert(orderModel);
             }
         }
     }
     return null;
 }

根据我的理解,我应该覆盖此方法,以根据我的要求中设置的条件生成不同的 CartModel ,并为每个 CartModel 下订单。我修改了 CartModel 类,它的超类 AbstractOrderModel ,我在 getCart()调用之后猜测上面的方法,我只需要修改 CartModel 中的条目,并为我需要放置的每个订单调用方法 placeOrder(),但是它是否允许以这种方式修改 CartModel 对象?

或者,如果我需要将购物车分成不同的订单,我应该以不同的方式处理这个问题吗?有什么东西,比如拥有多个推车,但将它们显示为应该做的一件事情?是否应该在OOTB commercefacades扩展上进行这种修改?有没有办法在我们的模块中的某处扩展它?

修改

我开始阅读Multiple Carts,这似乎是我需要的,但我还没有找到如何将条目保存到已保存的购物车中。在this link我可以看到如何保存购物车,方法 saveCart 返回 CommerceSaveCartResultData 对象, saveCart 和方法< em> getCartForCodeAndCurrentUser 收到一个必须包含CartModel的 CommerceSaveCartParameter ,如何在 CommerceSaveCartParameter 中生成此对象的实例?

4 个答案:

答案 0 :(得分:3)

此功能的常用方法是使用OOTB Order Splitting功能(DefaultOrderSplittingService)将您的订单拆分为OrderEntryGroup。 Hybris文档中的示例:

<bean id="orderSplittingService" class="de.hybris.platform.ordersplitting.impl.DefaultOrderSplittingService">
<property name="modelService" ref="modelService"/>
<property name="consignmentService" ref="consignmentService"/>
<property name="strategiesList">
    <list>
        <ref bean="splitByDeliveryMode"/>
    </list>
</property>

战略实施:

    public class SplitByDeliveryMode extends AbstractSplittingStrategy
{

    @Override
    public Object getGroupingObject(final AbstractOrderEntryModel orderEntry)
    {
        return orderEntry.getDeliveryMode();
    }

    @Override
    public void afterSplitting(final Object groupingObject, final ConsignmentModel createdOne)
    {
        createdOne.setDeliveryMode((DeliveryModeModel) groupingObject);

    }

}

如果您确实需要克隆订单,可以自定义SubmitOrderStrategyDefaultOrderService并使用CloneAbstractOrderStrategy

答案 1 :(得分:2)

I think you need to use multiple cart. When user click checkout button with his wants, you can create new cart with out of list, then remove them from cart and go to process it. Because there is alot of calculation over cart, if you don't split as two cart, coupon and rules can be give to customer extra fees because of whole products.

答案 2 :(得分:2)

我们的要求非常相似。我们的策略是按照之前的建议使用SplittingService,并覆盖CloneAbstractOrderStrategy以将委托转换为OrderModel(或SubOrderModel)。它可能很复杂,因为您必须正确管理订单的计算等,但可以使用此方法实现。

答案 3 :(得分:2)

最后,我发现我的方法从一开始就是完全错误的,订单拆分不应该既不会生成多个推车也不会使用托运,两者都是错误的选择。

由于要求将多个订单发送到ERP,而DataHub是负责在我的客户案例中执行此操作的,因此需要扩展的两个扩展名为: saporderexchange < / strong>, saporderexchangeb2b ysaporderfullfillment

首先我从ysaporderfullfillment模板创建了一个 customsaporderfullfillment 扩展,然后我必须更改 SendOrderToDataHubAction 中的 executeAction 方法来拆分生成的订单来自Hybris,因此符合标准:

@Override
public Transition executeAction(final OrderProcessModel process) throws RetryLaterException
{
    LOG.info("Executing Send Order To DataHub Action");
    final OrderModel order = process.getOrder();
    List<SendToDataHubResult> results = new ArrayList<>();
    List<AbstractOrderEntryModel> entries = order.getEntries();
    Map<String, List<AbstractOrderEntryModel>> sortedEntries = sortEntries(entries);
    final Object[] keyArray = sortedEntries.keySet().toArray();
    LOG.info("Number of Orders to generate: " + keyArray.length);

    for (int i = 0; i < keyArray.length; i++)
    {
        // Clone the order
        String newOrderCode = generateOrderCode();
        LOG.info("Generated Order Code " + newOrderCode);
        OrderModel clonedOrder = getOrderService().clone(null, null, order,
                newOrderCode);
        LOG.info("Cloned order.");
        String key = keyArray[i].toString();
        LOG.info("Setting entries for Key: " + key);
        final List<AbstractOrderEntryModel> entriesForCart = sortedEntries.get(key);
        clonedOrder.setEntries(entriesForCart);
        LOG.info("Sending Order to DataHub");
        sendOrder(clonedOrder, results);
    }

    if (!results.isEmpty() && results.stream().allMatch(result -> result.isSuccess())) {
        LOG.info("All Orders were sent successfully.");
        setOrderStatus(order, ExportStatus.EXPORTED);
        resetEndMessage(process);

        return Transition.OK;

    } else {
        LOG.info("Not all Orders were sent successfully.");
        setOrderStatus(order, ExportStatus.NOTEXPORTED);
        handleRetry(process);

        return Transition.NOK;
    }

}

然后我不得不用我自己的customsaporderexchangeb2b扩展扩展saporderexchangeb2b扩展,我必须创建一个CustomB2BOrderContributor,它将映射到我需要的RawHybrisOrder属性:

@Override
public Set<String> getColumns()
{
    final Set<String> columns = super.getColumns();
    columns.addAll(Arrays.asList(CustomOrderCsvColumns.SALES_ORGANIZATION, CustomOrderCsvColumns.DISTRIBUTION_CHANNEL,
            CustomOrderCsvColumns.DIVISION, CustomOrderCsvColumns.DOCUMENT_TYPE));
    LOG.info("Columns present " + columns.size() + " : " + columns.toString());
    return columns;
}

@Override
public List<Map<String, Object>> createRows(final OrderModel model)
{
    final List<Map<String, Object>> rows = super.createRows(model);
    return enhanceRowsByCustomB2BFields(model, rows);
}

protected List<Map<String, Object>> enhanceRowsByCustomB2BFields(final OrderModel model, final List<Map<String, Object>> rows)
{
    // There is only one row on order level
    final Map<String, Object> row = rows.get(0);
    final String salesArea = ((HelvexProductModel) model.getEntries().get(0).getProduct()).getSalesArea();
    final String[] valuesArray = salesArea.split("_");
    final String salesOrganization = valuesArray[0];
    final String distributionChannel = valuesArray[1];
    final String division = valuesArray[2];
    LOG.info("Enhancing columns of Order " + model.getCode() + " with Sales Organization : " + salesOrganization
            + ", Distribution Channel : " + distributionChannel + ", Division : " + division);
    row.put(CustomOrderCsvColumns.SALES_ORGANIZATION, salesOrganization);
    row.put(CustomOrderCsvColumns.DISTRIBUTION_CHANNEL, distributionChannel);
    row.put(CustomOrderCsvColumns.DIVISION, division);
    row.put(CustomOrderCsvColumns.DOCUMENT_TYPE, Config.getParameter("helvex.org.sales." + salesOrganization));
    row.put(CustomOrderCsvColumns.MOTIVE, sessionService.getAttribute(CustomOrderCsvColumns.MOTIVE));
    LOG.info("Enhanced rows " + row.toString());
    return rows;
}

由于RawHybrisOrder缺少saporder-raw,saporder-canonical和saporder-target中的映射,我不得不添加我在原始和规范中添加到行中的属性,最后我覆盖了要发送的iDoc的目标定义所以我在规范中映射的属性被用来代替标准映射。

现在你会说,Hybris订单产生了什么?由于我们展示的订单是从ERP而不是Hybris数据库中检索出来的,因此不会向店面显示那个。