Hello everybody,

I am just testing commerce for a D7 website that I am currently working on. Now I was asked, if we could implement an auction mode into the store.

I am not a proggy so I don't know how difficult and/or time consuming this might be. There must be others though, too in need for such a feature. On my search for a stand-alone module I had to learn that everybody wants it, but nobody has one.

So are there any plans for such a feature? Could give DC a stand-alone feature on the Drupal module 'market'. ;)

I am willing to test what every comes along, but as I said, can't prog it myself.

Kirsten

CommentFileSizeAuthor
#14 timeout.tar_.gz49.66 KBfarhadhf

Comments

rszrama’s picture

Status: Active » Postponed

I'm sure someone will do it eventually... hopefully they find this issue when they dive in. I'm going to mark this postponed until someone chimes in that they're working on it. For what it's worth, I haven't heard of anyone doing auctions yet but I have heard of multi-seller marketplace being worked on.

slimandslam’s picture

Issue tags: +auction, +reverse auction

It would be nice to have reverse-auction as well as auction. :-)

J

jepster_’s picture

there's the uc_auction module for ubercart. i've used it for a project and it worked without critical bugs. it would be great to find somebody, who will help me in migrating this project to commerce. alone it costs to much time.

farhadhf’s picture

I want to start working on it, but having marketplace functionality along side auctions is important for my project, so that each user can start his/her own auction... Do you think it's better to wait for marketplace functionality to be implemented first?

jepster_’s picture

why waiting? just do it!

farhadhf’s picture

Ok! I've been busy with another project and didn't have much free time to work on this! So, where should I start? I'm new to commerce but I've been writing modules (almost) all summer. Can someone who knows more about commerce help me to get started? Do I need to read Ubercart auction module first?

Thanks :)

wedge’s picture

subscribing

KirstenLangholz’s picture

@farhadhf: I wish I could answer your questions ...

farhadhf’s picture

Let's have a look at what's needed for commerce auction. For the minimum auction functionality We need a new field for bids on the product entity (something like node comments, sorted by bid values) and a timeout field that closes bids on the timeout event is occurred (maybe via rules?) - this will suffice my personal needs for an auction website.
I'll start coding this weekend and put the code here, please come forward and share your ideas so that I can write something that works for you too (or at least is capable of being extended for your needs! :)

Farhad

chefnelone’s picture

Any progress on this?
I'd like to contribute to develop this module as well.

decibel.places’s picture

This is the only piece missing in D7 for a project I am beginning NOW

I'm not sure if I have time in the schedule to develop auction from scratch, but I'm willing to collaborate a couple of days to push it through if it's close!

farhadhf’s picture

Hi
I've (mis)used comments on product display nodes (with a price field added to the comment and body field removed from it) to allow bidding, and implemented template_preprocess_comment_wrapper to sort comments by bid value. I've also wrote a countdown field, that gets a datetime on node creation and closes commenting on the node instance on timeout, updating the product price to highest bid and adding the referenced product to the winner's shopping cart.
I've also created a few pages with views that provide reports and tables for each user about the auctions they have participated in.
using comment module has its problems, (like "comment saved" being showed after bidding which technically is right but not what I want, etc) so I was thinking about writing a simpler field that allows bidding without using comments.
Anyway, If you think that any of this could help you in your project, please let me know so that I can give you the code!

decibel.places’s picture

farhadf

please share your code, here or on Git or contact me

I think we can adapt it to use a custom field, without hijacking the comments, that would make a lasting solution

farhadhf’s picture

StatusFileSize
new49.66 KB

Hi,
I've developed my module with marketplace AND auction in mind, and it needs to be separated into 2 new modules. I'm a little busy right now and don't have the time to do this.
But for the auction specific functionality, you need to:
1. create a product display content type (with "auction_display" machine name) with comments enabled,
2. remove all unrelated comment fields for this content type and add a price field with "field_auction_bid" machine name.
3. put this code in your module :

/**
 * implements hook_comment_presave()
 * Check bid amount of comments on auction display types before saving them.
 */
function MODULENAME_comment_presave($comment)
{
  $node = node_load($comment->nid);
  
  if ( !in_array($node->type, variable_get('auction_types' , array('auction_display'))))
  {
    return;
  }
  $bid = field_get_items('comment', $comment, 'field_auction_bid');
  
  $pid = field_get_items('node', $node, 'field_auction_reference');
  $product = commerce_product_load($pid[0]['product_id']);
  $highest_bid = field_get_items('commerce_product', $product, 'commerce_price');
  
  global $user;
  
  if ($bid[0]['amount'] < $highest_bid[0]['amount'])
  {
    drupal_set_message(t("Your bid amount (@amount) is lower that previous bid! you must enter a higher bid.",
                         array("@amount" => commerce_currency_format($bid[0]['amount'], commerce_default_currency()))),
                       'error');
    // somehow stop the comment from being saved!
    drupal_goto('node/' . $node->nid);
  }
  if ($node->last_comment_uid == $user->uid)
  {
    drupal_set_message(t("Your last bid is the highest bid, you can not bid on this product again until someone posts a higher bid."), 'error');
    // somehow stop the comment from being saved!
    drupal_goto('node/' . $node->nid);
  }
}

