【问题标题】:Drupal Commerce Line Items: alter the price?Drupal Commerce Line Items:更改价格?
【发布时间】:2012-11-21 11:10:31
【问题描述】:

我必须将一些自定义金额的订单项添加到我的购物车中。 商务产品以 price = 0 保存,我的模块计算价格并将订单项添加到购物车/订单,但我不明白如何以编程方式设置价格。

我已阅读有关使用规则的信息,但我需要我的模块能够设置/更改价格,无需调用规则。

我尝试过使用实体包装器,我尝试更改使用 commerce_product_line_item_new() 创建的行项目,但没有任何结果,当行项目进入购物车时始终具有原始产品价格(在我的情况下为 0)。

如何以编程方式更改订单项价格?

到目前为止,我的代码如下所示:

// For debugging, this function is called by hook_menu()
function mymodule_test($product_id)
{
    global $user;
    $user = user_load($user->uid);

    $order = commerce_cart_order_load($user->uid);
    $order_wrapper = entity_metadata_wrapper('commerce_order', $order);

    $product = commerce_product_load($product_id);

    $line_item = commerce_product_line_item_new(
            $product,
            1,
            0,
            array(
            ),
            'cover'
    );

    $line_item_wrapper = entity_metadata_wrapper("commerce_line_item", $line_item);

    $line_item_wrapper->commerce_unit_price->data = commerce_price_component_add(
            $line_item_wrapper->commerce_unit_price->value(),
            'base_price',
            array(
                            'amount' => 1234,
                            'currency_code' => 'EUR',
                            'data' => array(),
            ),
            TRUE
    );

    $insert_line_item = commerce_cart_product_add($user->uid, $line_item_wrapper->value(), FALSE);

    return 'done';
}

奇怪的是,我试图修改 commerce/modules/line_item/commerce_line_item.rules.inc 中的 commerce_line_item_unit_price_amount() 的代码,但是这个测试:

<?php
    global $user;
    $product = commerce_product_load(4); // my commerce product for test

    $line_item = commerce_product_line_item_new(
        $product,
        1,
        0,
        array(
        ),
        'cover' // I do have this line_items type
    );

    // manually set amount and component name
    $amount = 1234;
    $component_name = 'base_price'; // tryed with discount, nothing change

    $wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
    $unit_price = commerce_price_wrapper_value($wrapper, 'commerce_unit_price', TRUE);

    // Calculate the updated amount and create a price array representing the
    // difference between it and the current amount.
    $current_amount = $unit_price['amount'];
    $updated_amount = commerce_round(COMMERCE_ROUND_HALF_UP, $amount);

    $difference = array(
        'amount' => $updated_amount - $current_amount, 
        'currency_code' => $unit_price['currency_code'], 
        'data' => array(),
    );

    // Set the amount of the unit price and add the difference as a component.
    $wrapper->commerce_unit_price->amount = $updated_amount;

    $wrapper->commerce_unit_price->data = commerce_price_component_add(
        $wrapper->commerce_unit_price->value(), 
        $component_name, 
        $difference, 
        TRUE
    );

    $insert_line_item = commerce_cart_product_add($user->uid, $line_item, FALSE);
?>

仍然失败,line_item 进入购物车,但使用参考产品的原价。

有什么想法吗?

【问题讨论】:

  • 你没有保存你的包装器......这可能是问题所在(即$line_item_wrapper-&gt;save();)
  • @Clive 我想我也试过了,但让我再试一次以防万一
  • 哦,你还需要保存$order_wrapper(几个月前我在做类似的事情时得到了我)
  • @Clive 尝试过,仍然无法正常工作。我在之前(以及之后,以防万一)commerce_cart_product_add 添加了$line_item_wrapper-&gt;save(); $order_wrapper-&gt;save();,但没有任何改变...我没有收到任何错误,行项目进入购物车,但以原始产品的价格!
  • 嗯,顺便说一句,我遇到了一个奇怪的行为,如果我在 order_wrapper 上调用 save(),则订单项根本不会进入购物车(但仍然没有错误)

标签: drupal drupal-7 drupal-commerce


【解决方案1】:

对于那些不想使用规则并希望直接更改价格的人。这是我的解决方案:

// Alter the price in list and single product page.
function my_module_commerce_product_calculate_sell_price_line_item_alter($line_item){

    $price = 100; //1 dollar
    $line_item->commerce_unit_price[LANGUAGE_NONE]['0']['amount'] = $price;

}

// Alter the price in cart & order.
function my_module_commerce_cart_line_item_refresh($line_item, $order_wrapper){

    $price = 100; //1 dollar
    $line_item->commerce_unit_price[LANGUAGE_NONE]['0']['amount'] = $price;
    // Alter the base_price component.
    $line_item->commerce_unit_price[LANGUAGE_NONE]['0']['data']['components']['0']['price']['amount'] = $price;

}

【讨论】:

  • 嗨蒂姆,上面的hook 不是从我的模块触发的。试过单品页面hook。我正在使用 DC Kickstart。
  • 您还有其他地方可以定价吗?你可以试试kpr($line_item)中的钩子看看是什么样子的。
【解决方案2】:

如果您希望忽略已保存到订单项的任何先前值并根据新金额重新计算总数,则您要查找的函数是 commerce_line_item_rebase_unit_price。

设置新的金额值,然后通过那里运行您的订单项,保存订单项和订单:

$line_item_wrapper->commerce_unit_price->amount = 13;

commerce_line_item_rebase_unit_price($line_item_wrapper->value());

