diff --git a/README.md b/README.md index b40fbe0..6a3e33e 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Wiaas implementation based on wordpress [woocommerce](https://woocommerce.com/) - MySQL server (5.7) - [Composer](http://getcomposer.org) - [WP CLI](https://wp-cli.org/#installing) +- [PHPUnit](https://phpunit.de/getting-started/phpunit-6.html) for Unit testing - NodeJS (for building & developing frontend) ## Local Docker setup @@ -224,4 +225,21 @@ If your feature requires some database updates that can be easiliy executed from 2) Add this function to `wiaas/includes/class-wiaas-db-update.php` with its timestamp. This way after `composer update-db` is executed your database update will be applied. - \ No newline at end of file + +#### Unit testing + +1) Install [PHPUnit](https://phpunit.de/getting-started/phpunit-6.html) + + wget -O phpunit https://phar.phpunit.de/phpunit-6.phar + cp phpunit /usr/local/bin/phpunit + sudo chmod +x /usr/local/bin/phpunit + +2) Setup wiaas plugin unit testing + + cd backend/app/plugins/wiaas + ./test/bin/setup.sh [db-root] [db-root-pass] + +Script will install test environment in `/tmp/wiaas-backend-test` + +3) Now you can run `phpunit` inside `wiaas` directory + diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php new file mode 100644 index 0000000..461a51d --- /dev/null +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-api.php @@ -0,0 +1,65 @@ + 'GET', + 'callback' => array(__CLASS__, 'get_next_actions_for_user'), + ) ); + } + + + public static function get_next_actions_for_user() { + $current_user = wp_get_current_user(); + + $field_filters = array(); + $field_filters[] = array( + 'key' => 'workflow_user_id_' . $current_user->ID, + 'value' => 'pending', + ); + + $user_roles = gravity_flow()->get_user_roles(); + foreach ( $user_roles as $user_role ) { + $field_filters[] = array( + 'key' => 'workflow_role_' . $user_role, + 'value' => 'pending', + ); + } + + $field_filters['mode'] = 'any'; + + $search_criteria = array(); + $search_criteria['field_filters'] = $field_filters; + $search_criteria['status'] = 'active'; + + $form_ids = gravity_flow()->get_workflow_form_ids(); + + $total_count = 7; + + + $entries = GFAPI::get_entries( $form_ids, $search_criteria, null, null, $total_count ); + + $data = array(); + foreach ($entries as $entry) { + $step = gravity_flow()->get_step( $entry['workflow_step'] ); + $data[] = array( + 'idOrder' => $entry['wiaas_delivery_order_id'], + 'orderNumber' => $entry['wiaas_delivery_order_id'], + 'status' => $entry['workflow_final_status'], + 'stepAction' => $step->get_name(), + ); + } + + $response = new WP_REST_Response( $data ); + + return $response; + } +} \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-controller.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-rest-delivery-process-controller.php deleted file mode 100644 index e69de29..0000000 diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-api.php b/backend/app/plugins/wiaas/includes/class-wiaas-api.php index b0722d1..8549440 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-api.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-api.php @@ -8,12 +8,41 @@ defined( 'ABSPATH' ) || exit; +/** + * API class + */ class Wiaas_API { + public static function init() { + + if ( ! class_exists( 'WP_REST_Server' ) ) { + return; + } + + self::_rest_api_includes(); + + // Init REST API routes. + add_action( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ), 10 ); + } + /** * Include REST API classes */ - private function rest_api_includes() { + private static function _rest_api_includes() { + #Delivery process controller + include_once dirname( __FILE__ ) . '/api/class-wiaas-rest-delivery-process-api.php'; } -} \ No newline at end of file + + public static function register_rest_routes() { + $controllers = array( + 'Wiass_REST_Delivery_Process_API' + ); + + foreach ( $controllers as $controller ) { + call_user_func(array($controller, 'register_routes')); + } + } +} + +Wiaas_API::init(); \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-db-update.php b/backend/app/plugins/wiaas/includes/class-wiaas-db-update.php index 9cd100d..4f54fe4 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-db-update.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-db-update.php @@ -5,9 +5,18 @@ defined( 'ABSPATH' ) || exit; class Wiaas_DB_Update { private static $db_updates = array( - '20180728222206' => 'wiaas_db_update_enable_product_by_user_role' + '20180728222206' => 'wiaas_db_update_enable_product_by_user_role', + '20180801222206' => 'wiaas_db_update_setup_gravity', + '20180802222206' => 'wiaas_db_update_add_delivery_process_forms' ); + public static function execute() { + $pending_db_updates = self::get_pending_db_updates(); + foreach ( $pending_db_updates as $update_callback ) { + self::execute_update($update_callback); + } + } + public static function get_pending_db_updates() { $active_db_version = get_option( 'wiaas_db_version', '0' ); $pending_db_updates = array(); diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php b/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php index 6e476cd..7c4c9e3 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php @@ -1,52 +1,156 @@ 'Wiaas Delivery Process Step Order', - 'is_numeric' => true, - 'update_entry_meta_callback' => null, - 'is_default_column' => false, // this column will be displayed by default on the entry list - 'filter' => array( - 'operators' => array( 'is' ), - ), - ); + public static function init() { + self::_register_delivery_process_step_type(); - $entry_meta[ 'wiaas_delivery_process_id' ] = array( - 'label' => 'Wiaas Delivery Process Id', - 'is_numeric' => true, - 'update_entry_meta_callback' => null, - 'is_default_column' => false, // this column will be displayed by default on the entry list - 'filter' => array( - 'operators' => array( 'is' ), - ), - ); - - return $entry_meta; -} - -function action_gflow_after_workflow_complete($entry_id, $form, $final_status) { - $entry = GFAPI::get_entry($entry_id); - $parent_entry_id = $entry['wiaas_delivery_process_id']; - if (empty($parent_entry_id)) { - return; + self::_init_hooks(); } + private static function _init_hooks() { + add_action('woocommerce_new_order', array( __CLASS__, 'create_delivery_process_for_order' )); - $api = new Gravity_Flow_API( $form['id'] ); - $current_step = $api->get_current_step( $entry ); + add_filter( 'gform_entry_meta', array(__CLASS__, 'extend_gravity_form_entry_meta'), 10, 2 ); + add_action( 'gravityflow_workflow_complete', array(__CLASS__, 'maybe_complete_parent_process_step'), 5, 3 ); + } + + /** + * Registers our Delivery Process Step Type as available Gravity Flow Step Type + */ + private static function _register_delivery_process_step_type() { + require_once( 'delivery-process/class-wiaas-delivery-process-step.php' ); + + Gravity_Flow_Steps::register( new Wiaas_Delivery_Process_Step() ); + } + + /** + * Retrieves delivery process instance for order + * + * @param $order_id + * + * @return array|null + */ + public static function get_order_delivery_process($order_id) { + + $process_entry_id = get_post_meta($order_id, 'wiaas_delivery_process_entry_id'); + if (!isset($process_entry_id)) { + return null; + } + + $process_instance = GFAPI::get_entry($process_entry_id); + + $process_form = GFAPI::get_form($process_instance['form_id']); + + $api = new Gravity_Flow_API($process_instance['form_id']); + + $steps_info = $api->get_steps(); + + $delivery_process = array( + 'id' => $process_form['id'], + 'name' => $process_form['title'], + 'steps' => array() + ); + + foreach ( $steps_info as $step_info ) { + $step = $api->get_step( $step_info->get_id(), $process_instance ); + + $info = $step->get_feed_meta(); + $delivery_process['steps'][] = array( + 'step_id' => $step->get_id(), + 'step_form_entry_id' => $step->get_target_form_entry_id() ?: null, + 'short_desc' => $info['step_name'], + 'full_desc' => $info['description'], + 'action_code' => $step->get_delivery_action_type(), + 'step_type' => $step->get_delivery_action_type() === 'manual' ? 'manual' : 'extraAction', + 'status' => $step->get_status() ?: 'inactive', + 'order_id' => $order_id, + 'actual_date' => $step->get_target_actual_date(), + 'comments' => $step->get_target_step_comments(), + ); + } + + return $delivery_process; + } + + /** + * Automatically create delivery process instance when order is created + * @param $order_id + */ + public static function create_delivery_process_for_order($order_id) { + $process_form = null; + $forms = GFFormsModel::search_forms( self::$process_form_title_prefix, true ); + $process_form = $forms[0]; + if(isset($process_form)) { + $order = wc_get_order( $order_id ); + $new_process_entry = array( + 'form_id' => $process_form->id, + '2' => $order->get_customer_id(), + 'wiaas_delivery_order_id' => $order_id, + ); + $process_entry_id = GFAPI::add_entry( $new_process_entry ); + + add_post_meta($order_id, 'wiaas_delivery_process_id', $process_form->id); + add_post_meta($order_id, 'wiaas_delivery_process_entry_id', $process_entry_id); + } + } + + /** + * Extends Gravity Form entry metadata with 'wiaas_delivery_process_id' + * + * This way we can track for each delivery step its parent process + * @param $entry_meta + * + * @return mixed + */ + public static function extend_gravity_form_entry_meta($entry_meta) { + $entry_meta[ 'wiaas_delivery_process_id' ] = array( + 'label' => 'Wiaas Delivery Process Id', + 'is_numeric' => true, + 'update_entry_meta_callback' => null, + 'is_default_column' => false, // this column will be displayed by default on the entry list + 'filter' => array( + 'operators' => array( 'is' ), + ), + ); + + $entry_meta[ 'wiaas_delivery_order_id' ] = array( + 'label' => 'Wiaas Delivery Process Order Id', + 'is_numeric' => true, + 'update_entry_meta_callback' => null, + 'is_default_column' => false, // this column will be displayed by default on the entry list + 'filter' => array( + 'operators' => array( 'is' ), + ), + ); + + return $entry_meta; + } + + /** + * Process parent process when single step workflow has completed + * @param $entry_id + * @param $form + * @param $final_status + */ + public static function maybe_complete_parent_process_step($entry_id, $form) { + $entry = GFAPI::get_entry($entry_id); + $parent_entry_id = $entry['wiaas_delivery_process_id']; + + if (empty($parent_entry_id)) { + return false; + } - if ( empty( $current_step ) ) { $parent_entry_id = absint( $parent_entry_id ); $parent_entry = GFAPI::get_entry( $parent_entry_id ); @@ -55,105 +159,4 @@ function action_gflow_after_workflow_complete($entry_id, $form, $final_status) { } } - -add_action( 'rest_api_init', 'wiaas_action_rest_api_init' ); - -function wiaas_action_rest_api_init() { - register_rest_route( 'wiaas', 'next-delivery-steps', array( - 'methods' => 'GET', - 'callback' => 'get_next_actions_for_user', - 'permission_callback' => null, - ) ); - - register_rest_route( 'wiaas', 'order-delivery-process/(?P[\d]+)', array( - 'args' => array( - 'id' => array( - 'description' => __( 'Unique identifier for the resource.', 'wiaas' ), - 'type' => 'integer', - ), - ), - array( - 'methods' => 'GET', - 'callback' => 'get_delivery_process_for_order', - 'permission_callback' => null, - ) - ) ); -} - -function get_next_actions_for_user() { - $current_user = wp_get_current_user(); - - $field_filters = array(); - $field_filters[] = array( - 'key' => 'workflow_user_id_' . $current_user->ID, - 'value' => 'pending', - ); - - $user_roles = gravity_flow()->get_user_roles(); - foreach ( $user_roles as $user_role ) { - $field_filters[] = array( - 'key' => 'workflow_role_' . $user_role, - 'value' => 'pending', - ); - } - - $field_filters['mode'] = 'any'; - - $search_criteria = array(); - $search_criteria['field_filters'] = $field_filters; - $search_criteria['status'] = 'active'; - - $form_ids = gravity_flow()->get_workflow_form_ids(); - - $total_count = 7; - - - $entries = GFAPI::get_entries( $form_ids, $search_criteria, null, null, $total_count ); - - $data = array(); - foreach ($entries as $entry) { - $step = gravity_flow()->get_step( $entry['workflow_step'] ); - $data[] = array( - 'idOrder' => $entry['wiaas_delivery_order_id'], - 'orderNumber' => $entry['wiaas_delivery_order_id'], - 'status' => $entry['workflow_final_status'], - 'stepAction' => $step->get_name(), - ); - } - - $response = new WP_REST_Response( $data ); - - return $response; -} - -function get_delivery_process_for_order($data) { - $order_id = $data["id"]; - - $process = GFAPI::get_entry(161); - - $api = new Gravity_Flow_API($process['form_id']); - - $steps_info = $api->get_steps(); - - $response = array(); - - foreach ( $steps_info as $step_info ) { - $step = $api->get_step( $step_info->get_id(), $process ); - - $info = $step->get_feed_meta(); - $response[] = array( - 'step_id' => $step->get_id(), - 'step_form_entry_id' => $step->get_target_form_entry_id() ?: null, - 'short_desc' => $info['step_name'], - 'full_desc' => $info['description'], - 'action_code' => $step->get_delivery_action_type(), - 'step_type' => $step->get_delivery_action_type() === 'manual' ? 'manual' : 'extraAction', - 'status' => $step->get_status() ?: 'inactive', - 'order_id' => $order_id, - 'actual_date' => $step->get_target_actual_date(), - 'comments' => $step->get_target_step_comments(), - ); - } - - return new WP_REST_Response( $response ); -} \ No newline at end of file +add_action( 'gravityflow_loaded', array('Wiaas_Delivery_Process', 'init') ); \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-order.php b/backend/app/plugins/wiaas/includes/class-wiaas-order.php new file mode 100644 index 0000000..b62e181 --- /dev/null +++ b/backend/app/plugins/wiaas/includes/class-wiaas-order.php @@ -0,0 +1,54 @@ +get_data(); + + # apply overrides + $data = self::_append_order_process($data, $order, $request); + + $response->set_data($data); + + return $response; + } + + /** + * Append order delivery process info if single order is requested + * @param $data + * @param $order + * @param $request + * + * @return mixed + */ + private static function _append_order_process($data, $order, $request) { + + # if this is response to `/order/[id]` + if (isset($request['id'])) { + $data['delivery-process'] = Wiaas_Delivery_Process::get_order_delivery_process($order->get_id()); + } + + return $data; + } +} + +Wiaas_Order::init(); \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_customer_acceptance_form.json b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_customer_acceptance_form.json new file mode 100644 index 0000000..0b7fe6b --- /dev/null +++ b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_customer_acceptance_form.json @@ -0,0 +1,387 @@ +{ + "0": { + "title": "DELIVERY ACTION TYPE: Customer acceptance", + "description": "The customer must accept the implementation before further actions can be taken. If the customer isn't satisfied, the problems or discrepancies must be fixed in order to gen an acceptance.", + "labelPlacement": "top_label", + "descriptionPlacement": "below", + "button": { + "type": "text", + "text": "Submit", + "imageUrl": "" + }, + "fields": [ + { + "type": "workflow_user", + "id": 2, + "label": "customer-id", + "adminLabel": "customer-id", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "administrative", + "inputs": null, + "choices": [ + ], + "formId": 10, + "description": "", + "allowsPrepopulate": true, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "customer-id", + "noDuplicates": false, + "defaultValue": "", + "conditionalLogic": "", + "failed_validation": "", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "", + "enablePrice": "", + "gravityflowUsersRoleFilter": "" + }, + { + "type": "date", + "id": 6, + "label": "Actual date", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "dateType": "datepicker", + "calendarIconType": "none", + "formId": 10, + "description": "", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "calendarIconUrl": "", + "dateFormat": "ymd_dash", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "" + }, + { + "type": "fileupload", + "id": 7, + "label": "Acceptance document", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "formId": 10, + "description": "Upload your acceptance document", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "maxFileSize": "", + "maxFiles": "", + "multipleFiles": false, + "allowedExtensions": "", + "productField": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "" + } + ], + "version": "2.3.2", + "id": 10, + "useCurrentUserAsAuthor": true, + "postContentTemplateEnabled": false, + "postTitleTemplateEnabled": false, + "postTitleTemplate": "", + "postContentTemplate": "", + "lastPageButton": null, + "pagination": null, + "firstPageCssClass": null, + "confirmations": [ + { + "id": "5b5f75f7494b7", + "name": "Default Confirmation", + "isDefault": true, + "type": "message", + "message": "Thanks for contacting us! We will get in touch with you shortly.", + "url": "", + "pageId": "", + "queryString": "" + } + ], + "notifications": [ + { + "id": "5b5f75f748cee", + "to": "{admin_email}", + "name": "Admin Notification", + "event": "form_submission", + "toType": "email", + "subject": "New submission from {form_title}", + "message": "{all_fields}" + } + ], + "feeds": { + "gravityflow": [ + { + "id": "22", + "form_id": "10", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Upload acceptance file", + "description": "", + "step_type": "user_input", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "type": "select", + "assignees": [ + "role|administrator", + "assignee_user_field|2" + ], + "editable_fields": [ + "5" + ], + "routing": "", + "assignee_policy": "any", + "highlight_editable_fields_enabled": "0", + "highlight_editable_fields_class": "green-triangle", + "instructionsEnable": "0", + "instructionsValue": "", + "display_fields_mode": "selected_fields", + "display_fields_selected": [ + "5" + ], + "default_status": "hidden", + "note_mode": "not_required", + "assignee_notification_enabled": "0", + "assignee_notification_from_name": "", + "assignee_notification_from_email": "{admin_email}", + "assignee_notification_reply_to": "", + "assignee_notification_bcc": "", + "assignee_notification_subject": "Upload order acceptance file", + "assignee_notification_message": "A new entry requires your input.", + "assignee_notification_disable_autoformat": "0", + "resend_assignee_emailEnable": "0", + "resend_assignee_emailValue": "7", + "resend_assignee_email_repeatEnable": "0", + "resend_assignee_email_repeatValue": "3", + "in_progress_notification_enabled": "0", + "in_progress_notification_type": "select", + "in_progress_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "in_progress_notification_from_name": "", + "in_progress_notification_from_email": "{admin_email}", + "in_progress_notification_reply_to": "", + "in_progress_notification_bcc": "", + "in_progress_notification_subject": "", + "in_progress_notification_message": "Entry {entry_id} has been updated and remains in progress.", + "in_progress_notification_disable_autoformat": "0", + "complete_notification_enabled": "0", + "complete_notification_type": "select", + "complete_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "complete_notification_from_name": "", + "complete_notification_from_email": "{admin_email}", + "complete_notification_reply_to": "", + "complete_notification_bcc": "", + "complete_notification_subject": "", + "complete_notification_message": "Entry {entry_id} has been updated completing the step.", + "complete_notification_disable_autoformat": "0", + "confirmation_messageEnable": "0", + "confirmation_messageValue": "Thank you.", + "expiration": "0", + "expiration_type": "delay", + "expiration_date": "", + "expiration_delay_offset": "7", + "expiration_delay_unit": "days", + "expiration_date_field_offset": "0", + "expiration_date_field_offset_unit": "hours", + "expiration_date_field_before_after": "after", + "status_expiration": "expired", + "destination_expired": "next", + "destination_complete": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + }, + { + "id": "30", + "form_id": "10", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Approve customer acceptance", + "description": "", + "step_type": "approval", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "type": "select", + "assignees": [ + "role|administrator" + ], + "routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "assignee_policy": "any", + "instructionsEnable": "0", + "instructionsValue": "Instructions: please review the values in the fields below and click on the Approve or Reject button", + "display_fields_mode": "all_fields", + "assignee_notification_enabled": "0", + "assignee_notification_from_name": "", + "assignee_notification_from_email": "{admin_email}", + "assignee_notification_reply_to": "", + "assignee_notification_bcc": "", + "assignee_notification_subject": "", + "assignee_notification_message": "A new entry is pending your approval. Please check your Workflow Inbox.", + "assignee_notification_disable_autoformat": "0", + "resend_assignee_emailEnable": "0", + "resend_assignee_emailValue": "7", + "resend_assignee_email_repeatEnable": "0", + "resend_assignee_email_repeatValue": "3", + "rejection_notification_enabled": "0", + "rejection_notification_type": "select", + "rejection_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "rejection_notification_from_name": "", + "rejection_notification_from_email": "{admin_email}", + "rejection_notification_reply_to": "", + "rejection_notification_bcc": "", + "rejection_notification_subject": "", + "rejection_notification_message": "Entry {entry_id} has been rejected", + "rejection_notification_disable_autoformat": "0", + "approval_notification_enabled": "0", + "approval_notification_type": "select", + "approval_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "approval_notification_from_name": "", + "approval_notification_from_email": "{admin_email}", + "approval_notification_reply_to": "", + "approval_notification_bcc": "", + "approval_notification_subject": "", + "approval_notification_message": "Entry {entry_id} has been approved", + "approval_notification_disable_autoformat": "0", + "revertEnable": "0", + "revertValue": "22", + "note_mode": "not_required", + "expiration": "0", + "expiration_type": "delay", + "expiration_date": "", + "expiration_delay_offset": "", + "expiration_delay_unit": "hours", + "expiration_date_field_offset": "0", + "expiration_date_field_offset_unit": "hours", + "expiration_date_field_before_after": "after", + "status_expiration": "rejected", + "destination_expired": "next", + "destination_rejected": "22", + "destination_approved": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + } + ] + } + }, + "version": "2.3.2.6" +} \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_manual_form.json b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_manual_form.json new file mode 100644 index 0000000..f975650 --- /dev/null +++ b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_manual_form.json @@ -0,0 +1,249 @@ +{ + "0": { + "title": "DELIVERY ACTION TYPE: Manual", + "description": "Manual process step action type", + "labelPlacement": "top_label", + "descriptionPlacement": "below", + "button": { + "type": "text", + "text": "Submit", + "imageUrl": "" + }, + "fields": [ + { + "type": "workflow_user", + "id": 2, + "label": "customer-id", + "adminLabel": "customer-id", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "administrative", + "inputs": null, + "choices": [ + { + "value": 2, + "text": "Customer Wiaas" + }, + { + "value": 1, + "text": "wpUser" + } + ], + "formId": 12, + "description": "", + "allowsPrepopulate": true, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "customer-id", + "noDuplicates": false, + "defaultValue": "", + "conditionalLogic": "", + "failed_validation": "", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "", + "enablePrice": "", + "gravityflowUsersRoleFilter": "" + }, + { + "type": "date", + "id": 3, + "label": "Actual Date", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "dateType": "datepicker", + "calendarIconType": "calendar", + "formId": 12, + "description": "", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "calendarIconUrl": "", + "dateFormat": "ymd_dash", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "" + } + ], + "version": "2.3.2", + "id": 12, + "useCurrentUserAsAuthor": true, + "postContentTemplateEnabled": false, + "postTitleTemplateEnabled": false, + "postTitleTemplate": "", + "postContentTemplate": "", + "lastPageButton": null, + "pagination": null, + "firstPageCssClass": null, + "notifications": [ + { + "id": "5b5f9ebc520f3", + "to": "{admin_email}", + "name": "Admin Notification", + "event": "form_submission", + "toType": "email", + "subject": "New submission from {form_title}", + "message": "{all_fields}" + } + ], + "confirmations": [ + { + "id": "5b5f9ebc52a80", + "name": "Default Confirmation", + "isDefault": true, + "type": "message", + "message": "Thanks for contacting us! We will get in touch with you shortly.", + "url": "", + "pageId": "", + "queryString": "" + } + ], + "feeds": { + "gravityflow": [ + { + "id": "27", + "form_id": "12", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Complete step", + "description": "", + "step_type": "approval", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "schedule_date_field": "3", + "type": "select", + "assignees": [ + "role|administrator" + ], + "routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "assignee_policy": "any", + "instructionsEnable": "0", + "instructionsValue": "Instructions: please review the values in the fields below and click on the Approve or Reject button", + "display_fields_mode": "all_fields", + "assignee_notification_enabled": "0", + "assignee_notification_from_name": "", + "assignee_notification_from_email": "{admin_email}", + "assignee_notification_reply_to": "", + "assignee_notification_bcc": "", + "assignee_notification_subject": "", + "assignee_notification_message": "A new entry is pending your approval. Please check your Workflow Inbox.", + "assignee_notification_disable_autoformat": "0", + "resend_assignee_emailEnable": "0", + "resend_assignee_emailValue": "7", + "resend_assignee_email_repeatEnable": "0", + "resend_assignee_email_repeatValue": "3", + "rejection_notification_enabled": "0", + "rejection_notification_type": "select", + "rejection_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "rejection_notification_from_name": "", + "rejection_notification_from_email": "{admin_email}", + "rejection_notification_reply_to": "", + "rejection_notification_bcc": "", + "rejection_notification_subject": "", + "rejection_notification_message": "Entry {entry_id} has been rejected", + "rejection_notification_disable_autoformat": "0", + "approval_notification_enabled": "0", + "approval_notification_type": "select", + "approval_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "approval_notification_from_name": "", + "approval_notification_from_email": "{admin_email}", + "approval_notification_reply_to": "", + "approval_notification_bcc": "", + "approval_notification_subject": "", + "approval_notification_message": "Entry {entry_id} has been approved", + "approval_notification_disable_autoformat": "0", + "note_mode": "not_required", + "expiration": "0", + "expiration_type": "delay", + "expiration_date": "", + "expiration_delay_offset": "", + "expiration_delay_unit": "hours", + "expiration_date_field_offset": "0", + "expiration_date_field_offset_unit": "hours", + "expiration_date_field_before_after": "after", + "expiration_date_field": "3", + "status_expiration": "rejected", + "destination_expired": "next", + "destination_rejected": "complete", + "destination_approved": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + } + ] + } + }, + "version": "2.3.2.6" +} \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_schedule_meeting.json b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_schedule_meeting.json new file mode 100644 index 0000000..4c9bff0 --- /dev/null +++ b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_schedule_meeting.json @@ -0,0 +1,403 @@ +{ + "0": { + "title": "DELIVERY ACTION TYPE: Schedule meeting", + "description": "Schedule meeting with customer", + "labelPlacement": "top_label", + "descriptionPlacement": "below", + "button": { + "type": "text", + "text": "Submit", + "imageUrl": "" + }, + "fields": [ + { + "type": "workflow_user", + "id": 3, + "label": "customer-id", + "adminLabel": "customer-id", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "administrative", + "inputs": null, + "choices": [ + { + "value": 2, + "text": "Customer Wiaas" + }, + { + "value": 1, + "text": "wpUser" + } + ], + "formId": 13, + "description": "", + "allowsPrepopulate": true, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "customer-id", + "noDuplicates": false, + "defaultValue": "", + "conditionalLogic": "", + "failed_validation": "", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "", + "gravityflowUsersRoleFilter": "" + }, + { + "type": "date", + "id": 4, + "label": "Actual Date", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "dateType": "datepicker", + "calendarIconType": "calendar", + "formId": 13, + "description": "", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "calendarIconUrl": "", + "dateFormat": "ymd_dash", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "" + }, + { + "type": "date", + "id": 5, + "label": "Schedule date", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "dateType": "datepicker", + "calendarIconType": "calendar", + "formId": 13, + "description": "", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "calendarIconUrl": "", + "dateFormat": "ymd_dash", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false + } + ], + "version": "2.3.2", + "id": 13, + "useCurrentUserAsAuthor": true, + "postContentTemplateEnabled": false, + "postTitleTemplateEnabled": false, + "postTitleTemplate": "", + "postContentTemplate": "", + "lastPageButton": null, + "pagination": null, + "firstPageCssClass": null, + "confirmations": [ + { + "id": "5b60b12baa00e", + "name": "Default Confirmation", + "isDefault": true, + "type": "message", + "message": "Thanks for contacting us! We will get in touch with you shortly.", + "url": "", + "pageId": "", + "queryString": "" + } + ], + "notifications": [ + { + "id": "5b60b12ba9850", + "to": "{admin_email}", + "name": "Admin Notification", + "event": "form_submission", + "toType": "email", + "subject": "New submission from {form_title}", + "message": "{all_fields}" + } + ], + "feeds": { + "gravityflow": [ + { + "id": "31", + "form_id": "13", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Broker proposes meeting date", + "description": "", + "step_type": "user_input", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "schedule_date_field": "4", + "type": "select", + "assignees": [ + "role|administrator" + ], + "editable_fields": [ + "4", + "5" + ], + "routing": "", + "assignee_policy": "all", + "highlight_editable_fields_enabled": "0", + "highlight_editable_fields_class": "green-triangle", + "instructionsEnable": "0", + "instructionsValue": "", + "display_fields_mode": "selected_fields", + "display_fields_selected": [ + "4", + "5" + ], + "default_status": "submit_buttons", + "note_mode": "not_required", + "assignee_notification_enabled": "0", + "assignee_notification_from_name": "", + "assignee_notification_from_email": "{admin_email}", + "assignee_notification_reply_to": "", + "assignee_notification_bcc": "", + "assignee_notification_subject": "", + "assignee_notification_message": "A new entry requires your input.", + "assignee_notification_disable_autoformat": "0", + "resend_assignee_emailEnable": "0", + "resend_assignee_emailValue": "7", + "resend_assignee_email_repeatEnable": "0", + "resend_assignee_email_repeatValue": "3", + "in_progress_notification_enabled": "0", + "in_progress_notification_type": "select", + "in_progress_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "in_progress_notification_from_name": "", + "in_progress_notification_from_email": "{admin_email}", + "in_progress_notification_reply_to": "", + "in_progress_notification_bcc": "", + "in_progress_notification_subject": "", + "in_progress_notification_message": "Entry {entry_id} has been updated and remains in progress.", + "in_progress_notification_disable_autoformat": "0", + "complete_notification_enabled": "0", + "complete_notification_type": "select", + "complete_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "complete_notification_from_name": "", + "complete_notification_from_email": "{admin_email}", + "complete_notification_reply_to": "", + "complete_notification_bcc": "", + "complete_notification_subject": "", + "complete_notification_message": "Entry {entry_id} has been updated completing the step.", + "complete_notification_disable_autoformat": "0", + "confirmation_messageEnable": "0", + "confirmation_messageValue": "Thank you.", + "expiration": "0", + "expiration_type": "delay", + "expiration_date": "", + "expiration_delay_offset": "", + "expiration_delay_unit": "hours", + "expiration_date_field_offset": "0", + "expiration_date_field_offset_unit": "hours", + "expiration_date_field_before_after": "after", + "expiration_date_field": "4", + "status_expiration": "complete", + "destination_expired": "next", + "destination_complete": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + }, + { + "id": "32", + "form_id": "13", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Customer approval for scheduled date", + "description": "", + "step_type": "approval", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "schedule_date_field": "4", + "type": "select", + "assignees": [ + "assignee_user_field|3" + ], + "routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "assignee_policy": "all", + "instructionsEnable": "0", + "instructionsValue": "Instructions: please review the values in the fields below and click on the Approve or Reject button", + "display_fields_mode": "selected_fields", + "display_fields_selected": [ + "5" + ], + "assignee_notification_enabled": "0", + "assignee_notification_from_name": "", + "assignee_notification_from_email": "{admin_email}", + "assignee_notification_reply_to": "", + "assignee_notification_bcc": "", + "assignee_notification_subject": "", + "assignee_notification_message": "A new entry is pending your approval. Please check your Workflow Inbox.", + "assignee_notification_disable_autoformat": "0", + "resend_assignee_emailEnable": "0", + "resend_assignee_emailValue": "7", + "resend_assignee_email_repeatEnable": "0", + "resend_assignee_email_repeatValue": "3", + "rejection_notification_enabled": "0", + "rejection_notification_type": "select", + "rejection_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "rejection_notification_from_name": "", + "rejection_notification_from_email": "{admin_email}", + "rejection_notification_reply_to": "", + "rejection_notification_bcc": "", + "rejection_notification_subject": "", + "rejection_notification_message": "Entry {entry_id} has been rejected", + "rejection_notification_disable_autoformat": "0", + "approval_notification_enabled": "0", + "approval_notification_type": "select", + "approval_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "approval_notification_from_name": "", + "approval_notification_from_email": "{admin_email}", + "approval_notification_reply_to": "", + "approval_notification_bcc": "", + "approval_notification_subject": "", + "approval_notification_message": "Entry {entry_id} has been approved", + "approval_notification_disable_autoformat": "0", + "revertEnable": "0", + "revertValue": "31", + "note_mode": "not_required", + "expiration": "0", + "expiration_type": "delay", + "expiration_date": "", + "expiration_delay_offset": "", + "expiration_delay_unit": "hours", + "expiration_date_field_offset": "0", + "expiration_date_field_offset_unit": "hours", + "expiration_date_field_before_after": "after", + "expiration_date_field": "4", + "status_expiration": "rejected", + "destination_expired": "next", + "destination_rejected": "31", + "destination_approved": "complete" + }, + "addon_slug": "gravityflow", + "event_type": null + } + ] + } + }, + "version": "2.3.2.6" +} \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_validate_questionnaire_form.json b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_validate_questionnaire_form.json new file mode 100644 index 0000000..340ad0d --- /dev/null +++ b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_action_validate_questionnaire_form.json @@ -0,0 +1,261 @@ +{ + "0": { + "title": "DELIVERY ACTION TYPE: Validate Questionnaire", + "description": "The configuration details submitted at ordering must be validated and any missing or incomplete information must be added.", + "labelPlacement": "top_label", + "descriptionPlacement": "below", + "button": { + "type": "text", + "text": "Submit", + "imageUrl": "" + }, + "fields": [ + { + "type": "workflow_user", + "id": 4, + "label": "customer-id", + "adminLabel": "customer-id", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "administrative", + "inputs": null, + "choices": [ + { + "value": 2, + "text": "Customer Wiaas" + }, + { + "value": 1, + "text": "wpUser" + } + ], + "formId": 9, + "description": "", + "allowsPrepopulate": true, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "customer-id", + "noDuplicates": false, + "defaultValue": "", + "conditionalLogic": "", + "failed_validation": "", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "", + "enablePrice": "", + "gravityflowUsersRoleFilter": "" + }, + { + "type": "date", + "id": 5, + "label": "Actual date", + "adminLabel": "", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "dateType": "datepicker", + "calendarIconType": "none", + "formId": 9, + "description": "", + "allowsPrepopulate": false, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "calendarIconUrl": "", + "dateFormat": "", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false + } + ], + "version": "2.3.2", + "id": 9, + "useCurrentUserAsAuthor": true, + "postContentTemplateEnabled": false, + "postTitleTemplateEnabled": false, + "postTitleTemplate": "", + "postContentTemplate": "", + "lastPageButton": null, + "pagination": null, + "firstPageCssClass": null, + "notifications": [ + { + "id": "5b5f68818822e", + "to": "{admin_email}", + "name": "Admin Notification", + "event": "form_submission", + "toType": "email", + "subject": "New submission from {form_title}", + "message": "{all_fields}" + } + ], + "confirmations": [ + { + "id": "5b5f688188e90", + "name": "Default Confirmation", + "isDefault": true, + "type": "message", + "message": "Thanks for contacting us! We will get in touch with you shortly.", + "url": "", + "pageId": "", + "queryString": "" + } + ], + "feeds": { + "gravityflow": [ + { + "id": "20", + "form_id": "9", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Approve customer configuration", + "description": "", + "step_type": "approval", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": { + "conditionalLogic": { + "actionType": "show", + "logicType": "all", + "rules": [ + { + "fieldId": "2", + "operator": "is", + "value": "administrator" + } + ] + } + }, + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "schedule_date_field": "5", + "type": "select", + "assignees": [ + "role|administrator" + ], + "routing": [ + { + "target": false, + "fieldId": "0", + "operator": "is", + "value": "", + "type": false, + "assignee": "user_id|2" + } + ], + "assignee_policy": "any", + "instructionsEnable": "1", + "instructionsValue": "Instructions: please review the values in the fields below and click on the Approve or Reject button", + "display_fields_mode": "selected_fields", + "assignee_notification_enabled": "0", + "assignee_notification_from_name": "", + "assignee_notification_from_email": "{admin_email}", + "assignee_notification_reply_to": "", + "assignee_notification_bcc": "", + "assignee_notification_subject": "", + "assignee_notification_message": "A new entry is pending your approval. Please check your Workflow Inbox.", + "assignee_notification_disable_autoformat": "0", + "resend_assignee_emailEnable": "0", + "resend_assignee_emailValue": "7", + "resend_assignee_email_repeatEnable": "0", + "resend_assignee_email_repeatValue": "3", + "rejection_notification_enabled": "0", + "rejection_notification_type": "select", + "rejection_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "rejection_notification_from_name": "", + "rejection_notification_from_email": "{admin_email}", + "rejection_notification_reply_to": "", + "rejection_notification_bcc": "", + "rejection_notification_subject": "", + "rejection_notification_message": "Entry {entry_id} has been rejected", + "rejection_notification_disable_autoformat": "0", + "approval_notification_enabled": "0", + "approval_notification_type": "select", + "approval_notification_routing": [ + { + "assignee": "user_id|2", + "fieldId": "0", + "operator": "is", + "value": "", + "type": "" + } + ], + "approval_notification_from_name": "", + "approval_notification_from_email": "{admin_email}", + "approval_notification_reply_to": "", + "approval_notification_bcc": "", + "approval_notification_subject": "", + "approval_notification_message": "Entry {entry_id} has been approved", + "approval_notification_disable_autoformat": "0", + "note_mode": "not_required", + "expiration": "0", + "expiration_type": "delay", + "expiration_date": "", + "expiration_delay_offset": "", + "expiration_delay_unit": "hours", + "expiration_date_field_offset": "0", + "expiration_date_field_offset_unit": "hours", + "expiration_date_field_before_after": "after", + "expiration_date_field": "5", + "status_expiration": "rejected", + "destination_expired": "next", + "destination_rejected": "complete", + "destination_approved": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + } + ] + } + }, + "version": "2.3.2.6" +} \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_process_normal_delivery_form.json b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_process_normal_delivery_form.json new file mode 100644 index 0000000..997729c --- /dev/null +++ b/backend/app/plugins/wiaas/includes/db-updates/data/delivery-forms/delivery_process_normal_delivery_form.json @@ -0,0 +1,338 @@ +{ + "0": { + "title": "DELIVERY PROCESS: Normal Delivery", + "description": "Normal delivery process", + "labelPlacement": "top_label", + "descriptionPlacement": "below", + "button": { + "type": "text", + "text": "Submit", + "imageUrl": "" + }, + "fields": [ + { + "type": "number", + "id": 1, + "label": "order-id", + "adminLabel": "order-id", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "numberFormat": "decimal_dot", + "formId": "11", + "description": "", + "allowsPrepopulate": true, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "order-id", + "noDuplicates": false, + "defaultValue": "", + "choices": "", + "conditionalLogic": "", + "enableCalculation": false, + "rangeMin": "", + "rangeMax": "", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "", + "enablePrice": "" + }, + { + "type": "workflow_user", + "id": 2, + "label": "customer-id", + "adminLabel": "customer-id", + "isRequired": false, + "size": "medium", + "errorMessage": "", + "visibility": "visible", + "inputs": null, + "choices": [ + { + "value": 2, + "text": "Customer Wiaas" + }, + { + "value": 1, + "text": "wpUser" + } + ], + "formId": "11", + "description": "", + "allowsPrepopulate": true, + "inputMask": false, + "inputMaskValue": "", + "inputType": "", + "labelPlacement": "", + "descriptionPlacement": "", + "subLabelPlacement": "", + "placeholder": "", + "cssClass": "", + "inputName": "customer-id", + "noDuplicates": false, + "defaultValue": "", + "conditionalLogic": "", + "failed_validation": "", + "productField": "", + "multipleFiles": false, + "maxFiles": "", + "calculationFormula": "", + "calculationRounding": "", + "enableCalculation": "", + "disableQuantity": false, + "displayAllCategories": false, + "useRichTextEditor": false, + "displayOnly": "", + "enablePrice": "", + "gravityflowUsersRoleFilter": "" + } + ], + "version": "2.3.2.6", + "id": "11", + "useCurrentUserAsAuthor": true, + "postContentTemplateEnabled": false, + "postTitleTemplateEnabled": false, + "postTitleTemplate": "", + "postContentTemplate": "", + "lastPageButton": null, + "pagination": null, + "firstPageCssClass": null, + "is_active": "1", + "date_created": "2018-07-30 20:53:56", + "is_trash": "0", + "notifications": [ + { + "id": "5b5f7ae4baced", + "to": "{admin_email}", + "name": "Admin Notification", + "event": "form_submission", + "toType": "email", + "subject": "New submission from {form_title}", + "message": "{all_fields}", + "isActive": false + } + ], + "confirmations": [ + { + "id": "5b5f7ae4bb79e", + "name": "Default Confirmation", + "isDefault": true, + "type": "message", + "message": "Thanks for contacting us! We will get in touch with you shortly.", + "url": "", + "pageId": "", + "queryString": "" + } + ], + "feeds": { + "gravityflow": [ + { + "id": "28", + "form_id": "11", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Validate customer configuration information", + "description": "Validate customer configuration information", + "step_type": "wiaas_delivery_step", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "instructionsEnable": "0", + "instructionsValue": "", + "target_form_id": "9", + "store_new_entry_idEnable": "1", + "new_entry_id_field": "6", + "destination_complete": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + }, + { + "id": "33", + "form_id": "11", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Wait for installation to be scheduled and confirmed", + "description": "Wait for installation to be scheduled and confirmed", + "step_type": "wiaas_delivery_step", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "instructionsEnable": "0", + "instructionsValue": "", + "target_form_id": "12", + "store_new_entry_idEnable": "0", + "new_entry_id_field": "", + "destination_complete": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + }, + { + "id": "34", + "form_id": "11", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Installation", + "description": " Installation", + "step_type": "wiaas_delivery_step", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "instructionsEnable": "0", + "instructionsValue": "", + "target_form_id": "12", + "store_new_entry_idEnable": "0", + "new_entry_id_field": "", + "destination_complete": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + }, + { + "id": "29", + "form_id": "11", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Customer acceptance", + "description": "Customer acceptance", + "step_type": "wiaas_delivery_step", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "target_form_id": "10", + "store_new_entry_idEnable": "1", + "new_entry_id_field": "7", + "destination_complete": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + }, + { + "id": "36", + "form_id": "11", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Customer training", + "description": "Customer training", + "step_type": "wiaas_delivery_step", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "instructionsEnable": "0", + "instructionsValue": "", + "target_form_id": "12", + "store_new_entry_idEnable": "0", + "new_entry_id_field": "", + "destination_complete": "next", + "feedName": " - Copy 1" + }, + "addon_slug": "gravityflow", + "event_type": null + }, + { + "id": "35", + "form_id": "11", + "is_active": "1", + "feed_order": "0", + "meta": { + "step_name": "Set start\/stop dates for contracts", + "description": "Set start\/stop dates for contracts", + "step_type": "wiaas_delivery_step", + "step_highlight": "0", + "step_highlight_type": "color", + "step_highlight_color": "#dd3333", + "feed_condition_conditional_logic": "0", + "feed_condition_conditional_logic_object": [], + "scheduled": "0", + "schedule_type": "delay", + "schedule_date": "", + "schedule_delay_offset": "", + "schedule_delay_unit": "hours", + "schedule_date_field_offset": "0", + "schedule_date_field_offset_unit": "hours", + "schedule_date_field_before_after": "after", + "instructionsEnable": "0", + "instructionsValue": "", + "target_form_id": "12", + "store_new_entry_idEnable": "0", + "new_entry_id_field": "", + "destination_complete": "next" + }, + "addon_slug": "gravityflow", + "event_type": null + } + ] + } + }, + "version": "2.3.2.6" +} \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php b/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php index 6b03890..c537822 100644 --- a/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php +++ b/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-functions.php @@ -12,4 +12,68 @@ */ function wiaas_db_update_enable_product_by_user_role() { update_option('wcj_product_by_user_role_enabled', 'yes'); +} + +function wiaas_db_update_setup_gravity() { + // Gravity Form settings + update_option('gform_pending_installation', false); + update_option( 'gform_enable_background_updates', false ); + update_option('rg_gforms_enable_akismet', 0); + update_option('rg_gforms_currency', 'USD'); + + // Gravity Flow settings + update_option('gravityflow_pending_installation', false); +} + +function wiaas_db_update_add_delivery_process_forms() { + $action_type_forms_files = array( + 'delivery_action_customer_acceptance_form', + 'delivery_action_schedule_meeting', + 'delivery_action_validate_questionnaire_form', + 'delivery_action_manual_form', + ); + + // Since import action will generate form with new id, we need to remember this mapping + // so we can update process delivery steps to point to correct form ids + $action_type_forms_ids_mappings = array(); + + $process_forms_files = array( + 'delivery_process_normal_delivery_form' + ); + + $created_forms = array(); + + // import forms for delivery action types + foreach ($action_type_forms_files as $action_type_form_file) { + $form_json = file_get_contents( dirname( __FILE__ ) . "/data/delivery-forms/" . $action_type_form_file . '.json' ); + + $form_meta = json_decode( $form_json, true ); + $form_meta = $form_meta[0]; + + $form_id = GFAPI::add_form($form_meta); + + $created_forms[] = GFAPI::get_form($form_id); + + $action_type_forms_ids_mappings[$form_meta['id']] = $form_id; + } + + // import forms for delivery process + foreach ($process_forms_files as $process_form_file) { + $form_json = file_get_contents( dirname( __FILE__ ) . "/data/delivery-forms/" . $process_form_file . '.json' ); + + $form_meta = json_decode( $form_json, true ); + $form_meta = $form_meta[0]; + + // update delivery steps forms ids with correct values + foreach ($form_meta['feeds']['gravityflow'] as $key => $process_step_meta) { + $process_step_target_form_id = $form_meta['feeds']['gravityflow'][$key]['meta']['target_form_id']; + $form_meta['feeds']['gravityflow'][$key]['meta']['target_form_id'] = $action_type_forms_ids_mappings[$process_step_target_form_id]; + } + + $form_id = GFAPI::add_form($form_meta); + + $created_forms[] = GFAPI::get_form($form_id); + } + + do_action('gform_forms_post_import', $created_forms); } \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/delivery-process/class-wiaas-delivery-process-step.php b/backend/app/plugins/wiaas/includes/delivery-process/class-wiaas-delivery-process-step.php index 60a0648..ce887a1 100644 --- a/backend/app/plugins/wiaas/includes/delivery-process/class-wiaas-delivery-process-step.php +++ b/backend/app/plugins/wiaas/includes/delivery-process/class-wiaas-delivery-process-step.php @@ -2,8 +2,14 @@ class Wiaas_Delivery_Process_Step extends Gravity_Flow_Step { + /** + * Code for Wiaas Delivery Process Step type + * @var string + */ public $_step_type = 'wiaas_delivery_step'; + private static $delivery_action_form_title_prefix = 'DELIVERY ACTION TYPE:'; + private static $delivery_action_types = array( 'DELIVERY ACTION TYPE: Customer acceptance' => 'customer-acceptance', 'DELIVERY ACTION TYPE: Validate Questionnaire' => 'validate-questionnaire', @@ -11,15 +17,31 @@ class Wiaas_Delivery_Process_Step extends Gravity_Flow_Step { 'DELIVERY ACTION TYPE: Schedule meeting' => 'schedule-meeting' ); + public static function get_delivery_action_types() { + return array_keys(self::$delivery_action_types); + } + + public static function get_delivery_action_type_prefix() { + return self::$delivery_action_form_title_prefix; + } + + /** + * Returns label for Wiass Delivery Process Step + * @return string + */ public function get_label() { return esc_html__( 'Wiaas Delivery Step', 'wiaas' ); } + /** + * Returns settings for wiaas delivery process step + * @return array + */ public function get_settings() { $settings_api = $this->get_common_settings_api(); - $forms = $this->get_forms(); + $forms = $this->get_target_forms_choices(); $form_choices[] = array( 'label' => esc_html__( 'Select a Form', 'wiaas' ), 'value' => '' ); foreach ( $forms as $form ) { $form_choices[] = array( 'label' => $form->title, 'value' => $form->id ); @@ -45,7 +67,7 @@ class Wiaas_Delivery_Process_Step extends Gravity_Flow_Step { ), array( 'name' => 'target_form_id', - 'label' => esc_html__( 'Form', 'wiaas' ), + 'label' => esc_html__( 'Action', 'wiaas' ), 'type' => 'select', 'onchange' => "jQuery(this).closest('form').submit();", 'choices' => $form_choices, @@ -53,48 +75,40 @@ class Wiaas_Delivery_Process_Step extends Gravity_Flow_Step { ), ); - $settings['fields'][] = array( - 'name' => 'store_new_entry_id', - 'label' => esc_html__( 'Store New Entry ID', 'wiaas' ), - 'type' => 'checkbox_and_container', - 'checkbox' => array( - 'label' => esc_html__( 'Store the ID of the new entry.', 'wiaas' ), - ), - 'settings' => array( - array( - 'name' => 'new_entry_id_field', - 'type' => 'field_select', - 'args' => array( - 'input_types' => array( - 'hidden', - ), - ), - ), - ), - ); - return $settings; } + /** + * Process Wiass Delivery Process Step + * + * + * @return bool + */ function process() { $form = $this->get_form(); $entry = $this->get_entry(); $target_form = GFAPI::get_form( $this->target_form_id ); + + # if target form is not valid just finish the step + if (!$target_form) { + return true; + } + + # create new entry for target form with populated value for customer-id from parent entry $new_entry = array( 'form_id' => $this->target_form_id, 'wiaas_delivery_process_id' => $this->get_entry_id(), + 'wiaas_delivery_order_id' => $entry['wiaas_delivery_order_id'], ); $customer_id_value = null; if ( is_array( $form['fields'] ) ) { foreach ( $form['fields'] as $field ) { - if (GFCommon::get_label( $field ) === 'order-id') { - $new_entry['wiaas_delivery_order_id'] = $entry[$field->id]; - } if (GFCommon::get_label( $field ) === 'customer-id') { $customer_id_value = $entry[$field->id]; + break; } } } @@ -103,6 +117,7 @@ class Wiaas_Delivery_Process_Step extends Gravity_Flow_Step { foreach ( $target_form['fields'] as $field ) { if (GFCommon::get_label( $field ) === 'customer-id') { $new_entry[$field->id] = $customer_id_value; + break; } } } @@ -117,36 +132,62 @@ class Wiaas_Delivery_Process_Step extends Gravity_Flow_Step { $note = $this->get_name() . ': ' . esc_html__( 'started.', 'wiaas' ); $this->add_note( $note ); + + # return false since we wait for workflow of target entry to be complete first return false; } + /** + * Evaluates current step status based on target form entry status + * + * If target form entry has associated workflow current step will complete its status + * only when target form entry workflow is completed + * @return string + */ public function status_evaluation() { + + # retrieve target form entry to check its workflow status $target_form_entry = $this->get_target_form_entry(); - if(is_wp_error($target_form_entry)) { + # if there is no target form entry just complete the step + if(!$target_form_entry) { return 'complete'; } + # retrieve target form entry workflow status $api = new Gravity_Flow_API( $this->target_form_id ); $status = $api->get_status($target_form_entry); - if ( $status === 'complete' || $status === 'approved' ) { - return 'complete'; - } - - return 'pending'; + # status is complete only if target entry flow is complete + return $status === 'complete' || $status === 'approved' ? 'complete' : 'pending'; } + /** + * Expands step entry with additional metadata to track created target entry id + * @param array $entry_meta + * @param int $form_id + * + * @return array + */ public function get_entry_meta($entry_meta, $form_id) { - $entry_meta['wiaas_delivery_step_' . $this->get_id() .'_entry_id'] = null; + if ($form_id === $this->get_form_id()) { + $entry_meta['wiaas_delivery_step_' . $this->get_id() .'_entry_id'] = null; + } return $entry_meta; } - public function get_forms() { - $forms = GFFormsModel::get_forms(); - return $forms; + /** + * Retrieves forms that are valid options for delivery step action + * @return array + */ + public function get_target_forms_choices() { + return GFFormsModel::search_forms(self::$delivery_action_form_title_prefix, true); } + /** + * Retrieves delivery action type that is executed with this step + * @return string + */ public function get_delivery_action_type() { $target_form = GFAPI::get_form( $this->target_form_id ); return self::$delivery_action_types[$target_form['title']]; @@ -183,11 +224,26 @@ class Wiaas_Delivery_Process_Step extends Gravity_Flow_Step { return $comments; } + /** + * Retrieves target form entry created when step was started + * @return array|null + */ public function get_target_form_entry() { - return GFAPI::get_entry($this->get_target_form_entry_id()); + $entry = GFAPI::get_entry($this->get_target_form_entry_id()); + if(is_wp_error($entry)) { + return null; + } + return $entry; } + + /** + * Retrieves target form entry id created when step was started + * @return int + */ public function get_target_form_entry_id() { - return gform_get_meta($this->get_entry_id(), 'wiaas_delivery_step_' . $this->get_id() .'_entry_id'); + $value = gform_get_meta($this->get_entry_id(), 'wiaas_delivery_step_' . $this->get_id() .'_entry_id'); + + return absint($value); } } \ No newline at end of file diff --git a/backend/app/plugins/wiaas/phpcs.xml.dist b/backend/app/plugins/wiaas/phpcs.xml.dist new file mode 100644 index 0000000..4f1d0e5 --- /dev/null +++ b/backend/app/plugins/wiaas/phpcs.xml.dist @@ -0,0 +1,17 @@ + + + Generally-applicable sniffs for WordPress plugins + + + + + + + . + + + + + */node_modules/* + */vendor/* + diff --git a/backend/app/plugins/wiaas/phpunit.xml.dist b/backend/app/plugins/wiaas/phpunit.xml.dist new file mode 100644 index 0000000..4acada6 --- /dev/null +++ b/backend/app/plugins/wiaas/phpunit.xml.dist @@ -0,0 +1,15 @@ + + + + + ./tests/unit-tests + + + diff --git a/backend/app/plugins/wiaas/tests/bin/setup.sh b/backend/app/plugins/wiaas/tests/bin/setup.sh new file mode 100755 index 0000000..2ac2023 --- /dev/null +++ b/backend/app/plugins/wiaas/tests/bin/setup.sh @@ -0,0 +1,141 @@ +#!/usr/bin/env bash + +if [ $# -lt 2 ]; then + echo "usage: $0 " + exit 1 +fi + +DB_USER=$1 +DB_PASS=$2 +WP_TESTS_TAG="tags/4.9.7" + +# Get temp directory +TMPDIR=${TMPDIR-/tmp} +TMPDIR=$(echo $TMPDIR | sed -e "s/\/$//") + +# Evaluate current directory +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# Evaluate application root directory +WEB_ROOT_DIR="$( dirname "$( dirname "$( dirname "$( dirname "$( dirname "$DIR" )" )" )" )" )" +WP_CORE_DIR="$WEB_ROOT_DIR"/wp + +# Location where wordpress testing suite will be installed +WP_TESTS_DIR=${WP_TESTS_DIR-$TMPDIR/wordpress-tests-lib} +WP_TEST_APPLICATION_DIR=${WP_TEST_APPLICATION_DIR-$TMPDIR/wiaas-backend-test} + +download() { + if [ `which curl` ]; then + curl -s "$1" > "$2"; + elif [ `which wget` ]; then + wget -nv -O "$2" "$1" + fi +} + +set -ex + +# Since test enviroment needs to start with fresh setup +# we will install application in /tmp/ folder and execute all migrations +setup_test_application() { + rm -rf "$WP_TEST_APPLICATION_DIR" + + mkdir "$WP_TEST_APPLICATION_DIR" + + mkdir "$WP_TEST_APPLICATION_DIR"/app + + cp -r "$WEB_ROOT_DIR/app/mu-plugins" "$WP_TEST_APPLICATION_DIR/app/mu-plugins" + + mkdir "$WP_TEST_APPLICATION_DIR"/app/plugins + cp -r "$WEB_ROOT_DIR"/app/plugins/wiaas "$WP_TEST_APPLICATION_DIR"/app/plugins/wiaas + + cp -r "$WEB_ROOT_DIR"/app/plugins/gravityflow "$WP_TEST_APPLICATION_DIR"/app/plugins/gravityflow + cp -r "$WEB_ROOT_DIR"/app/plugins/gravityforms "$WP_TEST_APPLICATION_DIR"/app/plugins/gravityforms + + mkdir "$WP_TEST_APPLICATION_DIR"/app/themes + + mkdir "$WP_TEST_APPLICATION_DIR"/app/uploads + + cp -r "$WEB_ROOT_DIR"/config "$WP_TEST_APPLICATION_DIR"/config + sed -i "s|define('WP_ENV', env('WP_ENV') ?: 'development');|define('WP_ENV', 'test');|" "$WP_TEST_APPLICATION_DIR"/config/application.php + + cp "$WEB_ROOT_DIR/composer.json" "$WP_TEST_APPLICATION_DIR/composer.json" + cp "$WEB_ROOT_DIR/composer.lock" "$WP_TEST_APPLICATION_DIR/composer.lock" + cp "$WEB_ROOT_DIR/index.php" "$WP_TEST_APPLICATION_DIR/index.php" + cp "$WEB_ROOT_DIR/wp-config.php" "$WP_TEST_APPLICATION_DIR/wp-config.php" + cp "$WEB_ROOT_DIR/wp-cli.yml" "$WP_TEST_APPLICATION_DIR/wp-cli.yml" + + { + echo "MYSQL_DATABASE=wordpress_test" + echo "MYSQL_USER=wp_admin_test" + echo "MYSQL_PASSWORD=wp_admin_test_password" + echo "WP_AUTH_KEY=test" + echo "WP_SECURE_AUTH_KEY=test" + echo "WP_LOGGED_IN_KEY=test" + echo "WP_NONCE_KEY=test" + echo "WP_AUTH_SALT=test" + echo "WP_SECURE_AUTH_SALT=test" + echo "WP_LOGGED_IN_SALT=test" + echo "WP_NONCE_SALT=test" + echo "WP_JWT_AUTH_SECRET_KEY=test" + } >> "$WP_TEST_APPLICATION_DIR/.env" + +} + + +install_test_suite() { + # set up testing suite if it doesn't yet exist + if [ ! -d $WP_TESTS_DIR ]; then + # set up testing suite + mkdir -p $WP_TESTS_DIR + svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes + svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/data/ $WP_TESTS_DIR/data + fi + # set up testing environment wp-config entry point file if it does not exist + if [ ! -f "$WP_TESTS_DIR"/wp-tests-config.php ]; then + # init testing suite entry point settings file + { + echo "> "$WP_TESTS_DIR"/wp-tests-config.php + + fi +} + +setup_test_db() { + # create db user if not exists + mysql -u "$DB_USER" -p"$DB_PASS" --execute="CREATE USER IF NOT EXISTS wp_admin_test@localhost IDENTIFIED BY 'wp_admin_test_password';" + # delete database if it exists + mysql -u "$DB_USER" -p"$DB_PASS" --execute="DROP DATABASE IF EXISTS wordpress_test;" + # create database + mysql -u "$DB_USER" -p"$DB_PASS" --execute="CREATE DATABASE wordpress_test;GRANT ALL PRIVILEGES ON wordpress_test.* TO wp_admin_test@localhost;" + # seed database + mysql -u "$DB_USER" -p"$DB_PASS" wordpress_test < "$WEB_ROOT_DIR/../database/clean-dump.sql" +} + +migrate_test_db() { + cd "$WP_TEST_APPLICATION_DIR" + + composer install + + # Run this so ony pending database schema can be loaded + composer update-db +} + +setup_test_application + +install_test_suite + +setup_test_db + +migrate_test_db \ No newline at end of file diff --git a/backend/app/plugins/wiaas/tests/bootstrap.php b/backend/app/plugins/wiaas/tests/bootstrap.php new file mode 100644 index 0000000..e2beec6 --- /dev/null +++ b/backend/app/plugins/wiaas/tests/bootstrap.php @@ -0,0 +1,43 @@ +form_id = GFAPI::add_form(array( + 'title' => 'Delivery Process Step Test Form', + )); + $form_entry_id = GFAPI::add_entry(array( + 'form_id' => $this->form_id, + )); + + $this->target_form_id = GFFormsModel::search_forms( + 'DELIVERY ACTION TYPE: Manual', + true)[0]->id; + + + $this->step = Gravity_Flow_Steps::create( array( + 'form_id'=> $this->form_id, + 'is_active'=> '1', + 'meta' => array( + 'step_name' => 'Test Wiaas Delivery Process Step', + 'description' => 'Test Wiaas Delivery Process Step', + 'step_type' => 'wiaas_delivery_step', + 'target_form_id' => $this->target_form_id + ) + ), GFAPI::get_entry($form_entry_id)); + } + + private function _get_target_entry_meta_key() { + return 'wiaas_delivery_step_' . $this->step->get_id() .'_entry_id'; + } + + /** + * @covers Wiaas_Delivery_Process_Step::get_settings + */ + function test_settings_options_are_valid() { + + $this->assertEquals(get_class($this->step), 'Wiaas_Delivery_Process_Step'); + + $this->assertEquals($this->step->is_active(), true); + + $this->assertEquals($this->step->get_name(), 'Test Wiaas Delivery Process Step'); + + $this->assertEquals($this->step->description, 'Test Wiaas Delivery Process Step'); + + $this->assertEquals($this->step->target_form_id, $this->target_form_id); + + $this->assertEquals($this->step->get_label(), 'Wiaas Delivery Step'); + + #$this->assertEquals($step->is_visible_to_customer, true); + } + + /** + * @covers Wiaas_Delivery_Process_Step::get_target_forms_choices + */ + function test_target_forms_choices_are_valid() { + + $target_forms_choices = $this->step->get_target_forms_choices(); + + $available_action_types = Wiaas_Delivery_Process_Step::get_delivery_action_types(); + + $this->assertEquals(sizeof($target_forms_choices), sizeof($available_action_types)); + + foreach ($target_forms_choices as $target_forms_choice) { + $this->assertTrue(in_array($target_forms_choice->title, $available_action_types)); + } + } + + /** + * @covers Wiaas_Delivery_Process_Step::get_entry_meta + */ + function test_entry_meta_skipped_for_non_parent_form() { + $meta = array( + 'test' => 'test' + ); + + # Since this is not parent form id function should return unchanged meta + $this->assertEquals($meta, $this->step->get_entry_meta($meta, 55)); + } + + /** + * @covers Wiaas_Delivery_Process_Step::get_entry_meta + */ + function test_entry_meta_added_for_parent_form() { + $meta = array( + 'test' => 'test' + ); + $expected_meta = array( + 'test' => 'test', + 'wiaas_delivery_step_' . $this->step->get_id() .'_entry_id' => null + ); + + $this->assertEquals($expected_meta, $this->step->get_entry_meta($meta, $this->step->get_form_id())); + } + + /** + * @covers Wiaas_Delivery_Process_Step::process + */ + function test_process_with_no_target_form() { + $this->step->target_form_id = ''; + + $this->assertTrue($this->step->process()); + + # check that entry metadata is not updated + $target_entry_meta_key = $this->_get_target_entry_meta_key(); + $value = gform_get_meta($this->step->get_entry_id(), $target_entry_meta_key); + $this->assertFalse($value); + } + + /** + * @covers Wiaas_Delivery_Process_Step::process + */ + function test_process_with_target_form() { + # check that processing step returns false since it will wait for target form entry workflow to complete + $this->assertFalse($this->step->process()); + + # check that entry metadata is updated with correct target entry value + $target_entry_meta_key = $this->_get_target_entry_meta_key(); + $value = gform_get_meta($this->step->get_entry_id(), $target_entry_meta_key); + $target_entry_id = absint($value); + $this->assertGreaterThan(0, $target_entry_id); + + # check that entry metadata key for target entry id points to valid entry + $entry = GFAPI::get_entry($target_entry_id); + $this->assertFalse(is_wp_error($entry)); + } + + /** + * @covers Wiaas_Delivery_Process_Step::status_evaluation + */ + function test_status_evaluation_with_no_target_form() { + $this->step->target_form_id = ''; + + $this->step->process(); + + $this->assertEquals($this->step->status_evaluation(), 'complete'); + } + + /** + * @covers Wiaas_Delivery_Process_Step::status_evaluation + */ + function test_status_evaluation_with_target_form() { + $this->step->process(); + + # check that step status is now pending + $this->assertEquals($this->step->status_evaluation(), 'pending'); + + # complete target entry workflow + $api = new Gravity_Flow_API( $this->step->target_form_id ); + $target_form_entry = $this->step->get_target_form_entry(); + $this->assertEquals($api->get_status($target_form_entry), 'pending'); + + gform_update_meta($target_form_entry['id'], 'workflow_role_administrator', 'approved'); + $target_entry_current_step = $api->get_current_step($target_form_entry); + $target_entry_current_step->refresh_entry(); + + # check that step status is now complete + $this->assertEquals($this->step->status_evaluation(), 'complete'); + } +} diff --git a/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-delivery-process.php b/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-delivery-process.php new file mode 100644 index 0000000..dd2fac6 --- /dev/null +++ b/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-delivery-process.php @@ -0,0 +1,156 @@ +process_form = GFFormsModel::search_forms( + 'DELIVERY PROCESS: Normal Delivery', + true)[0]; + + $this->step_form = GFFormsModel::search_forms( + 'DELIVERY ACTION TYPE: Manual', + true)[0]; + + $process_form_instance_id = GFAPI::add_entry(array( + 'form_id' => $this->process_form->id, + )); + + $this->process_form_instance = GFAPI::get_entry($process_form_instance_id); + + $this->process_form_workflow_api = new Gravity_Flow_API( $this->process_form->id ); + } + + /** + * @covers Wiaas_Delivery_Process::create_delivery_process_for_order + */ + function test_delivery_process_for_order_created() { + $order = wc_create_order(); + $order_id = $order->get_id(); + + Wiaas_Delivery_Process::create_delivery_process_for_order($order_id); + + $order_process_id = absint(get_post_meta($order_id, 'wiaas_delivery_process_id')); + $order_process_instance_id = absint(get_post_meta($order_id, 'wiaas_delivery_process_entry_id')); + + # check field populated + $this->assertGreaterThan(0, $order_process_id); + $this->assertGreaterThan(0, $order_process_instance_id); + } + + /** + * @covers Wiaas_Delivery_Process::extend_gravity_form_entry_meta + */ + function test_gravity_form_entry_meta_extended() { + # create test entry with additional metadata + $entry = array( + 'form_id' => $this->step_form->id, + 'wiaas_delivery_process_id' => false, + ); + + $result = GFAPI::add_entry($entry); + + # test that entry was successfully created + $this->assertFalse(is_wp_error($result)); + } + + /** + * @covers Wiaas_Delivery_Process::maybe_complete_parent_process_step + */ + function test_do_nothing_if_completed_workflow_has_no_parent() { + # Test there is no exception if entry has no parent process + $entry_id = GFAPI::add_entry(array( + 'form_id' => $this->step_form->id + )); + + $this->assertFalse( + Wiaas_Delivery_Process::maybe_complete_parent_process_step( + $entry_id, + $this->step_form) + ); + } + + /** + * @covers Wiaas_Delivery_Process::maybe_complete_parent_process_step + */ + function test_process_parent_process_step_on_workflow_completion() { + # get process current step + $process_form_instance = GFAPI::get_entry($this->process_form_instance['id']); + + # retrieve process steps + $process_steps = $this->process_form_workflow_api->get_steps($this->process_form); + $first_process_step = $process_steps[0]; + $second_process_step = $process_steps[1]; + + # Check that current step is first step of corresponding process + $process_instance_current_step = $this->process_form_workflow_api->get_current_step($process_form_instance); + $this->assertEquals( + $process_instance_current_step->get_id(), + $first_process_step->get_id()); + + # Update step form entry to complete its workflow + $step_form_entry = $process_instance_current_step->get_target_form_entry(); + gform_update_meta($step_form_entry['id'], 'workflow_role_administrator', 'approved'); + + # execute callback + Wiaas_Delivery_Process::maybe_complete_parent_process_step($step_form_entry['id'], null); + + # refresh process instance and check we moved to next step + $process_form_instance = GFAPI::get_entry($this->process_form_instance['id']); + $this->assertEquals( + $this->process_form_workflow_api->get_current_step($process_form_instance)->get_id(), + $second_process_step->get_id()); + } + + + + /** + * @covers Wiaas_Delivery_Process::get_order_delivery_process() + */ + function test_get_order_delivery_process() { + + $order = wc_create_order(); + $order_id = $order->get_id(); + + $delivery_process = Wiaas_Delivery_Process::get_order_delivery_process($order_id); + + $this->assertNotNull($delivery_process); + + $steps = $delivery_process['steps']; + + $this->assertNotNull($steps); + $this->assertTrue(is_array($steps)); + + foreach ($steps as $step) { + + # test returned step is array + $this->assertTrue(is_array($step)); + + # test returned step properties + $this->assertArrayHasKey('step_id', $step); + $this->assertArrayHasKey('step_form_entry_id', $step); + $this->assertArrayHasKey('short_desc', $step); + $this->assertArrayHasKey('full_desc', $step); + $this->assertArrayHasKey('action_code', $step); + $this->assertArrayHasKey('step_type', $step); + $this->assertArrayHasKey('status', $step); + $this->assertArrayHasKey('order_id', $step); + + $this->assertEquals($step['order_id'], $order_id); + + # test that started steps have valid form entry + if ($step['status'] !== 'inactive') { + $process_instance = GFAPI::get_entry($step['step_form_entry_id']); + $this->assertFalse(is_wp_error($process_instance)); + } + } + } +} \ No newline at end of file diff --git a/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php b/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php new file mode 100644 index 0000000..72a0976 --- /dev/null +++ b/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-rest-delivery-process-api.php @@ -0,0 +1,55 @@ +order_id = $order->get_id(); + + wp_set_current_user(1); + } + + /** + * @covers Wiass_REST_Delivery_Process_API::get_next_actions_for_user + */ + function test_get_next_actions_for_user() { + wp_set_current_user(1); + + $response = Wiass_REST_Delivery_Process_API::get_next_actions_for_user(); + + $this->assertNotNull($response); + $this->assertInstanceOf('WP_REST_Response', $response); + + $next_steps = $response->get_data(); + + $this->assertNotNull($next_steps); + $this->assertTrue(is_array($next_steps)); + + # check that administrator has one action pending + $this->assertEquals(sizeof($next_steps), 1); + + $pending_step = $next_steps[0]; + + $this->assertTrue(is_array($pending_step)); + + $this->assertArrayHasKey('idOrder', $pending_step); + $this->assertArrayHasKey('orderNumber', $pending_step); + $this->assertArrayHasKey('status', $pending_step); + $this->assertArrayHasKey('stepAction', $pending_step); + + $this->assertEquals($pending_step['idOrder'], $this->order_id); + $this->assertEquals($pending_step['orderNumber'], $this->order_id); + $this->assertEquals($pending_step['status'], 'pending'); + $this->assertNotEmpty($pending_step['stepAction']); + } +} diff --git a/backend/app/plugins/wiaas/tests/wiaas-unit-test-case.php b/backend/app/plugins/wiaas/tests/wiaas-unit-test-case.php new file mode 100644 index 0000000..41d1e5f --- /dev/null +++ b/backend/app/plugins/wiaas/tests/wiaas-unit-test-case.php @@ -0,0 +1,17 @@ +install(); + + wiaas_db_update_setup_gravity(); + } +} \ No newline at end of file diff --git a/backend/app/plugins/wiaas/wiaas.php b/backend/app/plugins/wiaas/wiaas.php index ec6fd08..cd9f5b4 100644 --- a/backend/app/plugins/wiaas/wiaas.php +++ b/backend/app/plugins/wiaas/wiaas.php @@ -23,3 +23,7 @@ if ( defined( 'WP_CLI' ) && WP_CLI ) { } include_once WIAAS_DIR . '/includes/class-wiaas-delivery-process.php'; + +include_once WIAAS_DIR . '/includes/class-wiaas-order.php'; + +include_once WIAAS_DIR . '/includes/class-wiaas-api.php'; diff --git a/backend/composer.json b/backend/composer.json index 4033545..5900c23 100644 --- a/backend/composer.json +++ b/backend/composer.json @@ -3,6 +3,32 @@ { "type": "composer", "url": "https://wpackagist.org" + }, + { + "type": "package", + "package": { + "name": "3rdparty/gravityforms", + "type": "wordpress-plugin", + "version": "2.2.3", + "source": { + "url": "https://gitlab.com/saburly/wiaas/3rdparty/gravityforms", + "type": "git", + "reference": "origin/master" + } + } + }, + { + "type": "package", + "package": { + "name": "3rdparty/gravityflow", + "type": "wordpress-plugin", + "version": "2.2.3", + "source": { + "url": "https://gitlab.com/saburly/wiaas/3rdparty/gravityflow", + "type": "git", + "reference": "origin/master" + } + } } ], "require": { @@ -20,11 +46,13 @@ "wpackagist-plugin/klarna-checkout-for-woocommerce": "1.5.2", "wpackagist-plugin/mailchimp-for-woocommerce": "2.1.7", "wpackagist-plugin/woocommerce-gateway-paypal-express-checkout": "1.5.6", - "wpackagist-plugin/jwt-authentication-for-wp-rest-api": "1.2.4" + "wpackagist-plugin/jwt-authentication-for-wp-rest-api": "1.2.4", + + "3rdparty/gravityforms": "*", + "3rdparty/gravityflow": "*" }, "require-dev": { - "vlucas/phpdotenv": "2.5.0", - "squizlabs/php_codesniffer": "3.3.1" + "vlucas/phpdotenv": "2.5.0" }, "extra": { "installer-paths": { @@ -45,6 +73,8 @@ "wp plugin activate woocommerce", "wp plugin activate woocommerce-jetpack", "wp plugin activate jwt-authentication-for-wp-rest-api", + "wp plugin activate gravityforms", + "wp plugin activate gravityflow", "wp plugin activate wiaas" ], "update-db": [ diff --git a/backend/composer.lock b/backend/composer.lock index d897dfa..cda3cd2 100644 --- a/backend/composer.lock +++ b/backend/composer.lock @@ -4,8 +4,28 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b1d245f7a98541665eb383619bb23283", + "content-hash": "16aac868dbf84d6c3cf7c41703e9085f", "packages": [ + { + "name": "3rdparty/gravityflow", + "version": "2.2.3", + "source": { + "type": "git", + "url": "https://gitlab.com/saburly/wiaas/3rdparty/gravityflow", + "reference": "origin/master" + }, + "type": "wordpress-plugin" + }, + { + "name": "3rdparty/gravityforms", + "version": "2.2.3", + "source": { + "type": "git", + "url": "https://gitlab.com/saburly/wiaas/3rdparty/gravityforms", + "reference": "origin/master" + }, + "type": "wordpress-plugin" + }, { "name": "composer/installers", "version": "v1.5.0", @@ -559,57 +579,6 @@ } ], "packages-dev": [ - { - "name": "squizlabs/php_codesniffer", - "version": "3.3.1", - "source": { - "type": "git", - "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "628a481780561150481a9ec74709092b9759b3ec" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/628a481780561150481a9ec74709092b9759b3ec", - "reference": "628a481780561150481a9ec74709092b9759b3ec", - "shasum": "" - }, - "require": { - "ext-simplexml": "*", - "ext-tokenizer": "*", - "ext-xmlwriter": "*", - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" - }, - "bin": [ - "bin/phpcs", - "bin/phpcbf" - ], - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Greg Sherwood", - "role": "lead" - } - ], - "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", - "homepage": "http://www.squizlabs.com/php-codesniffer", - "keywords": [ - "phpcs", - "standards" - ], - "time": "2018-07-26T23:47:18+00:00" - }, { "name": "vlucas/phpdotenv", "version": "v2.5.0", diff --git a/backend/config/environments/test.php b/backend/config/environments/test.php new file mode 100644 index 0000000..d155f2e --- /dev/null +++ b/backend/config/environments/test.php @@ -0,0 +1,18 @@ +load(); + $dotenv->required(['MYSQL_DATABASE', 'MYSQL_USER', 'MYSQL_PASSWORD']); + } +} \ No newline at end of file diff --git a/docker/php/setup.sh b/docker/php/setup.sh index d4502a5..70c3edc 100644 --- a/docker/php/setup.sh +++ b/docker/php/setup.sh @@ -17,6 +17,8 @@ wp plugin activate woocommerce-jetpack --allow-root wp plugin activate groups --allow-root wp plugin activate jwt-authentication-for-wp-rest-api --allow-root wp plugin activate wiaas --allow-root +wp plugin activate gravityforms --allow-root +wp plugin activate gravityflow --allow-root # Execute database update for updated plugins # (if no changes detected command will do nothing)