/**
 * implements hook_comment_insert()
 * Update product price on comment save when node type is one of auction display node types.
 */
function MODULENAME_comment_insert($comment)
{
  $node = node_load($comment->nid);
  if ($node->type != 'auction_display')
    return ;
  $pid = field_get_items('node', $node, 'field_auction_reference');
  $bid = field_get_items('comment', $comment, 'field_auction_bid');
  $product = commerce_product_load($pid[0]['product_id']);
  $price = field_get_items('product', $product, 'commerce_price');
  // TODO: Change this code so that its not dependent on language code
  
  $product->commerce_price['und'][0] = $bid[0];
  dsm($product);
  commerce_product_save($product);
}

/**
 * Sort comments on auction types by bids.
 * TODO: Remove Reply link.
 */
function MODULENAME_preprocess_comment_wrapper(&$variables)
{
  // Provide contextual information.
  $variables['node'] = $variables['content']['#node'];
  $variables['display_mode'] = variable_get('comment_default_mode_' . $variables['node']->type, COMMENT_MODE_THREADED);
  if (!in_array($variables['node']->type, variable_get('auction_types' , array('auction_display'))))
  {
    return;
  }
  
  // Sort comments by bid value if exists
  $bids = array();
  $comments = $variables['content']['comments'];
  
  foreach ($comments as $index => $comment) {
    if (!is_array($comment) || !isset($comment['#comment']))
      continue;
    $bid = field_get_items('comment', $comment['#comment'], 'field_auction_bid');
    $comment['#comment']->subject = '';
    
    $bids[$index] = $bid[0]['amount'];
    
    unset($variables['content']['comments'][$index]);
  }
  if (!empty($bids)) {
    // sort bids from highest bid to lowest.
    uasort($bids, 'compare_comment_bids');
    $j = 1;
    // modify $variables so that the comments are printed out sorted by bid value
    foreach (array_keys($bids) as $i) {
      $variables['content']['comments'][$j] = $comments[$i];
      $j++;
    }
  }
  
  // The comment form is optional and may not exist.
  $variables['content'] += array('comment_form' => array());
}


function compare_comment_bids($a, $b)
{
  if ($a == $b)
    return 0;
  
  return ($a > $b) ? -1 : 1;
}

4. install Timeout module (attached to this post) and add a timeout field (with "field_auction_timeout" machine name) to auction_display content type.
5. add the following code to your module

function MODULENAME_node_view($node, $view_mode, $langcode) {
  if ($node->type == "auction_display" && $node->comment == COMMENT_NODE_OPEN) {
    $timeout = field_get_items('node', $node, 'field_auction_timeout', $langcode) ;
    if ( time() > $timeout[0]['timeout'] + $node->created) {
      // close comments on this node
      $node->comment = COMMENT_NODE_CLOSED;
      node_save($node);
    }
  }
} 

I think this will do it! If you got into problems please post a comment here :)
You can move the code updating product price from MODULENAME_comment_insert() to MODULENAME_node_vew() so that the price is updated whenever timeout happens.

@decibel.places, I'm on a trip right now, I'll get home in about 4 days from now! I'll be happy to work with you to develop a new field and use it instead of comments if you have time!

jepster_’s picture

Hi,

nice step. Why you add the auction functionality into a comment-hook? I'm worried about, that this isn't a way, how we should use the drupal api.

farhadhf’s picture

@jepSter, Yes, You're right, But I didn't want to put much time on this, and used the comment system as a workaround (and I don't know if it can be done using comments in any other way!). Drupal comments module is tied to nodes and many things are hardcoded in it - like the message being shown after saving a comment, or reply link shown on every posted comment....
Take a look at Decouple comment.module from node issue.
I also thought of using Reply module. But currently it's so unstable right now and has title and body hardcoded into the module...
IMHO a bid field should be developed to provide this functionality without interfering with comments module... I'll probably start working on this in the next week.
If anyone is interested in working on this, please contact me! :)

decibel.places’s picture

@farhadhf

I will certainly need this feature and I'm willing to help with it - but I'm not quite at that stage in my project, I won't be building the ecommerce functions for a couple of weeks. At the moment I am focused on the media aspects.

