You are here

commerce_userpoints_payment_method.module in Commerce userpoints 7

File

commerce_userpoints_payment_method/commerce_userpoints_payment_method.module
View source
<?php

/**
 * Implements hook_commerce_payment_method_info().
 */
function commerce_userpoints_payment_method_commerce_payment_method_info() {
  $payment_methods['commerce_userpoints'] = array(
    'base' => 'commerce_userpoints_payment_method',
    'title' => t('!Points', userpoints_translation()),
    'short_title' => t('!Points', userpoints_translation()),
    'description' => t('Pay with !Points', userpoints_translation()),
    'active' => TRUE,
    'settings' => array(
      'min_points' => 0,
      'userpoint_currency' => NULL,
    ),
  );
  $commerce_userpoints_currencies = commerce_userpoints_currencies();

  // Set default conversion rates for each enabled currency.
  // We use a default rate of 1 for commerce userpoints currencies, or 100
  // for normal currencies.
  foreach (commerce_currencies(TRUE) as $key => $currency) {
    $payment_methods['commerce_userpoints']['settings']['currencies'][$key] = array_key_exists($key, $commerce_userpoints_currencies) ? 1 : 100;
  }
  return $payment_methods;
}

/**
 * Payment method callback: submit form submission.
 */
function commerce_userpoints_payment_method_submit_form_submit($payment_method, $pane_form, $pane_values, $order, $charge) {
  $order->data['commerce_userpoints'] = $pane_values;
  commerce_userpoints_payment_method_transaction($payment_method, $order, $charge, $pane_values['name']);
}

/**
 * Creates a userpoints payment transaction for the specified charge amount.
 *
 * @param $payment_method
 *   The payment method instance object used to charge this payment.
 * @param $order
 *   The order object the payment applies to.
 * @param $charge
 *   An array indicating the amount and currency code to charge.
 * @param $name
 *   The name entered on the submission form.
 */
function commerce_userpoints_payment_method_transaction($payment_method, $order, $charge, $name) {
  $transaction = commerce_payment_transaction_new('commerce_userpoints', $order->order_id);
  $transaction->instance_id = $payment_method['instance_id'];
  $transaction->amount = $charge['amount'];
  $transaction->currency_code = $charge['currency_code'];
  $transaction->status = COMMERCE_PAYMENT_STATUS_SUCCESS;
  $transaction->message = 'Paid with !points.';
  $transaction->message_variables = userpoints_translation();
  commerce_payment_transaction_save($transaction);

  //Load the userpoints currency to get the tid of this currency..
  $point_currency = commerce_userpoints_load($payment_method['settings']['userpoint_currency']);
  userpoints_userpointsapi(array(
    'points' => $charge['amount'] * commerce_userpoints_payment_method_get_exchange_rate($payment_method['settings'], $order) * -1,
    'uid' => $order->uid,
    'tid' => $point_currency['tid'],
    'operation' => 'commerce_userpoints_payment_method_payment',
    'entity_id' => $order->order_id,
    'entity_type' => 'commerce_order',
  ));
}

/**
 * Implements hook_userpoints_info().
 */
function commerce_userpoints_payment_method_userpoints_info() {
  return array(
    'commerce_userpoints_payment_method_payment' => array(
      'description' => t('Paid an order.'),
    ),
  );
}

/**
 * Returns the current points credit limit.
 *
 * @param $settings
 *   The payment method settings.
 */
function commerce_userpoints_payment_method_get_credit_limit($settings) {
  return $settings['min_points'];
}

/**
 * Returns the exchange rate of the order currency.
 *
 * @param $settings
 *   The payment method settings.
 * @param $order
 *   The commerce_order object.
 */
function commerce_userpoints_payment_method_get_exchange_rate($settings, $order) {
  $inter = field_get_items('commerce_order', $order, 'commerce_order_total');
  $order_total = array_shift($inter);
  return $settings['currencies'][$order_total['currency_code']];
}

/**
 *
 * @param $settings
 * @param $order
 * @return
 */
