I talked with bojanz from Commerce Guys about my idea on buying userpoints with Commerce and he suggested that this should be possible by just using Rules.

I tried it, and it does work. However, setting up the rule is not exactly trivial (it requires a rule component and various conditions to verify the necessary fields exist), so I exported my configuration as a feature.

The feature contains currently:
- A Points product product type
- That has a field called field_userpoints, which is a simple integer field
- Rules configuration that grants the amount of points entered into that field of a product when the order is paid.

It works, but I am still thinking that it might make sense to provide a custom userpoints field, that would allow to enter the amount of points + the category. It would however make the rules integration harder I guess. Or at least we'd have to provide a custom rules action to get the points from the product.

Comments

sonictruth’s picture

This sounds great and I'd love to see such a thing get off the ground. I'm having a few issues though. I installed the patch but I'm getting this error:

Notice: Undefined index: commerce_product_type in features_admin_components() (line 501 of /Users/josh/Sites/livethemer.com/sites/all/modules/features/features.admin.inc).

I'm pretty sure it's because there is no commerce_product_type available to make a feature with. Is there some other module that enables Features integration for Commerce? or is this something that Commerce should do out of the box?

thanks

berdir’s picture

You are probably missing http://drupal.org/project/commerce_features.

The feature should depend on that, I'll fix that in the next version.

sonictruth’s picture

That would be it ;) thanks

berdir’s picture

Note that this is just a proof of concept that was quickly clicked together.

Any feedback would be welcome.

kclarkson’s picture

Status: Needs review » Reviewed & tested by the community

@Berdir,

I just tested this patch and it works great !!! Thanks for doing this.

The only confusing part was during the Points Product creation that "druplicons" were the amount "userpoints", they are purchasing on this points product.

After I took a second look I actually like the term druplicons :)

liupascal’s picture

Hey sorry i haven't included this patch in the release yet. I'm trying to keep it as simple as possible right now for code review and full project application. Will be applied right after validation.

rfay’s picture

@liupascal Don't forget that with git you can put things in other branches; it will not affect your application at all. Just make clear in your application what branch is to be reviewed.

berdir’s picture

Status: Reviewed & tested by the community » Needs review

No need to hurry.

The druplicoins confusion is exactly one of the things that I want to fix before this is commited.

The reason for that is that I have renamed Points to Druplicoins to test the points branding feature of Userpoints on my local test setup.

I want this to support that feature too and also be translatable before commiting it. I need to investigate if this is possible with Features or if we want to expose a custom userpoints field for example (which wouldn't necessarly need to live here, could also be a part of userpoints.module or another project).

pcambra’s picture

Version: » 7.x-1.x-dev

I can confirm what Berdir comments in #2, commerce_features should be included as a dependency, this now happens automatically as #1286512: Add commerce_features as a dependency

rfay’s picture

Here's a refresh of the OP patch. It adds commerce_features as a dependency, changes the package to Commerce (contrib) and removes the version number, all irrelevant things.

This works for me.

Coyote’s picture

Forgive me if I'm missing something.

I've just installed the patch by rfay.

I created a points product, assigned it a price of zero, points (druplicon) value of one added it to my cart, and checked out.

Checkout appeared to complete properly, but no points were awarded to the account.

There appears to be an active checkout rule for adding points from a product, but nothing happened.

Have I left out a step somewhere?

Coyote’s picture

Never mind. Silly me - it's looking for the Druplicons term in the taxonomy, which I forgot to add in, despite the prior discussion which suggested that would be necessary!

greggles’s picture

it's looking for the Druplicons term in the taxonomy, which I forgot to add in, despite the prior discussion which suggested that would be necessary!

Seems like this could be in README.txt and maybe a hook_requirements? I won't mark needs work for that alone.

berdir’s picture

@greggles: Sure, that would be one thing. However, this module shouldn't hardcode the points names or that it uses a specific category - Instead, the category should be configurable and it should build upon the built-in branding features of Userpoints.

Doing that would however require to create a special field type that can automatically uses the correct, branded names in the UI and allow to configure the category for which the points are.

greggles’s picture

When choosing between "something that can be committed and provide value right now, but require extra configuration" and "something which requires extra dev work which may or may not happen" I strongly suggest maintainers go for the commit and push the remaining bits to a follow-up patch.

unimarkt’s picture

StatusFileSize
new67.87 KB

Isn't it easy to fix with Rules? (Perhap my solution is too easy.. ) But:

Just added a product with SKU "PROD-3" for 30USD and
added the rule in the picture..

berdir’s picture

The patch is a feature that does built on top of Rules as well but additionally to your rule does a) provide a field (on a special product type) which allows to enter the amount of points that a product is worth which prevents you from having to set up multiple rules and b) also works when you buy the product multiple times in a single order.

