Answers.Body: <p><a href="https://craftcommerce.com/docs/order-model" rel="nofollow noreferrer">Commerce_OrderModel</a> has a <a href="https://craftcommerce.com/docs/order-model#getshippingmethod" rel="nofollow noreferrer"><code>getShippingMethod()</code></a> that will return a <code>Commerce_ShippingMethodModel</code> class of the current shipping method, or null if nothing has been set.</p>
  
  <p>If you've already got the order in the template is should be as simple as:</p>
  
  <pre><code>{% if order.getShippingMethod() %}
      Shipping.
  {% else %}
      No shipping.
  {% endif %}
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-04-09T19:29:46.423Z
Answers.Text: As a follow up question, Is there a way to check for this similar thing at the cart level? For example, I have not checked out yet, but all products in my cart have `freeShipping` selected. At this point, I don't know if my whole order qualifies for free shipping so I am checking each line item. Is `cart.totalShippingCost` accurate at this point in the checkout process?
Answers.UserDisplayName: Damon
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-04-09T23:22:50.633Z
Answers.Text: A cart is just an [OrderModel](https://craftcommerce.com/docs/order-model#overview) with its `isCompleted` property set to `false`.
Answers.UserDisplayName: Brad Bell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-04-06T16:56:00.843Z
Answers.LastActivityDate: 2017-04-06T16:56:00.843Z
Answers.UserDisplayName: Brad Bell
Answers.Body: <p>Well, I think somewhere in-between Brad's answer and this is the solution...</p>
  
  <p>I too have a mix of tangible and tangible products on my site. In the CP I have checked the "Free Shipping" checkbox for all non-tangible products when I create them.</p>
  
  <p>Because I eventually <em>will</em> have products that require shipping, I didn't want to completely do away with the shipping screen. Here is what I came up with.</p>
  
  <p><strong>EDIT/UPDATE</strong></p>
  
  <p>After working through this more, I wanted to provide more insight for others who might come across this thread. As always if there is room for improvement, please let me know so it can be updated.</p>
  
  <p><strong>/shop/checkout/addresses/</strong></p>
  
  <pre><code>{% set freeShipping  = false %}
  
  {% for item in cart.lineItems %}
      {% set variant = item.purchasable %}
      {% set product = variant.product %}
  
      {% if product.freeShipping %}
          {% set freeShipping = true %}
      {% else %}
          {% set freeShipping = false %}
      {% endif %}
  {% endfor %}
  
  ...
  
  &lt;form method="post" accept-charset="utf-8"&gt;
  &lt;input type="hidden" name="action" value="commerce/cart/updateCart"&gt;
  
  {% if freeShipping %}
      &lt;input type="hidden" name="redirect" value="shop/checkout/payment"/&gt;
  {% else %}
      &lt;input type="hidden" name="redirect" value="shop/checkout/shipping"/&gt;
  {% endif %}
  
  
  ...
  
  {% if freeShipping %}
      &lt;input type="hidden" name="sameAddress" value="1"&gt;
  {% else %}
      &lt;input type="hidden" name="sameAddress" value="0"&gt;
      &lt;input type="checkbox" name="sameAddress" id="sameAddress"
                                                 checked="checked"&gt;Use same address for shipping
  {% endif %}
  
  
  ...
  
  {% if freeShipping %}
      &lt;button type="submit" class="btn btn-primary"&gt;Continue To Payment&lt;/button&gt;
  {% else %}
      &lt;button type="submit" class="btn btn-primary"&gt;Continue To Shipping&lt;/button&gt;
  {% endif %}
  
  &lt;span&gt;or &lt;a href="{{ url('/shop/cart') }}"&gt;Return to cart&lt;/a&gt;&lt;/span&gt;
  </code></pre>
  
  <p>What I'm doing here is looping through my cart to see if <code>freeShipping</code> has been selected for every product (see above). Later I check the same var and handle the form redirect appropriately. If all products in my cart are set to <code>freeShipping</code> I don't really want to make the user have to enter a shipping address. So I will set the <code>sameAddress</code> for them. This way we still have a shipping address should we need it in the future. Then at the end changing the next button accordingly as well.</p>
  
  <p><strong>/shop/checkout/payment</strong></p>
  
  <pre><code>{% set freeShipping  = false %}
  {% for item in cart.lineItems %}
      {% set variant = item.purchasable %}
      {% set product = variant.product %}
  
      {% if product.freeShipping %}
          {% set freeShipping = true %}
      {% else %}
          {% set freeShipping = false %}
      {% endif %}
  {% endfor %}
  
  
  ...
  
  {% for adjustment in cart.adjustments %}
      &lt;div class="adjustment"&gt;
          {% if adjustment.name == "Free Shipping" %}
              {% if not freeShipping %}
                  &lt;h4&gt;{{ adjustment.name }}&lt;/h4&gt;
                  &lt;p&gt;{{ adjustment.amount|commerceCurrency(cart.currency) }}
                                      ({{ adjustment.description }})&lt;/p&gt;
              {% endif %}
          {% else %}
              &lt;h4&gt;{{ adjustment.name }}&lt;/h4&gt;
              &lt;p&gt;{{ adjustment.amount|commerceCurrency(cart.currency) }}
              ({{ adjustment.description }})&lt;/p&gt;
          {% endif %}
      &lt;/div&gt;
  {% endfor %}
  
  
  ...
  
  
  {% if not cart.shippingMethod %}
      {#
      If the order requires a shipping method be selected, you could redirect back to the shipping page until one is applied to the order.
      {% redirect "shop/checkout/shipping" %}
      You might also want to add a php plugin hook to require
      #}
      {% if freeShipping %}
          {# Shipping not applicable. #}
      {% else %}
          &lt;p&gt;&lt;strong&gt;Shipping&lt;/strong&gt; None selected. &lt;a href="{{ url('shop/checkout/shipping') }}"&gt;
          Choose a shipping method.&lt;/a&gt;
          &lt;/p&gt;
      {% endif %}
  {% endif %}
  </code></pre>
  
  <p>Same thing here, checking for <code>freeShipping</code> on all items. The biggest change here is (purely cosmetic) I didn't want to show "Free Shipping" since we aren't shipping anything. The last part is just updating existing shipping logic to accommodate the free shipping.</p>
  
  <p><strong>/shop/checkout/shipping</strong></p>
  
  <pre><code>{% set freeShipping  = false %}
  
  {% for item in cart.lineItems %}
      {% set variant = item.purchasable %}
      {% set product = variant.product %}
  
      {% if product.freeShipping %}
          {% set freeShipping = true %}
      {% else %}
          {% set freeShipping = false %}
      {% endif %}
  {% endfor %}
  
  ...
  
  {% if freeShipping %}
      &lt;p&gt;None of the items in your cart require shipping.&lt;/p&gt;
      &lt;form method="post" accept-charset="utf-8"&gt;
          &lt;input type="hidden" name="action" value="commerce/cart/updateCart"&gt;
          &lt;input type="hidden" name="redirect" value="shop/checkout/payment"&gt;
          &lt;input type="hidden" name="shippingMethod" value="freeShipping"&gt;
          {{ getCsrfInput() }}
  
          &lt;button type="submit" class="btn btn-primary"&gt;Continue to payment&lt;/button&gt;         
      &lt;/form&gt;
  {% else %}
      &lt;h3&gt;Shipping Method&lt;/h3&gt;
      &lt;p&gt;Select a shipping method below.&lt;/p&gt;
  
      ...
  {% endif %}
  </code></pre>
  
  <p>All we are doing here is checking (again) for <code>freeShipping</code>. If everything qualifies, I only show a button that tells the customer they don't have anything to ship and I send them to the <code>/payment</code> screen. I suppose you <em>could</em> just set a <code>{% redirect %}</code> as well.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-04-10T17:14:27.590Z
Answers.Text: Thanks. I may end up doing something like what you've suggested. I'm still getting my head around the way shipping works...Shipping Categories and Methods and Zones, Oh my...
Answers.UserDisplayName: casey
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-04-10T20:36:28.470Z
Answers.Text: What I struggled with was I wanted to check if the cart had anything that qualified for shipping before actually getting to the shipping screen. So I don't think checking `cart.totalShippingCost` would be accurate since I haven't even gotten to that screen yet. Hope this helps, I'd be interested to know what you come up with!
Answers.UserDisplayName: Damon
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-04-10T02:09:18.210Z
Answers.LastActivityDate: 2017-04-14T15:46:20.637Z
Answers.LastEditDate: 2017-04-14T15:46:20.637Z
Answers.UserDisplayName: Damon
Body: <p>We're selling a mix of both tangible and digital products with Commerce.</p>
  
  <p>If an order doesn't require shipping, I'd rather just take them to directly to the final one page checkout/payment form.</p>
  
  <p>Is there a way to determine this natively or do I need to add a "RequireShipping" field and loop through the line items to see if one exists in the user's cart?</p>
  
Tags: <plugin-craftcommerce><shipping>
Title: Is there a way to determine if an order requires shipping?
ThreadText: # Is there a way to determine if an order requires shipping?
  
  (Asked by: username_0 on 2017-04-06)
  
  We're selling a mix of both tangible and digital products with Commerce.
  
  If an order doesn't require shipping, I'd rather just take them to directly to the final one page checkout/payment form.
  
  Is there a way to determine this natively or do I need to add a "RequireShipping" field and loop through the line items to see if one exists in the user's cart?
  
  **Tags:** plugin-craftcommerce, shipping
  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_1 on 2017-04-06. Score: 1
  
  [Commerce\_OrderModel](https://craftcommerce.com/docs/order-model) has a [`getShippingMethod()`](https://craftcommerce.com/docs/order-model#getshippingmethod) that will return a `Commerce_ShippingMethodModel` class of the current shipping method, or null if nothing has been set.
  
  If you've already got the order in the template is should be as simple as:
  
  ```
  {% if order.getShippingMethod() %}
      Shipping.
  {% else %}
      No shipping.
  {% endif %}
  
  ```
  
  > **Comments:**
  > **username_2**: As a follow up question, Is there a way to check for this similar thing at the cart level? For example, I have not checked out yet, but all products in my cart have `freeShipping` selected. At this point, I don't know if my whole order qualifies for free shipping so I am checking each line item. Is `cart.totalShippingCost` accurate at this point in the checkout process?  
  > **username_1**: A cart is just an [OrderModel](https://craftcommerce.com/docs/order-model#overview) with its `isCompleted` property set to `false`.  
  
  ---
  
  ### Answer by username_2 on 2017-04-10. Score: 1
  
  Well, I think somewhere in-between username_1's answer and this is the solution...
  
  I too have a mix of tangible and tangible products on my site. In the CP I have checked the "Free Shipping" checkbox for all non-tangible products when I create them.
  
  Because I eventually *will* have products that require shipping, I didn't want to completely do away with the shipping screen. Here is what I came up with.
  
  **EDIT/UPDATE**
  
  After working through this more, I wanted to provide more insight for others who might come across this thread. As always if there is room for improvement, please let me know so it can be updated.
  
  **/shop/checkout/addresses/**
  
  ```
  {% set freeShipping  = false %}
  
  {% for item in cart.lineItems %}
      {% set variant = item.purchasable %}
      {% set product = variant.product %}
  
      {% if product.freeShipping %}
          {% set freeShipping = true %}
      {% else %}
          {% set freeShipping = false %}
      {% endif %}
  {% endfor %}
  
  ...
  
  <form method="post" accept-charset="utf-8">
  <input type="hidden" name="action" value="commerce/cart/updateCart">
  
  {% if freeShipping %}
      <input type="hidden" name="redirect" value="shop/checkout/payment"/>
  {% else %}
      <input type="hidden" name="redirect" value="shop/checkout/shipping"/>
  {% endif %}
  
  ...
  
  {% if freeShipping %}
      <input type="hidden" name="sameAddress" value="1">
  {% else %}
      <input type="hidden" name="sameAddress" value="0">
      <input type="checkbox" name="sameAddress" id="sameAddress"
                                                 checked="checked">Use same address for shipping
  {% endif %}
  
  ...
  
  {% if freeShipping %}
      <button type="submit" class="btn btn-primary">Continue To Payment</button>
  {% else %}
      <button type="submit" class="btn btn-primary">Continue To Shipping</button>
  {% endif %}
  
  <span>or <a href="{{ url('/shop/cart') }}">Return to cart</a></span>
  
  ```
  
  What I'm doing here is looping through my cart to see if `freeShipping` has been selected for every product (see above). Later I check the same var and handle the form redirect appropriately. If all products in my cart are set to `freeShipping` I don't really want to make the user have to enter a shipping address. So I will set the `sameAddress` for them. This way we still have a shipping address should we need it in the future. Then at the end changing the next button accordingly as well.
  
  **/shop/checkout/payment**
  
  ```
  {% set freeShipping  = false %}
  {% for item in cart.lineItems %}
      {% set variant = item.purchasable %}
      {% set product = variant.product %}
  
      {% if product.freeShipping %}
          {% set freeShipping = true %}
      {% else %}
          {% set freeShipping = false %}
      {% endif %}
  {% endfor %}
  
  ...
  
  {% for adjustment in cart.adjustments %}
      <div class="adjustment">
          {% if adjustment.name == "Free Shipping" %}
              {% if not freeShipping %}
                  <h4>{{ adjustment.name }}</h4>
                  <p>{{ adjustment.amount|commerceCurrency(cart.currency) }}
                                      ({{ adjustment.description }})</p>
              {% endif %}
          {% else %}
              <h4>{{ adjustment.name }}</h4>
              <p>{{ adjustment.amount|commerceCurrency(cart.currency) }}
              ({{ adjustment.description }})</p>
          {% endif %}
      </div>
  {% endfor %}
  
  ...
  
  {% if not cart.shippingMethod %}
      {#
      If the order requires a shipping method be selected, you could redirect back to the shipping page until one is applied to the order.
      {% redirect "shop/checkout/shipping" %}
      You might also want to add a php plugin hook to require
      #}
      {% if freeShipping %}
          {# Shipping not applicable. #}
      {% else %}
          <p><strong>Shipping</strong> None selected. <a href="{{ url('shop/checkout/shipping') }}">
          Choose a shipping method.</a>
          </p>
      {% endif %}
  {% endif %}
  
  ```
  
  Same thing here, checking for `freeShipping` on all items. The biggest change here is (purely cosmetic) I didn't want to show "Free Shipping" since we aren't shipping anything. The last part is just updating existing shipping logic to accommodate the free shipping.
  
  **/shop/checkout/shipping**
  
  ```
  {% set freeShipping  = false %}
  
  {% for item in cart.lineItems %}
      {% set variant = item.purchasable %}
      {% set product = variant.product %}
  
      {% if product.freeShipping %}
          {% set freeShipping = true %}
      {% else %}
          {% set freeShipping = false %}
      {% endif %}
  {% endfor %}
  
  ...
  
  {% if freeShipping %}
      <p>None of the items in your cart require shipping.</p>
      <form method="post" accept-charset="utf-8">
          <input type="hidden" name="action" value="commerce/cart/updateCart">
          <input type="hidden" name="redirect" value="shop/checkout/payment">
          <input type="hidden" name="shippingMethod" value="freeShipping">
          {{ getCsrfInput() }}
  
          <button type="submit" class="btn btn-primary">Continue to payment</button>         
      </form>
  {% else %}
      <h3>Shipping Method</h3>
      <p>Select a shipping method below.</p>
  
      ...
  {% endif %}
  
  ```
  
  All we are doing here is checking (again) for `freeShipping`. If everything qualifies, I only show a button that tells the customer they don't have anything to ship and I send them to the `/payment` screen. I suppose you *could* just set a `{% redirect %}` as well.
  
  > **Comments:**
  > **username_0**: Thanks. I may end up doing something like what you've suggested. I'm still getting my head around the way shipping works...Shipping Categories and Methods and Zones, Oh my...  
  > **username_2**: What I struggled with was I wanted to check if the cart had anything that qualified for shipping before actually getting to the shipping screen. So I don't think checking `cart.totalShippingCost` would be accurate since I haven't even gotten to that screen yet. Hope this helps, I'd be interested to know what you come up with!  
  
  ---
  
  