packship: updated default api url to be http instead of https, added a description...
[project/commerce_kiala.git] / modules / commerce_kiala_ps / commerce_kiala_ps.module
1 <?php
2
3 /**
4 * @file
5 * Allows you to define any number of Kiala shipping services
6 */
7
8 /**
9 * Implements hook_menu().
10 */
11 function commerce_kiala_ps_menu() {
12 $items = array();
13
14 $items['admin/commerce/orders/%commerce_order/kiala-packship-desktop-export'] = array(
15 'title' => 'P&S Desktop Export',
16 'page callback' => 'commerce_kiala_ps_desktop_order_export_page',
17 'page arguments' => array(3),
18 'access callback' => 'commerce_kiala_ps_desktop_order_export_page_access',
19 'access arguments' => array(3),
20 'type' => MENU_LOCAL_ACTION,
21 'weight' => 20,
22 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
23 );
24
25 $items['admin/commerce/orders/%commerce_order/kiala-packship-ws'] = array(
26 'title' => 'Pack and Ship',
27 'page callback' => 'commerce_kiala_ps_ws_order_page',
28 'page arguments' => array(3),
29 'access callback' => 'commerce_kiala_ps_ws_order_page_access',
30 'access arguments' => array(3),
31 'type' => MENU_LOCAL_TASK,
32 'weight' => 25,
33 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
34 'file' => 'includes/commerce_kiala_ps.admin.inc',
35 );
36 $items['admin/commerce/orders/%commerce_order/kiala-packship-ws/dashboard'] = array(
37 'title' => 'Dashboard',
38 'type' => MENU_DEFAULT_LOCAL_TASK,
39 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
40 'weight' => 0,
41 );
42
43 $items['admin/commerce/orders/%commerce_order/kiala-packship-ws/desktop-export'] = $items['admin/commerce/orders/%commerce_order/kiala-packship-desktop-export'];
44
45 $items['admin/commerce/orders/%commerce_order/kiala-packship-ws/logs/%commerce_kiala_ps_ws_log'] = array(
46 'title callback' => 'commerce_kiala_ps_ws_log_title',
47 'title arguments' => array(6),
48 'page callback' => 'commerce_kiala_ps_ws_log_view',
49 'page arguments' => array(6, 'administrator'),
50 'access callback' => 'commerce_kiala_ps_ws_log_access',
51 'access arguments' => array('view', 6),
52 );
53 $items['admin/commerce/orders/%commerce_order/kiala-packship-ws/logs/%commerce_kiala_ps_ws_log/view'] = array(
54 'title' => 'View',
55 'type' => MENU_DEFAULT_LOCAL_TASK,
56 'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
57 'weight' => 0,
58 );
59 $items['admin/commerce/orders/%commerce_order/kiala-packship-ws/logs/%commerce_kiala_ps_ws_log/delete'] = array(
60 'title' => 'Delete',
61 'page callback' => 'commerce_kiala_ps_ws_log_delete_form_wrapper',
62 'page arguments' => array(3, 6),
63 'access callback' => 'commerce_kiala_ps_ws_log_access',
64 'access arguments' => array('delete', 6),
65 'type' => MENU_LOCAL_TASK,
66 'context' => MENU_CONTEXT_INLINE,
67 'weight' => 10,
68 'file' => 'includes/commerce_kiala_ps.admin.inc',
69 );
70
71 return $items;
72 }
73
74 /**
75 * Implements hook_views_api().
76 */
77 function commerce_kiala_ps_views_api() {
78 return array(
79 'api' => 3,
80 'path' => drupal_get_path('module', 'commerce_kiala_ps') . '/includes/views',
81 );
82 }
83
84 /**
85 * Access callback for packship export page
86 */
87 function commerce_kiala_ps_desktop_order_export_page_access($order) {
88 if (!user_access('administer kiala services')) {
89 return FALSE;
90 }
91
92 return commerce_kiala_ps_desktop_order_export_access($order, TRUE);
93 }
94
95 /**
96 * Returns TRUE if order can use Kiala P&S Desktop
97 */
98 function commerce_kiala_ps_desktop_order_export_access($order, $exclude_warnings = FALSE) {
99 $settings = commerce_kiala_settings(array(
100 'include_passwords' => TRUE,
101 ));
102
103 // DENY if not basic pack ship order access
104 if (!commerce_kiala_ps_order_access($order, $exclude_warnings)) {
105 return FALSE;
106 }
107
108 // DENY if any warnings exist
109 if (empty($exclude_warnings)) {
110 $warnings = commerce_kiala_ps_desktop_order_warnings($order);
111 if (!empty($warnings)) {
112 return FALSE;
113 }
114 }
115
116 return TRUE;
117 }
118
119 /**
120 * Returns an array of warnings for Pack & Ship WS for the given order
121 */
122 function commerce_kiala_ps_desktop_order_warnings($order) {
123 $warnings = array();
124 /** @todo: any specifc to the desktop ??? ****/
125 return $warnings;
126 }
127
128 /**
129 * Menu access callback for P&S web service page
130 */
131 function commerce_kiala_ps_ws_order_page_access($order) {
132 if (!user_access('administer kiala packship ws')) {
133 return FALSE;
134 }
135
136 // return order access without weight check
137 return commerce_kiala_ps_ws_order_access($order, TRUE);
138 }
139
140 /**
141 * Returns TRUE if order can use Kiala P&S Web Service
142 */
143 function commerce_kiala_ps_ws_order_access($order, $exclude_warnings = FALSE) {
144 $settings = commerce_kiala_settings(array(
145 'include_passwords' => TRUE,
146 ));
147
148 // DENY if packship type is not desktop
149 if (!isset($settings['packship_type']) || $settings['packship_type'] != 'ws') {
150 return FALSE;
151 }
152
153 // DENY if not enough information provided
154 if (empty($settings['packship_ws_sender_id']) || empty($settings['packship_ws_password']) ||
155 empty($settings['packship_ws_url'])) {
156 return FALSE;
157 }
158
159 // DENY if not basic pack ship order access
160 if (!commerce_kiala_ps_order_access($order, $exclude_warnings)) {
161 return FALSE;
162 }
163
164 // DENY if any warnings exist
165 if (empty($exclude_warnings)) {
166 $warnings = commerce_kiala_ps_ws_order_warnings($order);
167 if (!empty($warnings)) {
168 return FALSE;
169 }
170 }
171
172 return TRUE;
173 }
174
175 /**
176 * Returns an array of warnings for Pack & Ship WS for the given order
177 */
178 function commerce_kiala_ps_ws_order_warnings($order) {
179 $warnings = array();
180 $settings = commerce_kiala_settings();
181
182 // check against max weight
183 if (!empty($settings['packship_ws_max_weight'])) {
184 $weight = commerce_physical_order_weight($order, 'kg');
185 if (empty($weight['weight']) || $weight['weight'] > $settings['packship_ws_max_weight']) {
186 $warnings['max_weight'] = t('The weight of this order is over the maximum allowed @max_weight kg, current weight is @weight kg.', array(
187 '@weight' => sprintf("%01.3f", round($weight['weight'], 3)),
188 '@max_weight' => sprintf("%01.3f", round($settings['packship_ws_max_weight'], 3)),
189 ));
190 }
191 }
192
193 return $warnings;
194 }
195
196 /**
197 * Returns TRUE if order can use Kiala P&S
198 */
199 function commerce_kiala_ps_order_access($order, $exclude_warnings = FALSE) {
200 if (empty($order->order_id)) {
201 return FALSE;
202 }
203
204 $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
205
206 // DENY if no kiala point associated with the order
207 $point_id = $order_wrapper->kiala_point_id->value();
208 if (empty($point_id)) {
209 return FALSE;
210 }
211
212 $settings = commerce_kiala_settings();
213
214 // DENY if no sender country
215 if (empty($settings['country'])) {
216 return FALSE;
217 }
218
219 // DENY if order has not completed checkout
220 if (!commerce_kiala_order_completed_date($order)) {
221 return FALSE;
222 }
223
224 // DENY if there is no order weight
225 $weight = commerce_physical_order_weight($order, 'kg');
226 if (empty($weight['weight'])) {
227 return FALSE;
228 }
229
230 // DENY if no recipient address
231 $recipient_address = commerce_kiala_order_recipient_addressfield($order);
232 if (empty($recipient_address) || empty($recipient_address['country']) ||
233 empty($recipient_address['postal_code']) || empty($recipient_address['last_name'])) {
234 return FALSE;
235 }
236
237 // DENY if any warnings exist
238 if (empty($exclude_warnings)) {
239 $warnings = commerce_kiala_ps_order_warnings($order);
240 if (!empty($warnings)) {
241 return FALSE;
242 }
243 }
244
245 return TRUE;
246 }
247
248 /**
249 * Returns an array of warnings for Pack & Ship for the given order
250 */
251 function commerce_kiala_ps_order_warnings($order) {
252 $warnings = array();
253 $recipient_address = commerce_kiala_order_recipient_addressfield($order);
254
255 // WARN if language mis-match
256 $language = language_default()->language;
257 if (!commerce_kiala_ps_language_combinations_match($language, $recipient_address['country'])) {
258 $warnings['language'] = t('Language is not supported in the recipient\'s country.');
259 }
260
261 /** @todo: check from and to country combinations *********************/
262 /*
263 if (FALSE) {
264 $warnings['language'] = t('Cannot ship to the recipient\'s country.');
265 }
266 */
267
268 return $warnings;
269 }
270
271 /*
272 * Render callback for packship export page
273 */
274 function commerce_kiala_ps_desktop_order_export_page($order) {
275 $wrapper = entity_metadata_wrapper('commerce_order', $order);
276 $export = $wrapper->kiala_packship_desktop_export->value();
277
278 if (is_string($export)) {
279 // Deliver the raw export text
280 drupal_add_http_header('Content-disposition', 'attachment; filename=order-' . $order->order_id . '.kiala');
281 echo $export;
282 }
283 else {
284 foreach ($export['errors'] as $error_msg) {
285 drupal_set_message($error_msg, 'error');
286 }
287
288 return t('Export failed.');
289 }
290 }
291
292 /**
293 * Implements hook_form_FORM_ID_alter()
294 */
295 function commerce_kiala_ps_form_commerce_kiala_settings_form_alter(&$form, &$form_state, $form_id) {
296 $kiala_contact_mail = 'e-commerce@kiala.com';
297 $settings_info = commerce_kiala_settings_info();
298 $default_values = commerce_kiala_settings(array(
299 'include_passwords' => FALSE,
300 'decrypt' => TRUE,
301 ));
302 $password_hashes = commerce_kiala_settings(array(
303 'include_passwords' => TRUE,
304 'conditions' => array('password' => TRUE),
305 ));
306
307
308 $form['commerce_kiala_packship'] = array(
309 '#type' => 'fieldset',
310 '#title' => t('Pack and Ship'),
311 '#collapsible' => TRUE,
312 '#group' => 'groups',
313 '#weight' => 1,
314 '#description' => t('In order to use Pack and Ship, you must have an account with Kiala. You can contact Kiala at !mail', array('!mail' => $kiala_contact_mail)),
315 );
316 $form_packship = &$form['commerce_kiala_packship'];
317
318 $form_packship['packship_type'] = array(
319 '#type' => 'select',
320 '#title' => t('Pack and Ship type'),
321 '#default_value' => isset($default_values['packship_type']) ? $default_values['packship_type'] : '',
322 '#required' => TRUE,
323 '#options' => array(
324 'desktop' => t('Desktop'),
325 'ws' => t('Web Service'),
326 ),
327 '#description' => t('In order to use Desktop or Web, please contact Kiala at !mail', array('!mail' => $kiala_contact_mail)),
328 );
329
330 $packship_active_states = array(
331 'ws' => array(
332 ':input[name*="packship_type"]' => array('value' => 'ws')
333 ),
334 'desktop' => array(
335 ':input[name*="packship_type"]' => array('value' => 'desktop')
336 ),
337 );
338
339
340 $form_packship['packship_ws'] = array(
341 '#type' => 'fieldset',
342 '#title' => t('Web Service Settings'),
343 '#states' => array(
344 'visible' => $packship_active_states['ws'],
345 ),
346 );
347 $form_packship['packship_ws']['packship_ws_sender_id'] = array(
348 '#type' => 'textfield',
349 '#title' => t('Sender ID'),
350 '#default_value' => isset($default_values['packship_ws_sender_id']) ? $default_values['packship_ws_sender_id'] : '',
351 '#description' => t('Maximum 32 characters.'),
352 '#maxlength' => 32,
353 '#states' => array(
354 'required' => $packship_active_states['ws'],
355 ),
356 );
357 $form_packship['packship_ws']['packship_ws_password'] = array(
358 '#type' => 'password',
359 '#title' => t('Password'),
360 '#description' => t('Please leave blank if you do not want to update your password at this time.'),
361 );
362 if (empty($password_hashes['packship_ws_password'])) {
363 $form_packship['packship_ws']['packship_ws_password']['#states'] = array(
364 'required' => $packship_active_states['ws'],
365 );
366 }
367 $form_packship['packship_ws']['packship_ws_url'] = array(
368 '#type' => 'textfield',
369 '#title' => t('API URL'),
370 '#default_value' => isset($default_values['packship_ws_url']) ? $default_values['packship_ws_url'] : '',
371 '#description' => t('The SOAP API url. Example: @url', array('@url' => $settings_info['packship_ws_url']['default'])),
372 //'#disabled' => TRUE,
373 '#states' => array(
374 'required' => $packship_active_states['ws'],
375 ),
376 );
377 $form_packship['packship_ws']['packship_ws_max_weight'] = array(
378 '#type' => 'textfield',
379 '#title' => t('Max Weight'),
380 '#description' => t('If the parcel exceeds the maximum weight allowed by Kiala,
381 then Kiala will not be able to handle your shipments. To know the exact restrictions, please contact Kiala.<br />
382 Leave blank to ignore the max weight restriction.'),
383 '#field_suffix' => t('kg'),
384 '#default_value' => isset($default_values['packship_ws_max_weight']) ? $default_values['packship_ws_max_weight'] : '',
385 '#size' => 5,
386 );
387
388 if (!empty($default_values['packship_ws_params'])) {
389 $form_packship['packship_ws']['packship_ws_params'] = commerce_kiala_admin_settings_params_element($default_values['packship_ws_params']);
390 }
391
392
393 $form['#validate'][] = 'commerce_kiala_ps_settings_form_validate';
394 }
395
396 /**
397 * Validate callback for commerce_kiala_settings_form()
398 */
399 function commerce_kiala_ps_settings_form_validate($form, &$form_state) {
400 $values = &$form_state['values'];
401
402 // get the stored passwords untouched from the database
403 $current_password_hashes = commerce_kiala_settings(array(
404 'include_passwords' => TRUE,
405 'decrypt' => FALSE,
406 'conditions' => array('password' => TRUE),
407 ));
408
409 // Pack & Ship conditional validation
410 if (isset($values['packship_type']) && $values['packship_type'] == 'ws') {
411 if ($values['packship_ws_max_weight'] != '') {
412 $max_weight = $values['packship_ws_max_weight'];
413 if (!is_numeric($max_weight) || $max_weight < 0) {
414 form_set_error('packship_ws_max_weight', t('Max weight must be a positive number.'));
415 }
416 }
417
418 if (empty($values['packship_ws_sender_id'])) {
419 form_set_error('packship_ws_sender_id', t('You must enter a Sender ID for the Pack & Ship Web Service.'));
420 return;
421 }
422
423 if (empty($values['packship_ws_password'])) {
424 if (empty($current_password_hashes['packship_ws_password'])) {
425 form_set_error('packship_ws_password', t('You must enter a password for the Pack & Ship Web Service.'));
426 return;
427 }
428 }
429 }
430 }
431
432 /**
433 * Implements hook_theme().
434 */
435 function commerce_kiala_ps_theme() {
436 return array(
437 'commerce_kiala_ps_ws_log' => array(
438 'variables' => array('log' => NULL, 'order' => NULL, 'view_mode' => NULL),
439 ),
440 );
441 }
442
443 /**
444 * Implements hook_permission().
445 */
446 function commerce_kiala_ps_permission() {
447 return array(
448 'administer kiala packship ws' => array(
449 'title' => t('Administer Kiala Pack & Ship web service'),
450 'description' => t('Allows users to perform any web service action for any order and view logs.'),
451 'restrict access' => TRUE,
452 ),
453 'view kiala packship ws logs' => array(
454 'title' => t('View Kiala Pack & Ship web service logs'),
455 'description' => t('Allows users to view the logs made to an order.'),
456 'restrict access' => TRUE,
457 ),
458 'create kiala packship ws logs' => array(
459 'title' => t('Create Kiala Pack & Ship web service logs'),
460 'description' => t('Allows users to create the logs made to an order.'),
461 'restrict access' => TRUE,
462 ),
463 'delete kiala packship ws logs' => array(
464 'title' => t('Delete Kiala Pack & Ship web service logs'),
465 'description' => t('Allows users to delete logs on orders they can access.'),
466 'restrict access' => TRUE,
467 ),
468 );
469 }
470
471 /**
472 * Implements hook_entity_info().
473 */
474 function commerce_kiala_ps_entity_info() {
475 $return['commerce_kiala_ps_ws_log'] = array(
476 'module' => 'commerce_kiala_ps',
477 'label' => t('Commerce Kiala PS web service log'),
478 'base table' => 'commerce_kiala_ps_ws_log',
479 'entity class' => 'CommerceKialaPSWSLogEntity',
480 'controller class' => 'CommerceKialaPSWSLogEntityController',
481 'metadata controller class' => 'CommerceKialaPSWSLogMetadataController',
482 'views controller class' => FALSE,
483 'rules controller class' => 'EntityDefaultRulesController',
484 'features controller class' => 'EntityDefaultFeaturesController',
485 'fieldable' => FALSE,
486 'exportable' => FALSE,
487 'entity keys' => array(
488 'id' => 'log_id',
489 'bundle' => 'method',
490 'label' => 'log_id',
491 ),
492 'bundle keys' => array(
493 'bundle' => 'method',
494 ),
495 'bundles' => array(
496 'createOrder' => array(
497 'label' => t('createOrder'),
498 ),
499 ),
500 'view modes' => array(
501 'administrator' => array(
502 'label' => t('Administrator'),
503 'custom settings' => FALSE,
504 ),
505 ),
506 'access callback' => 'commerce_kiala_ps_ws_log_access',
507 'load hook' => 'commerce_kiala_ps_ws_log_load',
508 'permission labels' => array(
509 'singular' => t('kiala packship ws log'),
510 'plural' => t('kiala packship ws logs'),
511 ),
512 );
513
514 return $return;
515 }
516
517 /**
518 * Returns a list of web service log statuses
519 */
520 function commerce_kiala_ps_ws_log_status_options_list() {
521 $statuses = array(
522 'success' => t('Success'),
523 'error' => t('Error'),
524 );
525
526 return $statuses;
527 }
528
529 /**
530 * Load a single web service log entry
531 */
532 function commerce_kiala_ps_ws_log_load($id) {
533 return entity_load_single('commerce_kiala_ps_ws_log', $id) ;
534 }
535
536 /**
537 * Menu item title callback: returns the web servicew log ID for its pages.
538 *
539 * @param $log
540 * The log object as loaded via the URL wildcard.
541 * @return
542 * A page title of the format "Web service log ##".
543 */
544 function commerce_kiala_ps_ws_log_title($log) {
545 return t('Web service log @log_id', array('@log_id' => $log->log_id));
546 }
547
548 /**
549 * Generate an array for rendering the given log entity.
550 *
551 * @param $entity
552 * An array of entities to render.
553 * @param $view_mode
554 * A view mode as used by this entity type, e.g. 'full', 'teaser'...
555 * @param $langcode
556 * (optional) A language code to use for rendering. Defaults to the global
557 * content language of the current request.
558 * @param $page
559 * (optional) If set will control if the entity is rendered: if TRUE
560 * the entity will be rendered without its title, so that it can be embeded
561 * in another context. If FALSE the entity will be displayed with its title
562 * in a mode suitable for lists.
563 * If unset, the page mode will be enabled if the current path is the URI
564 * of the entity, as returned by entity_uri().
565 * This parameter is only supported for entities which controller is a
566 * EntityAPIControllerInterface.
567 * @return
568 * The renderable array, keyed by the entity type and by entity identifiers,
569 * for which the entity name is used if existing - see entity_id(). If there
570 * is no information on how to view an entity, FALSE is returned.
571 */
572 function commerce_kiala_ps_ws_log_view($entity, $view_mode = 'administrator', $langcode = NULL, $page = NULL) {
573 $entities = array($entity->log_id => $entity);
574 return entity_view('commerce_kiala_ps_ws_log', $entities, $view_mode, $langcode, $page);
575 }
576
577 /**
578 * Determines access for a variety of operations on web service logs.
579 *
580 * @param $op
581 * The operation being performed, one of view, update, create, or delete.
582 * @param $log
583 * The web service log to check.
584 * @param $account
585 * The user account attempting the operation; defaults to the current user.
586 *
587 * @return
588 * TRUE or FALSE indicating access for the operation.
589 */
590 function commerce_kiala_ps_ws_log_access($op, $log, $account = NULL) {
591 if (isset($log->order_id)) {
592 $order = commerce_order_load($log->order_id);
593 if (!$order) {
594 return FALSE;
595 }
596 }
597 else {
598 $order = NULL;
599 }
600
601 return commerce_kiala_ps_ws_log_order_access($op, $order, $account);
602 }
603
604 /**
605 * Determines access for a variety of operations for web service logs on a given order.
606 *
607 * @param $op
608 * The operation being performed, one of view, update, create, or delete.
609 * @param $order
610 * The order to check against (optional if $op == 'create').
611 * @param $account
612 * The user account attempting the operation; defaults to the current user.
613 *
614 * @return
615 * TRUE or FALSE indicating access for the operation.
616 *
617 * @see commerce_payment_transaction_order_access()
618 */
619 function commerce_kiala_ps_ws_log_order_access($op, $order, $account = NULL) {
620 global $user;
621
622 if (empty($account)) {
623 $account = clone($user);
624 }
625
626 // Grant administrators access to do anything.
627 if (user_access('administer kiala packship ws', $account)) {
628 return TRUE;
629 }
630
631 switch ($op) {
632 // Creating new logs.
633 case 'create':
634 if (user_access('create kiala packship ws logs', $account)) {
635 // We currently allow any user to create any log,
636 // regardless of the order, because entity_access() doesn't give us a
637 // way to discriminate on the order.
638 // @todo: find a way to prevent creating a log if the
639 // user doesn't have access to the order.
640 if (!isset($order) || commerce_order_access('update', $order, $account)) {
641 return TRUE;
642 }
643 }
644 break;
645
646 // Viewing payment transactions.
647 case 'view':
648 if (user_access('view kiala packship ws logs', $account)) {
649 if (commerce_order_access('view', $order, $account)) {
650 return TRUE;
651 }
652 }
653 break;
654
655 case 'update':
656 if (user_access('update kiala packship ws logs', $account)) {
657 if (commerce_order_access('view', $order, $account)) {
658 return TRUE;
659 }
660 }
661 break;
662
663 case 'delete':
664 if (user_access('delete kiala packship ws logs', $account)) {
665 if (commerce_order_access('update', $order, $account)) {
666 return TRUE;
667 }
668 }
669 break;
670 }
671
672 return FALSE;
673 }
674
675 /**
676 * Theme for commerce_kiala_ps_ws_log
677 */
678 function theme_commerce_kiala_ps_ws_log($vars) {
679 if (empty($vars['log']) || empty($vars['log']->log_id)) {
680 return '';
681 }
682
683 $log = $vars['log'];
684 return drupal_render(commerce_kiala_ps_ws_log_view($log, 'administrator', NULL, TRUE));
685 }
686
687 /**
688 * Order metadata callback
689 */
690 function commerce_kiala_ps_order_property_get($entity, array $options, $name) {
691 switch ($name) {
692 case 'kiala_packship_desktop_export_access':
693 return commerce_kiala_ps_desktop_order_export_access($entity);
694
695 case 'kiala_packship_ws_access':
696 return commerce_kiala_ps_ws_order_access($entity);
697
698 case 'kiala_packship_desktop_export':
699 // This will either return a string or an errors array.
700 return commerce_kiala_ps_build_desktop_export(array($entity));
701 }
702 }
703
704 /**
705 * Build the export string for a list of orders
706 *
707 * @param type $orders
708 * @return type
709 */
710 function commerce_kiala_ps_build_desktop_export($orders) {
711 $settings = commerce_kiala_settings();
712 $countries_enabled = $settings['shipping_countries_enabled'];
713
714 // In the export values are keyed only by position, so this mapping makes it
715 // possible to keep track of things by name.
716 $map = array(
717 'partnerId',
718 'partnerBarcode',
719 'parcelNumber',
720 'orderNumber',
721 'orderDate',
722 'invoiceNumber',
723 'invoiceDate',
724 'shipmentNumber',
725 'CODAmount',
726 'commercialValue',
727 'parcelWeight',
728 'parcelVolume',
729 'parcelDescription',
730 'customerId',
731 'customerName',
732 'customerFirstname',
733 'customerTitle',
734 'customerStreet',
735 'customerStreetnumber',
736 'customerExtraAddressLine',
737 'customerZip',
738 'customerCity',
739 'customerLocality',
740 'customerLanguage',
741 'customerPhone1',
742 'customerPhone2',
743 'customerPhone3',
744 'customerEmail1',
745 'customerEmail2',
746 'customerEmail3',
747 'positiveNotificationRequested',
748 'kialaPoint',
749 'backupKialaPoint',
750 );
751
752 $output_string = '';
753
754 foreach ($orders as $order) {
755 $wrapper = entity_metadata_wrapper('commerce_order', $order);
756
757 // partnerId
758 $export['partnerId'] = $settings['dspid'];
759
760 // parcelNumber
761 $export['parcelNumber'] = $settings['dspid'] . '_' . $order->order_id;
762
763 // orderNumber
764 $export['orderNumber'] = $order->order_id;
765
766 // orderDate
767 $timestamp = commerce_kiala_order_completed_date($order);
768
769 if (!$timestamp) {
770 $errors[] = t('The customer has not completed checkout for this order.');
771 }
772 else {
773 $export['orderDate'] = date('Ymd', $timestamp);
774 }
775
776 // CODAmount. Set to zero because commerce customer will just be paying for
777 // everything online.
778 $export['CODAmount'] = '0.00';
779
780 // commercialValue (order total amount)
781 $amount = commerce_currency_amount_to_decimal($wrapper->commerce_order_total->amount->value(), commerce_default_currency());
782 $export['commercialValue'] = number_format((float)$amount, 2, '.', '');
783
784 // parcelWeight
785 $weight = commerce_physical_order_weight($order, 'kg');
786
787 if (empty($weight['weight'])) {
788 $errors[] = t('A product in this order does not have a weight.');
789 }
790 $export['parcelWeight'] = number_format((float)$weight['weight'], 3, '.', '');
791
792 //parcelVolume (liters i.e. 1000 cc)
793 $volume = commerce_physical_order_volume($order, 'cm');
794 $liters = $volume['volume'] / 1000;
795 $export['parcelVolume'] = number_format((float)$liters, 3, '.', '');
796
797 // Customer fields
798 if (!empty($order->commerce_customer_shipping)) {
799 $export['customerId'] = $wrapper->commerce_customer_shipping->profile_id->value();
800
801 $address = $wrapper->commerce_customer_shipping->commerce_customer_address->value();
802 $export['customerName'] = commerce_kiala_ps_parse_name($address['name_line']);
803 $export['customerStreet'] = $address['thoroughfare'];
804 $export['customerExtraAddressLine'] = $address['premise'];
805 $export['customerZip'] = $address['postal_code'];
806 $export['customerCity'] = $address['locality'];
807
808 // customerLanguage (DSP language)
809 if (commerce_kiala_ps_language_combinations_match(language_default()->language, $address['country'])) {
810 $export['customerLanguage'] = language_default()->language;
811 }
812 else {
813 $errors[] = t('Language is not supported.');
814 }
815 }
816 else {
817 $errors[] = t('No shipping profile found.');
818 }
819
820 // customerEmail1
821 $export['customerEmail1'] = $order->mail;
822
823 // positiveNotificationRequested @TODO opt-in field
824 $export['positiveNotificationRequested'] = 'yes';
825
826 // kialaPoint
827 $export['kialaPoint'] = $wrapper->kiala_point_id->value();
828
829 // Allow modules to add to the export
830 drupal_alter('commerce_kiala_ps_desktop_export', $export, $order);
831
832 // Fill in missing values and sort by mapping order
833 foreach ($map as $key) {
834 if (isset($export[$key])) {
835 // Check for illegal characters
836 if (strstr($export[$key], '|')) {
837 $errors[] = t('Pipe character found in data, please remove and reinitiate export');
838 break;
839 }
840 $output[] = $export[$key];
841 }
842 else {
843 $output[] = '';
844 }
845 }
846
847 if (isset($errors)) {
848 return array('errors' => $errors);
849 }
850 }
851
852 // Convert to string
853 return implode('|', $output);
854 }
855
856 /**
857 * Kiala P&S Web Service request
858 *
859 * @param $order
860 * An order object
861 *
862 * @return
863 * A P&S Web Service response object
864 */
865 function commerce_kiala_ps_ws_ping_create_order($order) {
866 $method = 'createOrder';
867 $handler = new CommerceKialaPSWS($order);
868 $response = $handler->sendRequest($method);
869
870 $log_values = array(
871 'order_id' => $order->order_id,
872 'method' => $method,
873 'response' => $response,
874 );
875
876 if (isset($response->trackingNumber)) {
877 $log_values['tracking_number'] = $response->trackingNumber;
878 }
879
880 entity_create('commerce_kiala_ps_ws_log', $log_values)->save();
881
882 return $response;
883 }
884
885 /**
886 * Return an address name line string in "lastname firstname" format.
887 *
888 * @param type $name
889 * @return type
890 */
891 function commerce_kiala_ps_parse_name($name) {
892 // For common 2 part space separated names
893 $parts = explode(' ', $name);
894
895 if (count($parts) == 2) {
896 return $parts[1] . ' ' . $parts[0];
897 }
898
899 // Otherwise just leave as is.
900 return $name;
901 }
902
903 /**
904 * Return a list of support packship language-country combinations
905 *
906 * @return array
907 * @ref http://packandship.kiala.com/desktop/doc/technical/description-of-import-fields.html
908 */
909 function commerce_kiala_ps_language_combinations() {
910 return array(
911 'fr' => array('BE', 'FR'),
912 'nl' => array('NL', 'BE'),
913 'es' => array('ES'),
914 'ca' => array('ES'),
915 'de' => array('AT'),
916 'ru' => array('RU')
917 );
918 }
919
920 /**
921 * Determine whether a language and a country may be exported together.
922 *
923 * @param type $lang_code
924 * @param type $country_code
925 * @return type
926 */
927 function commerce_kiala_ps_language_combinations_match($lang_code, $country_code) {
928 $combinations = commerce_kiala_ps_language_combinations();
929
930 if (isset($combinations[$lang_code]) && in_array($country_code, $combinations[$lang_code])) {
931 return TRUE;
932 }
933 }
934
935 /**
936 * Fetch the date when the order became checkout complete
937 *
938 * @param type $order
939 * @return type
940 */
941 function commerce_kiala_order_completed_date($order) {
942 $results =
943 db_select('commerce_order_revision', 'c')
944 ->fields('c', array('revision_timestamp'))
945 ->condition('c.status', 'checkout_complete')
946 ->condition('c.order_id', $order->order_id)
947 ->orderBy('c.revision_timestamp')
948 ->range(0,1)
949 ->execute()
950 ->fetchAll();
951
952 if (!empty($results)) {
953 $revision = reset($results);
954 return $revision->revision_timestamp;
955 }
956 }