mxa055’s picture

I noticed that the component "Add points from product" does not account for line item quantity. So if I make a product with say 10 points and add 3 of them in my cart, after completing the order I only get 10 points instead of 30. I tried modifying the component by calculating the actual value of user points each line item should provide by multiplying line-item:quantity with line-item:commerce-product:field-userpoints, but unfortunately this value is not accessible inside the "Grant points to a user" action.

Any ideas for a fix?

webdrips’s picture

@mxa055, ever find a solution?

berdir’s picture

Should be as simple as adding an additional action to the tasks that multiples the price with the line item quantity and then uses that for the userpoints action.

Rc1585’s picture

Berdir can you please expand on this.

I created an action that multiplies the commerce order quantity by "1" so I get the total quantity for the product.

The problem I have is when I create an action "grant userpoints to a user" i am forced to enter a number into the field "how many points would you like to add or remove". How do you suggest changing the number of points being added/removed to not reflect a manually input number but a number that is based on the product quantity?

Thanks!

berdir’s picture

Switch to data selection (button below) and select your variable?

Rc1585’s picture

Thanks, I've tried switching to data selector but the variable isn't showing up. Just to confirm, what should the variable be?

berdir’s picture

Whatever you said it to be before :) Provide an export of your rule and I'll have a look.

Rc1585’s picture

It may be that I installed the patch wrong.

What is the easiest way to install the patch you've created?

Rc1585’s picture

What file within the commerce userpoints folder should I patch?

somimi’s picture

Slightly off-topic, but I've been trying for days to use Rules to grant points to users when they purchase points - except I'm using Ubercart. Any help with this would be mightily appreciated - I can't seem to figure out how to access the CCK integer field I've created in the Product node for points amount to purchase, and I'm truly out of ideas.

dgastudio’s picture

Simple and working rule

replace 'coin' with your 'money' product type:

{ "rules_buy_userpoints" : {
    "LABEL" : "Buy userpoints",
    "PLUGIN" : "reaction rule",
    "REQUIRES" : [ "commerce_order", "php", "userpoints_rules", "commerce_checkout" ],
    "ON" : [ "commerce_checkout_complete" ],
    "IF" : [
      { "commerce_order_contains_product" : {
          "commerce_order" : [ "commerce_order" ],
          "product_id" : "coin",
          "operator" : "\u003E=",
          "value" : "1"
        }
      }
    ],
    "DO" : [
      { "userpoints_action_grant_points" : {
          "user" : [ "commerce-order:owner" ],
          "points" : {
            "select" : "commerce-order:order-id",
            "php" : { "code" : "$order =commerce_order_load($value);\r\n$wrapper = entity_metadata_wrapper(\u0027commerce_order\u0027, $order);\r\n$line_items = $wrapper-\u003Ecommerce_line_items;\r\n$quantity = commerce_line_items_quantity($line_items, commerce_product_line_item_types(\u0027coin\u0027));\r\nreturn $quantity;" }
          },
          "tid" : "0",
          "entity" : [ "" ],
          "operation" : "Userpoints purchased",
          "display" : 1,
          "moderate" : "approved"
        }
      }
    ]
  }
}
zdean’s picture

#28 works for me. Thanks, @kervi!

dready2011’s picture

As a reply to #18, the rule not taking qauntity field into account:

