如何从 Hybris 店面的购物车生成多个订单?
How to generate multiple orders from cart in Hybris storefront?
我正在使用 Hybris 6.3,我们为 B2B 实施生成了一个模块,我需要根据购物车中的产品、账单地址、付款、送货等将购物车内容分成不同的订单必须共享相同的参数。
根据我们从客户那里收集到的要求,我们得出结论,应用寄售策略不是我们在这里所要求的,因为它处理一个订单并将其拆分以用于运输和交付目的,而我们客户的需求是购物车中的不同产品按一组共享属性分组,并为每组产品生成一个订单。
到目前为止,我已经确定 class 负责在店面扩展中下订单,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 下订单。我修改了CartModelclass,超级classAbstractOrderModel,我猜是在[=26=之后]getCart() 在上面的方法中调用,我只需要修改 CartModel 中的条目并调用方法 placeOrder() 对于我需要下的每个订单,但是是否允许以这种方式修改 CartModel 对象?
或者如果我需要将我的购物车分成不同的订单,我应该以不同的方式处理吗?是否像拥有多个购物车但将它们显示为一个应该做的事情?这种修改是否应该在 OOTB commercefacades 扩展上进行?有没有办法在我们的模块中的某个地方扩展它?
编辑
我开始阅读 Multiple Carts and it seems to be what I need, but I haven't found how to save entries to a saved cart. In this link 我可以看到如何保存购物车,方法 saveCart returns a CommerceSaveCartResultData 对象,saveCart 和方法 getCartForCodeAndCurrentUser 都会收到一个 CommerceSaveCartParameter,它必须包含一个 CartModel , 如何生成此对象的实例以在 CommerceSaveCartParameter?
中设置
此功能的常用方法是使用 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
我认为您需要使用多个购物车。当用户点击他想要的结帐按钮时,您可以创建不在列表中的新购物车,然后将它们从购物车中删除并去处理它。因为购物车有很多计算,如果你不拆分成两个购物车,优惠券和规则可以给客户额外的费用,因为整个产品。
我们的要求非常相似。我们的策略是按照之前的建议使用 SplittingService,并覆盖 CloneAbstractOrderStrategy 以将货物转换为 OrderModel(或 SubOrderModel)。它可能很复杂,因为您必须正确管理订单的计算等,但可以使用这种方法来实现。
最后我发现我的做法从一开始就是完全错误的,分单不应该,生成多个购物车和使用托运,都是错误的选择。
由于要求将多个订单发送到 ERP,而 DataHub 是我客户的负责人,因此需要扩展的两个扩展是:saporderexchange, saporderexchangeb2b and ysaporderfullfillment.
首先,我从 ysaporderfullfillment 模板创建了一个 customsaporderfullfillment 扩展,然后我不得不更改 中的 executeAction 方法SendOrderToDataHubAction 根据条件集拆分从 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 数据库中检索的,因此该订单不会显示在店面。
我正在使用 Hybris 6.3,我们为 B2B 实施生成了一个模块,我需要根据购物车中的产品、账单地址、付款、送货等将购物车内容分成不同的订单必须共享相同的参数。
根据我们从客户那里收集到的要求,我们得出结论,应用寄售策略不是我们在这里所要求的,因为它处理一个订单并将其拆分以用于运输和交付目的,而我们客户的需求是购物车中的不同产品按一组共享属性分组,并为每组产品生成一个订单。
到目前为止,我已经确定 class 负责在店面扩展中下订单,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 下订单。我修改了CartModelclass,超级classAbstractOrderModel,我猜是在[=26=之后]getCart() 在上面的方法中调用,我只需要修改 CartModel 中的条目并调用方法 placeOrder() 对于我需要下的每个订单,但是是否允许以这种方式修改 CartModel 对象?
或者如果我需要将我的购物车分成不同的订单,我应该以不同的方式处理吗?是否像拥有多个购物车但将它们显示为一个应该做的事情?这种修改是否应该在 OOTB commercefacades 扩展上进行?有没有办法在我们的模块中的某个地方扩展它?
编辑
我开始阅读 Multiple Carts and it seems to be what I need, but I haven't found how to save entries to a saved cart. In this link 我可以看到如何保存购物车,方法 saveCart returns a CommerceSaveCartResultData 对象,saveCart 和方法 getCartForCodeAndCurrentUser 都会收到一个 CommerceSaveCartParameter,它必须包含一个 CartModel , 如何生成此对象的实例以在 CommerceSaveCartParameter?
中设置此功能的常用方法是使用 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
我认为您需要使用多个购物车。当用户点击他想要的结帐按钮时,您可以创建不在列表中的新购物车,然后将它们从购物车中删除并去处理它。因为购物车有很多计算,如果你不拆分成两个购物车,优惠券和规则可以给客户额外的费用,因为整个产品。
我们的要求非常相似。我们的策略是按照之前的建议使用 SplittingService,并覆盖 CloneAbstractOrderStrategy 以将货物转换为 OrderModel(或 SubOrderModel)。它可能很复杂,因为您必须正确管理订单的计算等,但可以使用这种方法来实现。
最后我发现我的做法从一开始就是完全错误的,分单不应该,生成多个购物车和使用托运,都是错误的选择。
由于要求将多个订单发送到 ERP,而 DataHub 是我客户的负责人,因此需要扩展的两个扩展是:saporderexchange, saporderexchangeb2b and ysaporderfullfillment.
首先,我从 ysaporderfullfillment 模板创建了一个 customsaporderfullfillment 扩展,然后我不得不更改 中的 executeAction 方法SendOrderToDataHubAction 根据条件集拆分从 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 数据库中检索的,因此该订单不会显示在店面。