diff --git a/shipping/uc_shipping/uc_shipping.info b/shipping/uc_shipping/uc_shipping.info index c1143bf..4c330bb 100644 --- a/shipping/uc_shipping/uc_shipping.info +++ b/shipping/uc_shipping/uc_shipping.info @@ -3,3 +3,6 @@ description = Gets products ready for physical shipment. dependencies[] = uc_quote package = Ubercart - core (optional) core = 7.x + +; Views handlers +files[] = views/uc_shipping_handler_field_sid.inc diff --git a/shipping/uc_shipping/uc_shipping.module b/shipping/uc_shipping/uc_shipping.module index 0a15bb0..71043e1 100644 --- a/shipping/uc_shipping/uc_shipping.module +++ b/shipping/uc_shipping/uc_shipping.module @@ -766,3 +766,13 @@ function uc_shipping_address_form($form, &$form_state, $addresses, $order) { ); return $form; } + +/** + * Implements hook_views_api(). + */ +function uc_shipping_views_api() { + return array( + 'api' => '2.0', + 'path' => drupal_get_path('module', 'uc_shipping') . '/views', + ); +} diff --git a/shipping/uc_shipping/views/uc_shipping.views.inc b/shipping/uc_shipping/views/uc_shipping.views.inc new file mode 100644 index 0000000..ec386f5 --- /dev/null +++ b/shipping/uc_shipping/views/uc_shipping.views.inc @@ -0,0 +1,516 @@ + array( + 'left_field' => 'order_id', + 'field' => 'order_id', + ), + ); + + // Shipment ID field. + $data['uc_shipments']['sid'] = array( + 'title' => t('Shipment ID'), + 'help' => t('The shipment ID.'), + 'field' => array( + 'handler' => 'uc_shipping_handler_field_sid', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + 'name field' => 'title', + 'numeric' => TRUE, + 'validate type' => 'sid', + ), + ); + + // Carrier field + $data['uc_shipments']['carrier'] = array( + 'title' => t('Carrier'), + 'help' => t('The company making the delivery.'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + ); + + // Shipment Transaction ID field + $data['uc_shipments']['transaction_id'] = array( + 'title' => t('Transaction ID'), + 'help' => t('The carrier\'s shipment identifier.'), + 'field' => array( + 'handler' => 'uc_shipping_handler_field_sid', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + 'name field' => 'title', + 'numeric' => TRUE, + 'validate type' => 'transaction_id', + ), + ); + + // Shipment Tracking Number field + // @todo An option to external URL for tracking + $data['uc_shipments']['tracking_number'] = array( + 'title' => t('Tracking Number'), + 'help' => t('The number used by the carrier to locate the shipment while it is in transit.'), + 'field' => array( + 'handler' => 'uc_shipping_handler_field_sid', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + 'name field' => 'title', + 'numeric' => TRUE, + 'validate type' => 'transaction_id', + ), + ); + + $data['uc_shipments']['ship_date'] = array( + 'title' => t('Ship date'), + 'help' => t('The date when the shipment left the origin address.'), + 'field' => array( + 'handler' => 'views_handler_field_date', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort_date', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_date', + ), + ); + + $data['uc_shipments']['expected_delivery'] = array( + 'title' => t('Expected delivery date'), + 'help' => t('The expected date of delivery.'), + 'field' => array( + 'handler' => 'views_handler_field_date', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort_date', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_date', + ), + ); + + $data['uc_shipments']['changed'] = array( + 'title' => t('Last modified'), + 'help' => t('The time the shipment was last modified.'), + 'field' => array( + 'handler' => 'views_handler_field_date', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort_date', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_date', + ), + ); + + // Use the sleeker Date module views handler if available. + if (module_exists('date_views')) { + $data['uc_shipments']['ship_date']['filter'] = array( + 'handler' => 'date_views_filter_handler_simple', + 'is date' => TRUE, + ); + $data['uc_shipments']['expected_delivery']['filter'] = array( + 'handler' => 'date_views_filter_handler_simple', + 'is date' => TRUE, + ); + $data['uc_shipments']['changed']['filter'] = array( + 'handler' => 'date_views_filter_handler_simple', + 'is date' => TRUE, + ); + } + + // Changed field handler to display as a price + // uc_order is required by shipping module so is safe to use uc_order handler + $data['uc_shipments']['cost'] = array( + 'title' => t('Cost'), + 'help' => t('The cost of the shipment.'), + 'field' => array( + 'handler' => 'uc_order_handler_field_money_amount', + 'click sortable' => TRUE, + 'float' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + ), + ); + + // @todo Shipping method as relationship when shipping methods are exposed to + // views also. + + // Packages count + // @todo Make the handler + /* + $data['uc_shipments']['packages_count'] = array( + 'title' => t('Packages count'), + 'help' => t('The total number of packages in the shipment.'), + 'field' => array( + 'handler' => 'views_handler_field_numeric', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + ), + ); + */ + + $addresses = array( + 'o' => t('Origin address'), + 'd' => t('Delivery address'), + ); + + $fields = array( + 'first_name' => t('First name'), + 'last_name' => t('Last name'), + 'company' => t('Company'), + 'street1' => t('Street address 1'), + 'street2' => t('Street address 2'), + 'city' => t('City'), + 'postal_code' => t('Postal code'), + ); + + foreach ($addresses as $prefix => $address) { + $group = t('Shipments') . ': ' . $address; + + foreach ($fields as $field => $label) { + $data['uc_shipments'][$prefix . '_' . $field] = array( + 'group' => $group, + 'title' => $label, + 'help' => t('The !field of the !address of the shipment.', array('!field' => drupal_strtolower($label), '!address' => drupal_strtolower($address))), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + ); + } + // uc_order is required by shipping module so is safe to use uc_order handler + $data['uc_shipments'][$prefix . '_full_name'] = array( + 'group' => $group, + 'title' => t('Full name'), + 'help' => t('The !field of the !address of the shipment.', array('!field' => t('full name'), '!address' => drupal_strtolower($address))), + 'field' => array( + 'additional fields' => array( + $prefix . '_first_name', + $prefix . '_last_name' + ), + 'handler' => 'uc_order_handler_field_order_fullname', + 'prefix' => $prefix, + ), + ); + + $data[$prefix . '_countries']['table']['group'] = $group; + $data[$prefix . '_countries']['table']['join']['uc_shipments'] = array( + 'table' => 'uc_countries', + 'left_field' => $prefix . '_country', + 'field' => 'country_id', + ); + $data[$prefix . '_countries']['country_id'] = array( + 'title' => t('ISO country code (numeric)'), + 'help' => t('The !field of the !address of the shipment.', array('!field' => t('numeric ISO country code'), '!address' => drupal_strtolower($address))), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + 'name field' => 'country_iso_code_2', + 'numeric' => TRUE, + 'validate type' => 'country_id', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + ), + ); + $data[$prefix . '_countries']['country_name'] = array( + 'title' => t('Country'), + 'help' => t('The !field of the !address of the shipment.', array('!field' => t('country name'), '!address' => drupal_strtolower($address))), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + ); + $data[$prefix . '_countries']['country_iso_code_2'] = array( + 'title' => t('ISO country code (2 characters)'), + 'help' => t('The !field of the !address of the shipment.', array('!field' => t('ISO country code'), '!address' => drupal_strtolower($address))), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + ); + $data[$prefix . '_countries']['country_iso_code_3'] = array( + 'title' => t('ISO country code (3 characters)'), + 'help' => t('The !field of the !address of the shipment.', array('!field' => t('ISO country code'), '!address' => drupal_strtolower($address))), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + ); + + $data[$prefix . '_zones']['table']['group'] = $group; + $data[$prefix . '_zones']['table']['join']['uc_shipments'] = array( + 'table' => 'uc_zones', + 'left_field' => $prefix . '_zone', + 'field' => 'zone_id', + ); + $data[$prefix . '_zones']['zone_name'] = array( + 'title' => t('State/Province'), + 'help' => t('The !field of the !address of the shipment.', array('!field' => t('state or province'), '!address' => drupal_strtolower($address))), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + ); + $data[$prefix . '_zones']['zone_code'] = array( + 'title' => t('State/Province code'), + 'help' => t('The !field of the !address of the shipment.', array('!field' => t('state or province code'), '!address' => drupal_strtolower($address))), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + ); + } + + // Expose packages + $data['uc_packages']['table']['group'] = t('Shipment Package'); + + // Expose products to their orders as a relationship. + // @todo Why order_id exists in the uc_packages shcema. In order for a package + // to exist there must be a shippment first so the package should link + // only to it's shippment not directly to order. + $data['uc_shipments']['packages'] = array( + 'relationship' => array( + 'title' => t('Packages'), + 'help' => t('Relate packages to a shipment. This relationship will create one record for each shipped package.'), + 'handler' => 'views_handler_relationship', + 'base' => 'uc_packages', + 'base field' => 'sid', + 'relationship field' => 'sid', + 'label' => t('packages'), + ), + ); + + // Package ID field. + // Packages don't have a separate page each so when click on package id redirect + // to shipment (same handler). + $data['uc_packages']['package_id'] = array( + 'title' => t('Package ID'), + 'help' => t('The package ID.'), + 'field' => array( + 'handler' => 'uc_shipping_handler_field_sid', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + 'name field' => 'title', + 'numeric' => TRUE, + 'validate type' => 'sid', + ), + ); + + // Shipment type field + $data['uc_packages']['shipping_type'] = array( + 'title' => t('Shipment type'), + 'help' => t('The basic type of shipment, e.g.: small package, freight, etc.'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + ); + + // Package type + $data['uc_packages']['pkg_type'] = array( + 'title' => t('Package type'), + 'help' => t('The type of packaging.'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_string', + ), + ); + + // @todo Dimension handler for united dimensions + + // Changed field handler to display as a price + // uc_order is required by shipping module so is safe to use uc_order handler + $data['uc_packages']['value'] = array( + 'title' => t('Value'), + 'help' => t('The monetary value of the package contents.'), + 'field' => array( + 'handler' => 'uc_order_handler_field_money_amount', + 'click sortable' => TRUE, + 'float' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + ), + ); + + // Shipment Tracking Number field + // @todo An option to external URL for tracking + $data['uc_packages']['tracking_number'] = array( + 'title' => t('Tracking Number'), + 'help' => t('The number used by the carrier to locate the package while it is in transit.'), + 'field' => array( + 'handler' => 'uc_shipping_handler_field_sid', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + ), + 'argument' => array( + 'handler' => 'views_handler_argument_numeric', + 'name field' => 'title', + 'numeric' => TRUE, + 'validate type' => 'transaction_id', + ), + ); + + // Expose packaged products + + // Expose packed products on their package as a relationship. + $data['uc_packages']['packages'] = array( + 'relationship' => array( + 'title' => t('Packaged Products'), + 'help' => t('Relate packaged products to a package. This relationship will create one record for each packaged product.'), + 'handler' => 'views_handler_relationship', + 'base' => 'uc_packaged_products', + 'base field' => 'package_id', + 'relationship field' => 'package_id', + 'label' => t('packaged_products'), + ), + ); + + // Packaged quantity field + $data['uc_packaged_products']['qty'] = array( + 'title' => t('Quantity'), + 'help' => t('The quantity packaged.'), + 'field' => array( + 'handler' => 'views_handler_field', + 'click sortable' => TRUE, + ), + 'sort' => array( + 'handler' => 'views_handler_sort', + ), + 'filter' => array( + 'handler' => 'views_handler_filter_numeric', + ), + ); + + // Pull in ordered product fields directly. + $data['uc_order_products']['table']['join']['uc_packaged_products'] = array( + 'left_field' => 'order_product_id', + 'field' => 'order_product_id', + ); + + // @todo Package weight maybe is useful here. + + return $data; +} diff --git a/shipping/uc_shipping/views/uc_shipping_handler_field_sid.inc b/shipping/uc_shipping/views/uc_shipping_handler_field_sid.inc new file mode 100644 index 0000000..16d78cb --- /dev/null +++ b/shipping/uc_shipping/views/uc_shipping_handler_field_sid.inc @@ -0,0 +1,80 @@ +options['link_to_shipment'])) { + $this->additional_fields['order_id'] = array('table' => 'uc_orders', 'field' => 'order_id'); + $this->additional_fields['sid'] = array('table' => 'uc_shipments', 'field' => 'sid'); + } + } + + /** + * Overrides views_handler::option_definition(). + */ + function option_definition() { + $options = parent::option_definition(); + $options['link_to_shipment'] = array('default' => FALSE); + return $options; + } + + /** + * Overrides views_handler::options_form(). + * + * Provides link to shipment administration page. + */ + function options_form(&$form, &$form_state) { + parent::options_form($form, $form_state); + $form['link_to_shipment'] = array( + '#title' => t('Link this field to the shipment page'), + '#description' => t('This will override any other link you have set.'), + '#type' => 'checkbox', + '#default_value' => !empty($this->options['link_to_shipment']), + ); + } + + /** + * Renders whatever the data is as a link to the order. + * + * Data should be made XSS safe prior to calling this function. + */ + function render_link($data, $values) { + if (!empty($this->options['link_to_shipment'])) { + $this->options['alter']['make_link'] = FALSE; + + if (user_access('fulfill orders')) { + $path = 'admin/store/orders/' . $this->get_value($values, 'order_id') . '/shipments/' . $this->get_value($values, 'sid'); + } + else { + $path = FALSE; + } + + if ($path && $data !== NULL && $data !== '') { + $this->options['alter']['make_link'] = TRUE; + $this->options['alter']['path'] = $path; + } + } + return $data; + } + + /** + * Overrides views_handler_field::render(). + */ + function render($values) { + return $this->render_link(check_plain($values->{$this->field_alias}), $values); + } + +}