diff --git a/README.md b/README.md
index b40fbe0..ac21102 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
+ ./tests/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/class-wiaas-api.php b/backend/app/plugins/wiaas/includes/class-wiaas-api.php
new file mode 100644
index 0000000..8549440
--- /dev/null
+++ b/backend/app/plugins/wiaas/includes/class-wiaas-api.php
@@ -0,0 +1,48 @@
+ '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
new file mode 100644
index 0000000..7c4c9e3
--- /dev/null
+++ b/backend/app/plugins/wiaas/includes/class-wiaas-delivery-process.php
@@ -0,0 +1,162 @@
+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;
+ }
+
+ $parent_entry_id = absint( $parent_entry_id );
+ $parent_entry = GFAPI::get_entry( $parent_entry_id );
+
+ $parent_api = new Gravity_Flow_API( $parent_entry['form_id'] );
+ $parent_api->process_workflow( $parent_entry_id );
+ }
+}
+
+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
new file mode 100644
index 0000000..ce887a1
--- /dev/null
+++ b/backend/app/plugins/wiaas/includes/delivery-process/class-wiaas-delivery-process-step.php
@@ -0,0 +1,249 @@
+ 'customer-acceptance',
+ 'DELIVERY ACTION TYPE: Validate Questionnaire' => 'validate-questionnaire',
+ 'DELIVERY ACTION TYPE: Manual' => 'manual',
+ '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_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 );
+ }
+
+
+ $settings = array(
+ 'title' => esc_html__( 'Wiaas Delivery Step', 'wiaas' ),
+ 'fields' => array(
+ $settings_api->get_setting_instructions(),
+ array (
+ 'name' => 'is_visible_to_customer',
+ 'label' => __( 'Visible to customer', 'wiaas' ),
+ 'type' => 'checkbox',
+ 'choices' => array(
+ array(
+ 'label' => __( 'Show to customer', 'wiaas' ),
+ 'name' => 'is_visible_to_customer',
+ 'default_value' => true,
+ ),
+ ),
+ 'tooltip' => __( 'Determines if this step will be shown to customer.', 'wiaas' ),
+ ),
+ array(
+ 'name' => 'target_form_id',
+ 'label' => esc_html__( 'Action', 'wiaas' ),
+ 'type' => 'select',
+ 'onchange' => "jQuery(this).closest('form').submit();",
+ 'choices' => $form_choices,
+ ),
+ ),
+ );
+
+ 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 ) === 'customer-id') {
+ $customer_id_value = $entry[$field->id];
+ break;
+ }
+ }
+ }
+
+ if ( is_array( $target_form['fields'] ) ) {
+ foreach ( $target_form['fields'] as $field ) {
+ if (GFCommon::get_label( $field ) === 'customer-id') {
+ $new_entry[$field->id] = $customer_id_value;
+ break;
+ }
+ }
+ }
+
+ $entry_id = GFAPI::add_entry( $new_entry );
+ if ( is_wp_error( $entry_id ) ) {
+ $this->log_debug( __METHOD__ .'(): failed to add entry' );
+ } else {
+ // store entry id
+ gform_update_meta($this->get_entry_id(), 'wiaas_delivery_step_' . $this->get_id() .'_entry_id', $entry_id);
+ }
+
+ $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 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);
+
+ # 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) {
+ if ($form_id === $this->get_form_id()) {
+ $entry_meta['wiaas_delivery_step_' . $this->get_id() .'_entry_id'] = null;
+ }
+ return $entry_meta;
+ }
+
+ /**
+ * 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']];
+ }
+
+ public function get_target_actual_date() {
+ $target_entry = $this->get_target_form_entry();
+ $target_form = GFAPI::get_form( $this->target_form_id );
+
+ if (!is_wp_error($target_entry) && is_array($target_form['fields'])) {
+ foreach ( $target_form['fields'] as $field ) {
+ if (GFCommon::get_label( $field ) === 'Actual Date') {
+ return $target_entry[$field->id];
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public function get_target_step_comments() {
+ $notes = RGFormsModel::get_lead_notes( $this->get_target_form_entry_id() );
+
+ $comments = array();
+ foreach ( $notes as $key => $note ) {
+ if ( $note->note_type !== 'gravityflow' ) {
+ $comments[] = array(
+ 'date' => $note->date_created,
+ 'text' => $note->value,
+ 'user' => $note->user_name
+ );
+ }
+ }
+ return $comments;
+ }
+
+ /**
+ * Retrieves target form entry created when step was started
+ * @return array|null
+ */
+ public function get_target_form_entry() {
+ $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() {
+ $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 a6b8f1a..cd9f5b4 100644
--- a/backend/app/plugins/wiaas/wiaas.php
+++ b/backend/app/plugins/wiaas/wiaas.php
@@ -21,3 +21,9 @@ define( 'WIAAS_DIR', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
if ( defined( 'WP_CLI' ) && WP_CLI ) {
include_once WIAAS_DIR . '/includes/class-wiaas-cli.php';
}
+
+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)