Shipping fee based on a TV value

If anyone is familiar with the commerce plugin, could they tell me about 2 things :

  1. if there is a way where I can add shipping fee on a product based on a TV value.
  2. to then there to be no shipping cost if they have more than 1 product in the cart.

This is a sample snippet with the logic:

<?php
/**
 * Custom shipping calculator for Commerce
 * Returns £8 if:
 * - There is exactly one ink product (total quantity of inks = 1)
 * - AND that ink product has product_profit < 8
 * Otherwise returns 0 (free shipping).
 */

// Get the cart
$cart = $modx->commerce->getCart();
$items = $cart->getItems();

$totalInkQuantity = 0;
$lowProfitExists  = false;

foreach ($items as $item) {
    // Get the product object (comProduct)
    $product = $item->getProduct();
    if (!$product) {
        continue;
    }

    // Get the linked resource (MODX resource) to access the TV
    $resource = $product->getResource();
    if (!$resource) {
        continue;
    }

    // Retrieve the product_profit TV value
    $profit = $resource->getTVValue('product_profit');

    // If the TV is not equal to -1, we consider this an ink product
    if ($profit !== -1) {
        $quantity = $item->get('quantity');
        $totalInkQuantity += $quantity;

        // Check if this product has low profit (<8)
        if ((float)$profit < 8) {
            $lowProfitExists = true;
        }
    }
}

// Rule 1: If total ink quantity > 1, shipping is free
if ($totalInkQuantity > 1) {
    return 0.00;
}

// Rule 2: If exactly one ink product (total quantity = 1) and it has low profit, charge £8
if ($totalInkQuantity === 1 && $lowProfitExists) {
    return 8.00;
}

// All other cases: free shipping
return 0.00;

Custom shipping methods are powerful in Commerce but because of that also a little complicated the first time.

You need to start building your own module (extension). https://docs.modmore.com/en/Commerce/v1/Developer/Guides/Bootstrapping_a_Module.html

Once you have that, you can extend the comShippingMethod class through the xPDO model in the extension to create your custom shipping method. https://docs.modmore.com/en/Commerce/v1/Developer/Custom_Shipping_Methods.html

Once you have that, you can take your example code and put it in the getPriceForShipment method. I see some minor issues you’d need to fix:

  • It’s $shipment->getItems(), or $order = $shipment->getOrder() and then $order->getItems() to get the items.
  • It’s $product->getTarget(), not $product->getResource().
  • Careful using strict type matching for TV values. Those typically come through as strings, so I suspect your $profit match would not work.