After struggling for a while, I think the reason that you do not get access to the line-item:quantity field, is that it is not of type integer.
I was able to multiply the number of druplicons with the lineitem:quantity field in the following way.

step 1:
Under actions, add an action of type 'convert datatype' and convert [line-item:quantity] to int. Give some name for the variable.
Move this action to the top.
Step 2:
Add another action of type 'Calculate a value'. As Input Value 1 choose the variable declared in step 1. Choose * as operator and line-item:commerce-product:field-userpoints as Input Value 2. Choose a name for the variable.
Move this one below the convert datatype action.
Step 3:
In action 'grant points to a user', use the variable declared in step 2 for the Points data selector.

Who knows it might be useful for someone, here my exported rule

{ "rules_hobo_commerce_add_points_from_product" : {
    "LABEL" : "Add points from product",
    "PLUGIN" : "rule",
    "REQUIRES" : [ "rules", "userpoints_rules" ],
    "USES VARIABLES" : {
      "line_item" : { "label" : "Line Item", "type" : "commerce_line_item" },
      "order" : { "label" : "Oder", "type" : "commerce_order" }
    },
    "IF" : [
      { "entity_has_field" : { "entity" : [ "line-item" ], "field" : "commerce_product" } },
      { "entity_has_field" : {
          "entity" : [ "line-item:commerce-product" ],
          "field" : "field_userpoints"
        }
      },
      { "node_is_of_type" : {
          "node" : [ "order:owner:og-node:0" ],
          "type" : { "value" : { "agentur" : "agentur" } }
        }
      }
    ],
    "DO" : [
      { "data_convert" : {
          "USING" : { "type" : "integer", "value" : [ "line-item:quantity" ] },
          "PROVIDE" : { "conversion_result" : { "qty_int" : "Quantity as Int" } }
        }
      },
      { "data_calc" : {
          "USING" : {
            "input_1" : [ "qty-int" ],
            "op" : "*",
            "input_2" : [ "line-item:commerce-product:field-userpoints" ]
          },
          "PROVIDE" : { "result" : { "numcreditslineitem" : "Number of Credits for a lineitem" } }
        }
      },
      { "userpoints_action_grant_points" : {
          "user" : [ "order:owner" ],
          "points" : [ "numcreditslineitem" ],
          "tid" : "0",
          "entity" : [ "order" ],
          "description" : "Credits bought",
          "operation" : "commerce_userpoints_buy",
          "reference" : "Order [line-item:order-id]",
          "display" : 1,
          "moderate" : "default"
        }
      }
    ]
  }
}
John Ching’s picture

Issue summary: View changes
StatusFileSize
new119.22 KB
new123.43 KB
new124.32 KB
new114.62 KB
new124.88 KB

I have just been though painstaking 3-4 days (pain.. lots of pain) trying let users buy points on my site, that takes the Quantity of the items in the shopping cart into calculation. The advises above all didn't work for me, maybe because they are all so outdated already. I have finally done it and I am going to share the steps in detail here, so that others won't have to go through the same amount of paiiinn that I went through.

Step 1: Event. Create an Event "Completing the checkout process"

Step 2: Conditions. Create "Order contains a particular product". Data selector = commerce order. Product SKU = BuyCredits (whatever you have named your product-type SKU). Operator is >=. Quantity 1

Step 3a: Actions. Convert Data Type. Target Type = Integer. Value To Convert = commerce-order:commerce-order-total:amount. Conversion Variable name = conversion_result.

Step 3b: Actions. Calculate a Value. Data Selector = conversion result (result of step 3a). Operator = (*). Input Value 2 Value = 0.01 (eg. if 1 Point = USD1). Variable Name = result.

Step 3c: Actions. Grant Points to a user. User Data Selector = site:current-user. Points Data Selector = result (result of step3b). Points Category = General. Operation Value = Buy Points (or any other name to describe this item). Moderate = Use the site default.

FYI I am using the latest modules as of this date Drupal 7.39, commerce-7.x-1.x-dev, ctools-7.x-1.x-dev, views-7.x-3.x-dev, Userpoints 7.x-1.1+0-dev, Userpoints rules integration 7.x-1.1+0-dev, Commerce Userpoints 7.x-1.x-dev.

