This is actually a ported version of this post on drupal 6 with some more advance features.

Describing the problem

We have a customer's request that requires us to create a simple user points conssumption system agaist a list of N products.
The user gets points manually (only by admin) in a loyalty reward session.
The user can consume his/her points by selecting one or more products from a product gallery.

It looks like as an e-shop solution but the users can use points instead of money.

Modules used

The modules that I used are the following:
cck (most of this module has moved into the Drupal 7 core), ctools, entity, flag, insert, libraries, oauth, rules, rules_better_message (depreciated, no longer supported), services, token, userpoints, views
In addition, I suppose that the theme is the default drupal 7 theme: 'Bartik'.

Steps for the implementation

The steps that I follow to implement this simple project are the following:

1. Create a new Content Type

I will create the Items Gallery by adding a new Content Type (say 'Store Item') from 'Home » Administration » Structure » Content types » Basic page' and press 'Add Content type'.
Go to 'Manage Fields' and:
1. Remove the default Body field.
2. Add a new custom field named 'ImageItem' of field type 'Image' and widget 'Image'. Check the Required checkbox since this field is mandatory. This is the image of the item of our item gallery. Here you can also set some other features, as the maximum or minimum image resolution, define the default image, etc. I leave this with their default values just to simplify this tutorial. You can of course set them according to your needs. Save your settings!
3. Add a new custom field named 'Photo Caption' of field type 'Text' and widget 'Text field'. Check the Required checkbox since this field is mandatory too. This is the image title of the item of our item gallery. Enter a 'size of textfield' to 60. Save your settings!
4. Add a new custom field named 'Price' of field type 'Integer' and widget 'Text field'. Check the Required checkbox since this field is mandatory too. This is the price in 'points' of the item of our item gallery.
Save our new 'Store Item' content type. You can set here the minimum and maximum allowable price. In my case I set 1 and 999 respectively. Save your settings!
You can now (as admin) select 'add content' from the Navigation Menu and add some new items (or products if you like!).

2. Create a Flag that a user can use to choose an Item

We will create a new Flag (Home » Administration » Structure then 'Add Flag') that will allow a registered user to flag a selected content of type 'Item Store'. In addition, after selecting item the system will prompt user to enter a quantity for the selected content.
The settings will be the following:
Title: Purchase
Global flag : LEAVE UNCHECK
Flag link text *: Flag this item
Flag link description: Flag
Flagged message : Checked!
Unflag link text *: [CHECKED] Unflag this item
Unflag link description : Unflag
Unflagged message : Unchecked!

Roles that may use this flag : CHECK THE BOXES FLAG/UNFLAG OF authenticated user

Unflag not allowed text: flagged

Bundles: CHECK THE Store Item ONLY

... LEAVE DEFAULT VALUES... TILL

Link type : SELECT RADIO Confirmation form

Flag confirmation message *:
Are you sure you want to flag this content?

Unflag confirmation message *:
Are you sure you want to unflag this content?

SAVE THIS FLAG!! ;)
then edit the new flag again and select 'MANAGE FIELDS'
Add a new Label 'Qty' with field type 'INTEGER' and WIDGET 'Text Field'.
Edit this new label and enter:
Minimum:1
Maximum:999 (this is the maximum order quantity in my case)
and
Default Value:1
Save your changes.
Please note that when parameters are not referenced supposed to retain their default values.
From now on, on any new content of type 'Store Item' any registered user can flag it select quantity and/or unflag it.

3. Show the Gallery

To show the Gallery to the sites front page we need to create a view. A view named 'Item Callery' that will display all contents of type 'Store Item' (we created at step 1)
To be more specific, our view will have the following settings:

----- COLUMN I of VIEW
Title
Title: Item Gallery

Format
Format: Grid | Settings ==>> I SET THE NUMBER OF COLUMNS TO 4 in Settings.
Show: Fields | Settings
open

Fields
Content: Title
Content: ImageItem
Content: Photo Caption
Content: Price
(flag) Flags: Flagged (Flagged)
(flag) Flagging: Qty (Flagged Qty)

Filter criteria
Content: Published (Yes)
Content: Type (= Store Item)

Sort criteria
Content: Post date (desc)

----- COLUMN II of VIEW

Page settings
Path: /item-gallery
Menu: Normal: Item Gallery ===>> THE GALLERY WILL BE DISPLAYED IN A NEW TAB ON FRONT PAGE
Access: Role | Multiple roles

Footer
-
Pager
-
Use pager: Full | Paged, 10 items
More link: No

----- COLUMN III of VIEW
Advanced
Contextual filters

Relationships
Flags: purchase (by current user) ===>> HERE I JOIN THE CURRENT ITEM WITH THE CURRENT USER TO GET SELECTION INFO

No results behavior
Exposed form
Exposed form in block: No

Exposed form style: Basic | Settings