function commerce_userpoints_payment_method_get_required_points($settings, $order) {
  $requerido = field_get_items('commerce_order', $order, 'commerce_order_total');
  $order_total = array_shift($requerido);
  $exchange_rate = commerce_userpoints_payment_method_get_exchange_rate($settings, $order);
  return $order_total['amount'] * $exchange_rate;
}

/**
 * Payment method callback: submit form.
 */
function commerce_userpoints_payment_method_submit_form($payment_method, $pane_values, $checkout_pane, $order) {
  $form = array();
  if (empty($payment_method['settings'])) {
    $form['validation'] = array(
      '#type' => 'item',
      '#markup' => t('This order cannot be paid with !points because there is no exchange rate configured.', userpoints_translation()),
    );
    return $form;
  }
  $credit_limit = commerce_userpoints_payment_method_get_credit_limit($payment_method['settings']);

  //Add parameter all for userpoints_get_current_points().

  //TODO::is it necessary to add a config UI for user to choose which userpoint category could be used as payment?
  $point_currency = commerce_userpoints_load($payment_method['settings']['userpoint_currency']);
  $current_points = userpoints_get_current_points($order->uid, $point_currency['tid']);
  $exchange_rate = commerce_userpoints_payment_method_get_exchange_rate($payment_method['settings'], $order);
  if ($exchange_rate == 0) {
    $form['validation'] = array(
      '#type' => 'item',
      '#markup' => t('This order cannot be paid with !points because there is no exchange rate configured.', userpoints_translation()),
    );
    return $form;
  }
  $required_points = commerce_userpoints_payment_method_get_required_points($payment_method['settings'], $order);

  //We need to convert this into interger.
  $required_points = commerce_round(COMMERCE_ROUND_HALF_UP, $required_points);
  $resulting_balance = $current_points - $required_points;
  $header = array(
    array(
      'data' => t('!Points requirements', userpoints_translation()),
      'colspan' => 2,
    ),
  );
  $rows = array(
    array(
      t('Current !points', userpoints_translation()),
      theme('cu_points', array(
        'points' => $current_points,
      )),
    ),
    array(
      t('!Points credit limit', userpoints_translation()),
      theme('cu_points', array(
        'points' => $credit_limit,
      )),
    ),
    array(
      t('Exchange rate'),
      theme('cu_points', array(
        'points' => $exchange_rate,
      )),
    ),
    array(
      t('Required !points', userpoints_translation()),
      '<strong>' . theme('cu_points', array(
        'points' => $required_points,
      )) . '</strong>',
    ),
    array(
      t('Resulting balance'),
      theme('cu_points', array(
        'points' => $resulting_balance,
      )),
    ),
  );
  $form['table'] = array(
    '#theme' => 'table',
    '#rows' => $rows,
    '#header' => $header,
  );
  if ($resulting_balance > $credit_limit) {
    $form['validation'] = array(
      '#type' => 'item',
      '#markup' => t('You have enough !points!', userpoints_translation()),
    );
  }
  else {
    $form['validation'] = array(
      '#type' => 'item',
      '#markup' => t('You have <strong>not</strong> enough !points!', userpoints_translation()),
    );
  }
  return $form;
}

/**
 * Payment method callback: submit form validation.
 */
function commerce_userpoints_payment_method_submit_form_validate($payment_method, $pane_form, $pane_values, $order, $form_parents = array()) {
  $credit_limit = commerce_userpoints_payment_method_get_credit_limit($payment_method['settings']);
  $current_points = userpoints_get_current_points($order->uid, 'all');
  $conversion = commerce_userpoints_payment_method_get_exchange_rate($payment_method['settings'], $order);
  if ($conversion == 0) {
    form_set_error(implode('][', array_merge($form_parents, array(
      'required',
    ))), t('This order cannot be paid with !points because there is no exchange rate configured.', userpoints_translation()));
    return FALSE;
  }
  $required_points = commerce_userpoints_payment_method_get_required_points($payment_method['settings'], $order);
  $resulting_balance = $current_points - $required_points;
  if ($resulting_balance < $credit_limit) {
    form_set_error(implode('][', array_merge($form_parents, array(
      'required',
    ))), t('Not enough !points.', userpoints_translation()));

    // Even though the form error is enough to stop the submission of the form,
    // it's not enough to stop it from a Commerce standpoint because of the
    // combined validation / submission going on per-pane in the checkout form.
    return FALSE;
  }
}

