代码之家  ›  专栏  ›  技术社区  ›  Uriel Arvizu

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

  •  4
  • Uriel Arvizu  · 技术社区  · 8 年前

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

    根据我们从客户那里收集到的要求,我们得出结论,应用发货策略并不是我们在这里所需要的,因为这可以处理一个订单,并将其拆分为装运和交付目的,相反,我们客户的需求是将购物车中的不同产品按一组共享属性分组,并为每组产品生成订单。

    到目前为止,我已经确定了负责在店面扩展中下单的类, 默认CheckOutFacade ,其中包含以下方法:

     @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 我可以看看如何保存购物车,方法 存储车 商业存储结果数据 对象,两者 存储车 和方法 接收 CommerceSaveCart参数 其中必须包含CartModel,如何生成该对象的实例以在 CommerceSaveCart参数 ?

    4 回复  |  直到 8 年前
        1
  •  3
  •   Vitaliy    8 年前

    此功能的常见方法是使用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

        2
  •  3
  •   Uriel Arvizu    8 年前

    最后,我发现我的方法从一开始就完全错了,订单分割不应该做,既不应该生成多个购物车,也不应该使用发货,两者都是错误的选择。

    由于要求将多个订单发送到ERP,而DataHub是我的客户负责这项工作的人,因此需要扩展的两个扩展是: saporderexchange , saporderexchangeb2b ysaporderfullfillment

    首先,我创建了一个 扩展,然后我必须更改 执行 中的方法 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中的映射,我不得不将添加的属性添加到raw和canonical中的行中,最后我重写了要发送的iDoc的目标定义,因此使用了我在canonical中映射的属性,而不是标准映射。

    现在你会说,生成的Hybris订单怎么样?由于我们显示的订单是从ERP检索的,而不是从Hybris数据库检索的,因此该订单不会显示在店面上。

        3
  •  2
  •   mkysoft    8 年前

    我认为你需要使用多车。当用户点击他想要的结帐按钮时,你们可以创建一个新的购物车,并将其从购物车中删除,然后进行处理。因为购物车有很多计算,如果你不分成两个购物车,优惠券和规则可以给客户额外的费用,因为整个产品。

        4
  •  2
  •   Guillaume A.    8 年前

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