But I can help with any standalone tests, or exported Features etc you are working on. If you start a project in Git please add me as co-maintainer.

jepster_’s picture

Maybe it's better to migrate some of the functionality of the ubercart auction module? I've modified that module, so that it isn't really relying on ubercart. So I think that the refactoration of that module with droping all the ubercart dependency, will be the way to go.

farhadhf’s picture

Oops! I didn't know that uc_auction has been ported to drupal 7!
How does uc_auction handle bidding? I didn't see a field in the code.

@decibel.places, OK, I'll create a github repo and push everything I have to it, I'll post the link here when it's done! :)

Elementica’s picture

I also need auction+marketplace, but cannot wait, so I will work it out using present features of D7 and Drupalcommerce.

SOLUTION ON THE WAY WITH NO FORKING AT ALL.
For marketplace I just set permissions to "create new" & "edit own" products. That should be enough.
For bidding... this is a problem... forking into comments is a great work, but I don't want to fork anything (for future upgrades)... I'm thinking of a new node type (let's call it "offer", again with permissions "create new" & "edit own") with a reference to a product and one more field (the bid). I think (still to be done) I'll make a rule to automagically create it when a user wants to bid. So:

Marketplace:
- users can create products (just give permissions)

Bidding:
- users can create offers, referencing a product and setting a bid

Maybe I'll go with some more rules to fine tune some checking (e.g.: cannot edit a product if auction is closed).

I'd like opinions/idea on this...

farhadhf’s picture

Hi Andy, Thanks for sharing your solution :)
IMHO one problem is that Title of node types are locked and required (same problem with comments), and I don't think that a title is needed for every offer. Maybe it's possible to use Entity Construction Kit to create a bid entity that has no title and add the reference field with Entity Reference?

I'm not familiar with *panels and display suit. Is it possible to add a form to post offers under the product display node (like the comment form) without custom code?
I don't remember how the comment module is implemented, but I think a comment itself is an entity too, so if i'm right, we're basically doing the same thing, and avoiding custom code!
I like the idea anyway! thanks again! :)

Farhad

decibel.places’s picture

@ #21

yes, we should be able to add a form in a pane, with a reference to the node in the superior pane...

but what about making the actual bid field editable for bidders (using content field permissions or whatever that is in D7) or the Entity Reference sounds promising, and changing the owner of the auction node to the highest bidder (when the new value is higher than the saved value), then rewarding the win when the clock runs out to the current owner therefore highest bidder?

That would make it simple to create a dashboard "My Auctions" filtering a View by the author = current user. Using Revisions we could track the history so the auction would show up even if the current user is not the current owner.

for a robust community solution, custom code will almost certainly be necessary, I can help out with that (in a week or two). If you're not creating a (sub)module at least export the settings as a Feature.

Elementica’s picture

@#21 @#22

About mandatory fields like "Title"... it wouldn't be a problem... I was thinking of something like:
- a custom view to show a product and all the bids (nodes that reference the product: I would show only the "bid" field, anyway) and a link to make a new bid
- the link for a new bid trigger a rule, so a node is created "automatically" (no form shown to the user) with an automatic title (could be "Offer #nn", but it's not shown anywhere) and the previous view is re-called (updated)... or we can call the standard form using (not tested, but sounds good) Automatic Nodetitles, but I'm still looking how to fill the reference to the product.

I'm going to explore entities, now. Please if someone of you arrives to a working solution, post it here!

Elementica’s picture

I've tested entities but I've had some problems... I'm exploring other ways... like:

Hp 1) a repeatable field "bid" giving users permission to "create a new value": I shoud give the permission to edit the whole node (product, atually), but with http://drupal.org/project/field_permissions I disable the permissions on all fields but on "bid". Presently two main problems:
- let "add another value" button appear (it's not shown)
- keep track of users

Hp 2) Follow my original idea auto-creating node titles

decibel.places’s picture

Hi AndyNaimoli,

Hp 1) We may need a new table or column in an existing table that cross-references users with products with bids. I'm not even sure we need a bidding history for all cases of this functionality, just the current winning bid/user. Then we would not need "add another"

IF we are writing additional info to the db, then the "bid" could just be a db value, it would not need to be a node or entity, as long as we know the product (node) and bidding user. There are conceivably use cases where it may be useful to be a node, for reference or attachment, but damned if I need that now.

Scalability also may be an issue if the db needs to be polled on every product view. Building the product view with a cachable View would help, but only a little because the cache time would need to be very short, or a hook would need to clear the cache when a winning bid is submitted.

