Here is how I ultimately did this.
First, I assessed what was going on in the Commerce Invoice module and determined I could not use this. We need to allow partial payments / deposits.
Second, we basically need exactly what administrators see on the backend when viewing orders.
Recreating this:
- Give the customer role 'Create Payments' and 'Edit own orders' Permissions
- In the Commerce Payments default view, add a Block display and override it.
- In this new view, adjust the Fields to your liking. I removed a couple for UX reasons.
- Create a custom module, and use the code below
To be somewhat consistent, I wanted to put tabs on the order display for a user so you could see order details and payments.
In a custom module, utilize hook_menu like so:
<?php
$items['user/%user/orders/%commerce_order/view'] = array(
'title callback' => 'commerce_order_ui_order_title',
'title arguments' => array(3),
'page callback' => 'commerce_order_ui_order_view',
'page arguments' => array(3, 'customer', FALSE),
'access callback' => 'commerce_order_customer_order_view_access',
'access arguments' => array(3),
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['user/%/orders/%/payments'] = array(
'title' => 'Payments',
'description' => 'Make payments for this order.',
'page callback' => 'your_custom_module_payments',
'page arguments' => array(1, 3),
'access arguments' => array('view own commerce_order entities'),
'type' => MENU_LOCAL_TASK,
'file' => 'includes/your_custom_module.payments.inc',
);
?>
The first item above I basically followed what was in commerce for the order display callback, and made /view a default task to get setup for additional tab(s), Payments. This callback is going to render a page, and call our view.
<?php
function your_custom_module_payments($uid, $order_id) {
global $user;
$order = commerce_order_load($order_id);
// not sure if this will work longterm, in the case of admins creating orders for users
if ($user->uid != $order->uid) {
return drupal_access_denied();
}
drupal_set_title('Payments');
$output .= commerce_embed_view('commerce_payment_order', 'your_new_view_display_id', array($order_id));
return $output;
}
?>
This basically checks to see that the current user is the owner of the order they are about to make or view payments against, then embeds the new view we created from the default off of Commerce Payments. I could not find a better method of doing this- I would rather check access at the menu item level, but every attempt resulted in Access Denied.
One more additional step you will want to take is to alter the Cancel link that is output in the payment form for a regular user. If not, it will attempt to take them to admin/ area by default. I just
<?php
function your_custom_module_form_commerce_payment_order_transaction_add_form_alter(&$form, &$form_state) {
if (!empty($form_state['payment_method']) && !user_access('administer payments')) {
$form['actions']['submit']['#suffix'] = l(t('Cancel'), 'user/' . $form_state['order']->uid . '/orders/' . $form_state['order']->order_id . '/payments');
}
}
?>
Here is the result:
This is now what a user sees when viewing their order, clickable with a tab between order details and Payments.
This is (for us) a larger step toward having customer balance(s) functionality. We have some D6 Ubercart clients who have running totals, not exactly storefronts. As long as they keep up on payments they still receive weekly deliveries.
Comments
Kevin posted this in IRC directly after adding the amazing amount of awesome content, "on second thought, i suppose you could dupe the master view in the Commerce Payments view, change the path to (path)/view, and make it a Tab, then create the Payments view tab, and not have any hook menu callbacks or code at all other than the form alter for the cancel link"
Thanks Kevin!