commerce_line_item_save($line_item_wrapper->value());

【讨论】:

  • 在我看来这是最好的答案。我确信在某些情况下 Drupal Commerce 的复杂定价系统非常有用,但在我遇到的用例中,我只想设置价格,我不想必须实现另一个钩子(从而使我的代码更难理解)。
【解决方案3】:

我今天整天都在努力解决这个问题,最终找到了改变订单项价格的正确途径。问题是,即使您成功地将订单项价格更改为自定义值,在下一页刷新购物车时,也会重置订单项以匹配原始产品价格。详情请查看commerce_cart_order_refresh() 函数。每次在页面上加载订单/购物车时都会执行此函数,并且无法绕过它。

事实证明,更改行项目价格的正确方法是使用规则或实现hook_commerce_cart_line_item_refresh() 函数。无论哪种方式,Drupal Commerce 都需要能够在每次加载购物车/订单时应用更改逻辑。

我最终在订单项中创建了一个自定义字段,用于存储我想要的自定义价格值。然后,每当刷新购物车时,我都会使用定价规则将自定义价格值复制到产品价格值。

以下博客文章对解决这个问题非常有帮助。它向您展示了如何将自定义字段添加到订单项类型以及如何设置定价规则以将自定义金额复制到单价。

http://commerceguys.com/blog/using-custom-line-items-provide-donation-feature-drupal-commerce

【讨论】:

  • 感谢分享! Drupal Commerce 功能强大且灵活,但我仍然不明白为什么价格变动如此严格地受规则约束。
  • @MichaelStevens 我已经发布了一个实现此功能的示例。
【解决方案4】:

最近我不得不在 Commerce 中实现一个捐赠表单,但 Commerce Express Checkout 模块不处理自定义订单项。由于这是一笔捐赠(谁在试图搞砸房子?),我觉得将捐赠金额作为快速结帐模块提供的 URL 中的第三个参数传递是合适的。以下是我如何破解模块:

我向路由器添加了一个新条目:

$items['commerce-express-checkout/%/%/%'] = array(
      'title' => 'Express Checkout w/ extra argument',
      // 'page callback' => 'commerce_express_checkout_create_order',
      'page callback' => 'commerce_express_checkout_create_order_extra',
      'page arguments' => array(1, 2, 3),
      'access arguments' => array('access checkout'),
      'type' => MENU_CALLBACK,
  );

我复制并调整了默认回调并添加了“_extra”。请注意,“数据”属性似乎是一个静态变量存储,用于此类情况,并保持订单项的生命周期。

function commerce_express_checkout_create_order_extra($product_id, $token, $amount) {

  if (drupal_hmac_base64($product_id, drupal_get_private_key().drupal_get_hash_salt()) == $token && is_numeric($amount)) {
    global $user;

    $product = commerce_product_load($product_id);

    $product->commerce_price['und'][0]['amount'] = (int)$amount;

    $order = ($user->uid) ? commerce_order_new($user->uid, 'checkout_checkout') : commerce_cart_order_new();

    commerce_order_save($order);

    $price = array('amount' => commerce_round(COMMERCE_ROUND_HALF_UP, $amount), 'currency_code' => commerce_default_currency());

    $line_item = commerce_product_line_item_new($product, 1, $order->order_id);
    $line_item->data = array('und' => array('0' => $price));
    commerce_line_item_save($line_item);

    $order_wrapper = entity_metadata_wrapper('commerce_order', $order);

    $order_wrapper->commerce_line_items[] = $line_item;

    $order->data['type'] = 'commerce_express_checkout_order';

    commerce_order_save($order);

    drupal_goto('checkout/' . $order->order_id);

    return "";
  }

   return "";
}

由于学习曲线和不知道要使用什么功能,这是最棘手的部分:

/**                                                                             
 * Implements hook_commerce_cart_line_item_refresh().                           
 */                                                                             
function commerce_express_checkout_commerce_cart_line_item_refresh($line_item, $order_wrapper) { 
  if ($line_item->commerce_product['und'][0]['line_item_label'] == 'DONATE' || $line_item->commerce_product['und'][0]['product_id'] == '11') {
    $price = array('amount' => commerce_round(COMMERCE_ROUND_HALF_UP, $line_item->data['und'][0]['amount']), 'currency_code' => commerce_default_currency());
    $line_item->commerce_unit_price = array('und' => array('0' => $price));
    $line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
    $line_item_wrapper->commerce_unit_price->data = commerce_price_component_add(
      $line_item_wrapper->commerce_unit_price->value(), 'base_price', $price, TRUE
    );
  }
}

每次修改购物车时,它都会刷新并尝试将购物车中的产品设置为其代码内原型。这对我来说似乎效率也很低,但我可能会遗漏一些东西。

【讨论】:

    【解决方案5】:

    这篇文章为我指明了使用hook_commerce_cart_line_item_refersh() 以编程方式更改drupal 商务订单项的正确方向。然而,这里的一些答案要么是完全错误的,要么是非常低效和草率的。

    这将是在 Drupal Commerce 中更改行项目类型的正确工作解决方案:

    /*  
     * implements hook_commerce_cart_line_item_refresh()
     *  
     */
    
    function MYMODULE_commerce_cart_line_item_refresh($line_item, $order_wrapper){
    
        $line_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
    
        $new_price = 100; //I use a function to calculate the value of $new_price
    
        if(!empty($new_price)){
            $line_wrapper->commerce_unit_price->amount->set($new_price);
            $line_wrapper->save();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-17
      • 2011-09-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多