If there is a permissions issue then check http://api.drupal.org/api/drupal/modules--system--system.api.php/functio... and http://api.drupal.org/api/drupal/modules--user--user.module/function/use...

I have found some D7 code forgets to add the permission hook or check. (Until recently ANYBODY could reorder a Sortable View)

Hp 2) Automatic Nodetitles is an excellent module, I use it often.

decibel.places’s picture

I am talking to beejeebus about integrating a node.js bid field at Drupalcamp NJ

BUT scaling node.js for A LOT of users might be an issue - I'm looking at Cloud Foundry to host the node.js component.

This is exciting but there may be a need for a solution that does not require node.js

Elementica’s picture

I'm on the way with my original idea... I have a working installation with the following:

- users can create product of type "X"
- a rule is triggered to create a node of type "X" that references the just created product
note: automatic fields are set (using automatic nodetitles and auto-sku, for example)

- users can create offers, that are just nodes of type "Y" with a reference to a node "X" (and so to a product "X")
- nodereference_url is used as the offers are locked to a certain product
So I have a list of nodes that reference products, each one having a link to create a new offer.
I'm using EVA to bind a view with a list of offers to a specific product.

It simply works.

Now I'm fine tuning, as I'll go for some checks on bids and so on...

Elementica’s picture

[SOLVED: working solution with NO fork at all]

Ongoing... I point out that this is a work for a big business project on the way, so widely analyzed and tested.

Now I have a view that is a list of "objects" (actually nodes that point to products) each with an attached (sub)view (a list of referencing nodes) that is the list of "offers" for the object. At the end of each "object" (either in teaser and in full view) I have a "create new offer" link (thankx to nodereference_url module): this link jumps to the creation of a new node (an "offer") already referencing the "object" with a custom field "bid".

My next step is to check new bids, so they are higher than the highest already set. I'm thinking of a custom rule, but this time a php snippet will probably be necessary, but I'll see..

As already said I don't want any fork at all and I'd like to minimize the use of custom php (modules or snippets) anywhere for future upgrades.

decibel.places’s picture

AndyNaimoli:

I think when configurations are necessary but an entire module isn't, some people are rolling them into a Feature, the best of both worlds.

Elementica’s picture

Yes... I'd like to see a full "auction/bid" feature in the commerce system, but meanwhile....

Elementica’s picture

Fees and mass payments.

Another related issue is about fees: whenever an auction is completed, a fee is usually due to the host... to avoid a "double payment" process solutions are:
- buyer pays seller, seller pays host
- buyer pays host, host pays seller
- buyer does a "mass payment" with two recipients: host and seller

First and second could be - maybe - achived via rules, again.
Latter is better, but also hard to integrate with present payment systems.

decibel.places’s picture

buyer pays host, host pays seller

seller pays host is iffy, two payments is complex

I've used PayPal mass payments api with Drupal before, integrated with Workflow to trigger release of funds

farhadhf’s picture

Hi guys,
I wrote a module that uses eck to create a new entity for auction bids. you can find it here: http://drupal.org/sandbox/farhadhf/1445190
The module depends on eck(obviously!), Entity Reference, Commerce Price field and timeout field (attached to #14).

You should remove permission to create auction_bids that are provided by eck, and give 'Place bids on auctions' permission to the users. the node/%node/placebid does some validation on bid amount and auction timeout.

After enabling the module, add an entityreference on auction display node type that accepts 'commerce_auction_bid' entity type, with unlimited cardinality. also add a timeout field to your auction display node.

(currently it creates a menu item 'node/%node/placebid', but I'll create an admin interface so that the site administrator can select the auction display node type)

P.S.
I think commerce payout can be used for payment fees, etc...

EDIT:
I changed the module, you'll need to add a commerce_price field to auction display node, the module will update this field with the highest bid every time it saves a new bid... It helps performance and lets you create per-user bidding tables with views easier...

Farhad

Elementica’s picture

Thankx for your post... I'll check them... meanwhile I need to go with my solution as I'm setting a site up with a near deadline, so I need to package working "released" modules. Through a custom module I make all additional checks (e.g.: new bid must be higher than base price and other bids).

farhadhf’s picture

Status: Postponed » Fixed

Hey guys,
I wrote commerce_auction module, It supports auctions, there's no reverse auction feature yet, but it's in my todo list and I'll try to implement this feature for the next release.

Regards
Farhad

rszrama’s picture

Wonderful, thanks for the update Farhad.

Elementica’s picture

I've just found your module taking back my project after a forced delay... I'm trying a new fresh installation and I'll think I'll definitely go for it! Stay tuned... thank your for your work, Farhad.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

liliplanet’s picture

that is tremendous, thank you farhadhf .. would most appreciate the reverse auction feature :)