socialnicheguru’s picture

Edit:

what is the patch in #10 for?

paean99’s picture

what is the patch in #10 for?

It makes some corrections to @Berdir original patch (It was automatically hidden because of new files added on others comments, i think).
@Berdir patch:

"Adds a product type, field and the corresponding rules to allow buying userpoints through Rules"

So after applying the patch you will have to enable the new feature to test it out.

Here are the dependencies (of @Berdir patch, see the changes on #10 by @rfay for more):

+dependencies[] = "commerce_cart"
+dependencies[] = "commerce_payment"
+dependencies[] = "commerce_product_ui"
+dependencies[] = "features"
+dependencies[] = "number"
+dependencies[] = "userpoints_rules"

socialnicheguru’s picture

Ok. so this new patch is similar to this sandbox module: https://www.drupal.org/sandbox/thomjjames/1515550

paean99’s picture

Thanks for the link, i didn't know about it.

They have some similarities in what they try to accomplish, but they do it in different ways.

The sandboxes is a module that:

Provides a new Rules action called "Grant points to a user based on quantity of items in an order", which will read how many of a given product type (which is selectable) are within an order and grant that many points to a given user.

So one just has to create a new rules to see the new action.
I don't think it depends on 'Commerce userpoints', but just on the normal commerce and userpoints modules.

While the patch is just a feature (use the Feature module) that shows how one can do a similar thing with the normal userpoints rules without new code.

That is, if my memory is not failing. I used it some time ago. ;)

dalegrebey’s picture

Sell User Points using Drupal 7 Commerce

#28 Worked for me. To clarify, I:

  1. Copied the rule to my IDE
  2. Changed the word "coin" to match both my product type and product sku called "cred"
  3. Set the price of each Cred to $0.01 penny.
  4. _altered (see below) the quantity field to allow a quantity greater than 9,999

What that does, in effect, is allows a user to Add a User Points product to the shopping cart, then set the quantity of how many User Points they want to buy, calculates the total (I did 1 User Point = 1 penny) and allows them to checkout. On successful checkout, it grants the User the quantity of User Points they selected and charges their card accordingly.

The default commerce max quantity only allows you to have 4 characters, i.e., quantity of 9,999 max. I also overrode this to allow users to buy, for example, 20,000 User Points. That code is listed below.

#28 RULE

{ "rules_buy_userpoints" : {
    "LABEL" : "Buy userpoints",
    "PLUGIN" : "reaction rule",
    "REQUIRES" : [ "commerce_order", "php", "userpoints_rules", "commerce_checkout" ],
    "ON" : [ "commerce_checkout_complete" ],
    "IF" : [
      { "commerce_order_contains_product" : {
          "commerce_order" : [ "commerce_order" ],
          "product_id" : "coin",
          "operator" : "\u003E=",
          "value" : "1"
        }
      }
    ],
    "DO" : [
      { "userpoints_action_grant_points" : {
          "user" : [ "commerce-order:owner" ],
          "points" : {
            "select" : "commerce-order:order-id",
            "php" : { "code" : "$order =commerce_order_load($value);\r\n$wrapper = entity_metadata_wrapper(\u0027commerce_order\u0027, $order);\r\n$line_items = $wrapper-\u003Ecommerce_line_items;\r\n$quantity = commerce_line_items_quantity($line_items, commerce_product_line_item_types(\u0027coin\u0027));\r\nreturn $quantity;" }
          },
          "tid" : "0",
          "entity" : [ "" ],
          "operation" : "Userpoints purchased",
          "display" : 1,
          "moderate" : "approved"
        }
      }
    ]
  }
}

ALTER

function commerce_line_item_field_widget_form_alter() {
  $element['line_items'][$line_item_id]['quantity'] = array(
    '#type' => 'textfield', 
    '#datatype' => 'integer', 
    '#default_value' => $quantity, 
    '#size' => 6, 
    '#maxlength' => max(6, strlen($quantity)),
  );
}