Other
Machine Name: page
Comment: No comment
Use AJAX: No
Hide attachments in summary: No
Hide contextual links: No
Use aggregation: No
Query settings: Settings
Field Language: Current user's language
Caching: None
CSS class: None
Theme: Information

At the end our site will be shown as:
ItemsGallery

4. Business Logic

We will define some logic on each user action of flagging and unflagging. The corresponding actions will be implemented via the 'Rules' module on 'Home » Administration » Configuration » Workflow' Tab Rules. In addition, some will be implemented through the module 'Execute custom PHP code;'.

Business Rule 1: Flag an item

When the user flags an item the system must first check if the user has enough points and if yes then decrease his/her points by (Item.Price * Qty).
The above will be implemented in drupal, with two rules:

Drupal Rule I: 'Check User Points' (with Weight: -5)
Event:
A node has been flagged, under "Purchase"
Conditions:
1. Entity is of bundle, Parameter: Entity: [flagging], Entity type: Flagging, Entity bundle: Purchase
2. Entity is of bundle, Parameter: Entity: [flagged-node], Entity type: Node, Entity bundle: Store Item
3. Execute custom PHP code:
if ([flagging-user:points] < ([flagged-node:field-price] * [flagging:field-qty]) ) {return TRUE;}
Actions:
1.Unflag a Node
Parameter:
Flag: Purchase, Node: [flagged-node],
User on whose behalf to flag: [flagging_user],
Skip permission check: false
2.Calculate a value
Parameter:
Input value 1: [flagged-node:field-price],
Operator: ( * ),
Input value 2: [flagging:field-qty]
Provides variables: OrderedPoints (ordered_points)
3.Show a message on the site
Parameter:
Message: Ops!! Order canceled. You need [ordered-points:value] points (i.e. price: [flagged-node:field-price]points X [flagging:field-qty]qty) to order the [flagged-node:title].
Message type: Error

NOTE: Please note the Conditions 1 and 2. Without them it is not possible to access the extra custom fields 'Price' and 'Qty' defined in 'Store Item' content type and flag 'Purchase' respectively.

Drupal Rule II: 'Flag Item' (with Weight: 0)
Event:
A node has been flagged, under "Purchase"
Conditions:
1.Entity is of bundle
Parameter: Entity: [flagging], Entity type: Flagging, Entity bundle: Purchase
2. Entity is of bundle
Parameter: Entity: [flagged-node], Entity type: Node, Entity bundle: Store Item
Actions:
1.Calculate a value
Parameter: Input value 1: [flagged-node:field-price], Operator: ( * ), Input value 2: [flagging:field-qty]
Provides variables: Calc_PriceTimesQty (calc_pricetimesqty)
2.Calculate a value
Parameter: Input value 1: [calc-pricetimesqty], Operator: ( * ), Input value 2: -1
Provides variables: PointsToSubtract (points_to_subtract)
3. Grant points to a user
Parameter: User: [flagging-user], Points: [points-to-subtract], Points category: General, Entity: [flagged-node], Description: Decrease because of Flagging, Operation: Remove, Moderate: Automatically approved

Business Rule 2: Unflag an item

When the user unflags an item the system must return back the previously consumed points.
The above will be implemented in drupal, with one more rule:

Drupal Rule III: 'Unlag Item' (with Weight: 5)
Event:
A node has been flagged, under "Purchase"
Conditions:
1.Entity is of bundle
Parameter: Entity: [flagging], Entity type: Flagging, Entity bundle: Purchase
2. Entity is of bundle
Parameter: Entity: [flagged-node], Entity type: Node, Entity bundle: Store Item
Actions:
1.Calculate a value
Parameter: Input value 1: [flagged-node:field-price], Operator: ( * ), Input value 2: [flagging:field-qty]
Provides variables: Calc_PriceTimesQty (calc_pricetimesqty)
2.Calculate a value
Parameter: Input value 1: [calc-pricetimesqty],
Operator: ( * ),
Input value 2: 1
Provides variables: PointsToSubtract (points_to_subtract)
3. Grant points to a user
Parameter: User: [flagging-user], Points: [points-to-subtract], Points category: General, Entity: [flagged-node], Description: Decrease because of Flagging, Operation: Remove, Moderate: Automatically approved

Conclusion

The above are only the basic steps need to be implemented for a simple project like this. Of course there are many more actions left out such as reports (Orders per user, Total Orders) Batch User Points update, etc. Actually, such actions are beyond the scope of this little tutorial.
Finally, I would like to say that I am almost sure that many of the functionality shown here can be implemented in many different ways. This is also the joy of drupal.
And...Oh, I almost forget it: I apologize for some bad or strange implemented actions (if you see any), since this is my 2nd week with drupal... ;)

Keep Open Sourcing Guys!

AttachmentSize
Items' Gallery238.42 KB