如何从 Hybris 店面的购物车生成多个订单?
Posted
技术标签:
【中文标题】如何从 Hybris 店面的购物车生成多个订单?【英文标题】:How to generate multiple orders from cart in Hybris storefront? 【发布时间】:2018-04-24 04:59:41 【问题描述】:我正在使用 Hybris 6.3,我们为 B2B 实施生成了一个模块,我需要根据购物车中的产品、账单地址、付款、交货等必须共享的情况将购物车内容分成不同的订单相同的参数。
根据我们从客户那里收集到的要求,我们得出结论,应用寄售策略不是我们在这里所需要的,因为它处理一个订单并将其拆分用于运输和交付目的,相反,我们客户的需求是不同的产品在购物车中按一组共享属性进行分组,并为每组产品生成一个订单。
到目前为止,我已经确定了店面扩展中负责下订单的类,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 和方法 getCartForCodeAndCurrentUser 收到一个必须包含 CartModel 的 CommerceSaveCartParameter,如何生成该对象的实例以在 CommerceSaveCartParameter 中设置?
【问题讨论】:
【参考方案1】:此功能的常用方法是使用 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);
如果您确实需要克隆订单,可以自定义SubmitOrderStrategy
、DefaultOrderService
并使用CloneAbstractOrderStrategy
【讨论】:
寄售不是我们这里需要的,购物车中的商品需要按照我们业务逻辑中定义的标准进行分组,并为每组具有相同标准的商品生成订单,我需要将购物车中的商品拆分为不同的订单,而不是将订单拆分为寄售。 你为什么如此执着于克隆订单?拆分成货物正是你应该在这里做的。您可以非常灵活地定义如何拆分订单的标准。它不仅仅用于交付模式或仓库目的。 购物车中的每组商品都需要生成一个订单,而不是克隆它 @UrielArvizu :您应该只使用寄售拆分。它将帮助您使事情变得更容易。您可以编写自定义策略,根据购物车中的产品、帐单地址、付款、交货等将您的订单拆分为寄售。 问题是,寄售和订单不是一回事,订单从我们的客户发送到 ECC,寄售直接从 ItemModel 继承,并且缺少订单所做的信息,加上 ECC 然后发送iDocs with Orders,所以这是不使用寄售的主要原因。【参考方案2】:我认为您需要使用多个购物车。当用户点击结帐按钮时,您可以创建列表中的新购物车,然后将其从购物车中删除并进行处理。因为购物车的计算量很大,如果你不分成两个购物车,优惠券和规则可能会因为整个产品而给客户额外的费用。
【讨论】:
我没有使用过多个购物车,每个购物车会生成一个单独的订单吗?你有文档的链接吗? 找到 this link 并且我想我可以从显示给用户的主购物车创建购物车,每个购物车都填充了按共享标准分组的条目,但还没有找到如何将条目添加到这个购物车的实例,有什么建议吗? @UrielArvizu 有 cartService 用于将商品添加到购物车。您需要开发在购物车之间移动物品。 但是我需要生成一个 CartModel 来传递给 saveCart 的 CommerceSaveCartParameter,对吧?知道如何创建一个实例吗? 我检查了DefaultCartService,确实有你提到的方法但是它接收到一个CartModel,我怎样才能生成新的CartModel实例?【参考方案3】:我们有一个非常相似的要求。我们的策略是使用之前建议的 SplittingService,并覆盖 CloneAbstractOrderStrategy 以将寄售转换为 OrderModel(或 SubOrderModel)。这可能很复杂,因为您必须正确管理订单的计算等,但可以使用这种方法来实现。
【讨论】:
【参考方案4】:最后我发现我的方法从一开始就完全错误,不应该做订单拆分,既不生成多个购物车也不使用寄售,这两个都是错误的选择。
由于要求将多个订单发送到 ERP,而在我的客户案例中,DataHub 是负责执行此操作的,因此需要扩展的两个扩展是:saporderexchange、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;
然后我必须用我自己的 customaporderexchangeb2b 扩展扩展 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 中的映射,我不得不将添加的属性添加到 raw 和 canonical 的行中,最后我覆盖了要发送的 iDoc 的目标定义所以我在规范中映射的属性被用来代替标准映射。
现在你会说,生成的 Hybris 订单怎么样?由于我们显示的订单是从 ERP 而非 Hybris 数据库中检索的,因此该订单不会显示在店面中。
【讨论】:
以上是关于如何从 Hybris 店面的购物车生成多个订单?的主要内容,如果未能解决你的问题,请参考以下文章
SAP CX (HYBRIS) : 如何从保存的购物车中删除已删除的产品