/**
 * Payment method callback; return the settings form for a payment method.
 *
 * @param $settings
 *   An array of the current settings.
 * @return
 *   A form snippet.
 */
function commerce_userpoints_payment_method_settings_form($settings = NULL) {
  if (!is_array($settings)) {
    $settings = array();
  }
  $form['userpoint_currency'] = array(
    '#type' => 'select',
    '#options' => commerce_userpoints_currencies_option_list(),
    '#default_value' => $settings['userpoint_currency'],
  );
  $settings += array(
    'min_points' => 0,
    'currencies' => array(),
  );
  $form['min_points'] = array(
    '#type' => 'textfield',
    '#title' => t('Minimal !points balance limit', userpoints_translation()),
    '#default_value' => $settings['min_points'],
  );
  $form['currencies']['#tree'] = TRUE;
  $rows = array();
  foreach (commerce_currencies(TRUE) as $key => $currency) {
    $rate = !empty($settings['currencies'][$key]) ? $settings['currencies'][$key] : 1;
    $form['currencies'][$key] = array(
      '#type' => 'textfield',
      '#title' => t('Exchange rate for @currency', array(
        '@currency' => $currency['name'],
      )),
      '#default_value' => $rate,
      '#description' => t('A value of 0 prohibits using !points for this currency. Currently 1' . $currency['code'] . ' = ' . $rate . '!points', userpoints_translation()),
    );
  }
  return $form;
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function commerce_userpoints_payment_method_form_commerce_checkout_form_checkout_alter(&$form, &$form_state) {

  //Not Sure why this form need to alter. but it has make problems. see:

  //https://drupal.org/node/1936042

  //So below code is going to fix this issue.
  if (empty($form_state['values']['commerce_payment']) || empty($form['commerce_payment']['payment_methods']) || empty($order->data['payment_method'])) {
    return;
  }

  // Find the default payment method using either the preselected value stored
  // in the order / checkout pane or the first available method.
  $commerce_payment_pane_values = !empty($form_state['values']['commerce_payment']) ? $form_state['values']['commerce_payment'] : array();
  $order = $form_state['order'];
  if (isset($commerce_payment_pane_values['payment_method'])) {
    $payment_method = $commerce_payment_pane_values['payment_method'];
  }
  elseif (isset($order->data['payment_method'])) {
    $payment_method = $order->data['payment_method'];
  }
  else {
    reset($form['commerce_payment']['payment_methods']);
    $payment_method = key($form['commerce_payment']['payment_methods']['#value']);
  }
  if ($payment_method == 'commerce_userpoints|commerce_payment_commerce_userpoints') {
    $form['commerce_userpoints_discount'] = array(
      '#type' => 'container',
      '#attributes' => array(
        'id' => 'commerce-userpoints-discount',
      ),
    );
  }
  if (isset($form['commerce_userpoints_discount'])) {

    //  Set this global static to true so hook_ajax_render_alter
    //  knows it has to insert the command to update the cart.
    $commerce_userpoints =& drupal_static('commerce_userpoints');
    $commerce_userpoints = TRUE;
  }
}

/**
 * Implements hook_ajax_render_alter().
 *
 * In case the user has changed the payment method, insert an ajax
 * command that replaces the content of the commerce_userpoints_discount pane.
 */
function commerce_userpoints_payment_method_ajax_render_alter(&$commands) {
  $commerce_userpoints =& drupal_static('commerce_userpoints');
  if ($commerce_userpoints) {

    // Retrieve and process the form.
    // NOTE: Processing the form with drupal_process_form is important to
    // ensure that the form is fully rendered.
    list($form, $form_state, $form_id, $form_build_id) = ajax_get_form();
    drupal_process_form($form['#form_id'], $form, $form_state);
    if ($form_state['input']['_triggering_element_name'] == 'commerce_payment[payment_method]') {
      $commands[] = ajax_command_replace('#commerce-userpoints-discount', render($form['commerce_userpoints_discount']));
    }
  }
}