diff --git a/custom_connectors/oauth2/workflowmax_connector.rb b/custom_connectors/oauth2/workflowmax_connector.rb
new file mode 100644
index 00000000..aeb2e50d
--- /dev/null
+++ b/custom_connectors/oauth2/workflowmax_connector.rb
@@ -0,0 +1,919 @@
+{
+ title: 'WorkflowMax',
+
+ connection: {
+ fields: [
+ { name: 'client_id', optional: false,
+ hint: 'To create client id, you need to register an application in ' \
+ " " \
+ 'developer portal. Create an app with ' \
+ "'OAuth 2.0 grant type' and use client ID." },
+ { name: 'client_secret', control_type: 'password', optional: false,
+ hint: 'To create client secret, you need to register an application in ' \
+ " " \
+ 'developer portal. Create an app with ' \
+ "'OAuth 2.0 grant type' and use client secret." }
+ ],
+
+ authorization: {
+ type: 'oauth2',
+
+ authorization_url: lambda do |connection|
+ params = {
+ response_type: 'code',
+ client_id: connection['client_id'],
+ redirect_uri: 'https://www.workato.com/oauth/callback',
+ scope: 'workflowmax offline_access'
+ }.to_param
+
+ 'https://login.xero.com/identity/connect/authorize?' + params
+ end,
+
+ acquire: lambda do |connection, auth_code|
+ header = "#{connection['client_id']}:#{connection['client_secret']}"
+ response = post('https://identity.xero.com/connect/token').
+ payload(
+ grant_type: 'authorization_code',
+ redirect_uri: 'https://www.workato.com/oauth/callback',
+ code: auth_code
+ ).request_format_www_form_urlencoded.
+ headers(authorization: "Basic #{header.encode_base64}")
+ tenent_info = get('https://api.xero.com/connections').
+ headers(authorization: "Bearer #{response['access_token']}").
+ select { |item| item['tenantType'] == 'WORKFLOWMAX' }
+ [
+ {
+ access_token: response['access_token'],
+ refresh_token: response['refresh_token']
+ },
+ nil,
+ { tenent_id: tenent_info.dig(0, 'tenantId') }
+ ]
+ end,
+
+ refresh_on: [401, 403],
+
+ refresh: lambda do |connection, refresh_token|
+ header = "#{connection['client_id']}:#{connection['client_secret']}"
+ response = post('https://identity.xero.com/connect/token').
+ payload(
+ grant_type: 'refresh_token',
+ refresh_token: refresh_token,
+ redirect_uri: 'https://www.workato.com/oauth/callback'
+ ).request_format_www_form_urlencoded.
+ headers(authorization: "Basic #{header.encode_base64}")
+ tenent_info = get('https://api.xero.com/connections').
+ headers(authorization: "Bearer #{response['access_token']}").
+ select { |item| item['tenantType'] == 'WORKFLOWMAX' }
+ [
+ {
+ access_token: response['access_token'],
+ refresh_token: response['refresh_token']
+ },
+ { tenent_id: tenent_info.dig(0, 'tenantId') }
+ ]
+ end,
+
+ apply: lambda do |connection, access_token|
+ headers('authorization': "Bearer #{access_token}",
+ 'xero-tenant-id': connection['tenent_id'])
+ end
+ },
+ base_uri: -> { 'https://api.xero.com/workflowmax/3.0/' }
+ },
+
+ test: lambda { |_connection|
+ get('staff.api/list').response_format_xml['status']
+ },
+
+ methods: {
+
+ parse_xml_to_hash: lambda do |xml_obj|
+ xml_obj['xml']&.
+ reject { |key, _value| key[/^@/] }&.
+ inject({}) do |hash, (key, value)|
+ if value.is_a?(Array)
+ hash.merge(
+ if (array_fields = xml_obj['array_fields'])&.include?(key)
+ {
+ key => value.map do |inner_hash|
+ call('parse_xml_to_hash',
+ 'xml' => inner_hash,
+ 'array_fields' => array_fields)
+ end
+ }
+ else
+ {
+ key => call('parse_xml_to_hash',
+ 'xml' => value[0],
+ 'array_fields' => array_fields)
+ }
+ end
+ )
+ else
+ value
+ end
+ end&.presence
+ end
+
+ },
+
+ object_definitions: {
+
+ invoice: {
+ fields: lambda do |_connection|
+ [
+ { name: 'ID',
+ label: 'Invoice ID' },
+ { name: 'UUID', label: 'Invoice UUID' },
+ { name: 'Type' },
+ { name: 'Status',
+ control_type: 'select',
+ pick_list: 'invoice_status',
+ label: 'Invoice status',
+ toggle_hint: 'Select from list',
+ toggle_field:
+ { name: 'Status',
+ type: 'string',
+ control_type: 'text',
+ label: 'Invoice status',
+ toggle_hint: 'User custom value',
+ hint: 'Status can be one of Paid, ' \
+ 'Draft, Cancelled' } },
+ { name: 'JobText' },
+ { name: 'Date', type: 'date_time', control_type: 'date_time' },
+ { name: 'DueDate', type: 'date_time', control_type: 'date_time' },
+ { name: 'Amount', type: 'number', control_type: 'number' },
+ { name: 'AmountTax', type: 'number', control_type: 'number' },
+ { name: 'AmountIncludingTax', type: 'number',
+ control_type: 'number' },
+ { name: 'AmountPaid', type: 'number', control_type: 'number' },
+ { name: 'AmountOutstanding', type: 'number', control_type: 'number' },
+ { name: 'Client', type: 'object', properties: [
+ { name: 'UUID', type: 'integer', control_type: 'number' },
+ { name: 'Name' }
+ ] },
+ { name: 'Contact', type: 'object', properties: [
+ { name: 'UUID', type: 'integer', control_type: 'number' },
+ { name: 'Name' }
+ ] },
+ { name: 'Jobs', type: 'object', properties: [
+ { name: 'Job', type: 'array', of: 'object', properties: [
+ { name: 'ID', type: 'integer', control_type: 'number' },
+ { name: 'Name' },
+ { name: 'Description' },
+ { name: 'ClientOrderNumber' },
+ { name: 'Tasks', type: 'object', properties: [
+ { name: 'Task', type: 'array', of: 'object', properties: [
+ { name: 'UUID' },
+ { name: 'Name' },
+ { name: 'Description' },
+ { name: 'Minutes', type: 'integer',
+ control_type: 'number' },
+ { name: 'BillableRate', type: 'integer',
+ control_type: 'number' },
+ { name: 'Billable', type: 'boolean',
+ control_type: 'checkbox',
+ toggle_hint: 'Select from list',
+ toggle_field:
+ { name: 'Billable',
+ type: 'string',
+ control_type: 'text',
+ label: 'Billable',
+ toggle_hint: 'User custom value' } },
+ { name: 'Amount', type: 'number', control_type: 'number' },
+ { name: 'AmountTax', type: 'number',
+ control_type: 'number' },
+ { name: 'AmountIncludingTax', type: 'number',
+ control_type: 'number' }
+ ] }
+ ] },
+ { name: 'Costs', type: 'object', properties: [
+ { name: 'Cost', type: 'array', of: 'object', properties: [
+ { name: 'Description' },
+ { name: 'Code' },
+ { name: 'Billable', type: 'boolean',
+ control_type: 'checkbox',
+ toggle_hint: 'Select from list',
+ toggle_field:
+ { name: 'Billable', type: 'string',
+ control_type: 'text', label: 'Billable',
+ toggle_hint: 'User custom value' } },
+ { name: 'Quantity', type: 'number',
+ control_type: 'number' },
+ { name: 'UnitCost', type: 'number',
+ control_type: 'number' },
+ { name: 'UnitPrice', type: 'number',
+ control_type: 'number' },
+ { name: 'Amount', type: 'number', control_type: 'number' },
+ { name: 'AmountTax', type: 'number',
+ control_type: 'number' },
+ { name: 'AmountIncludingTax', type: 'number',
+ control_type: 'number' }
+ ] }
+ ] }
+ ] }
+ ] }
+ ]
+ end
+ },
+
+ client: {
+ fields: lambda do |_connection, _config_fields|
+ [
+ { name: 'UUID' },
+ { name: 'Name' },
+ { name: 'Email' },
+ { name: 'DateOfBirth', type: 'date', control_type: 'date' },
+ { name: 'Address' },
+ { name: 'City' },
+ { name: 'Region' },
+ { name: 'PostCode' },
+ { name: 'Country' },
+ { name: 'PostalAddress' },
+ { name: 'PostalCity' },
+ { name: 'PostalRegion' },
+ { name: 'PostalPostCode' },
+ { name: 'PostalCountry' },
+ { name: 'Phone' },
+ { name: 'Fax' },
+ { name: 'Website' },
+ { name: 'ReferralSource' },
+ { name: 'ExportCode' },
+ { name: 'IsProspect' },
+ { name: 'AccountManager', type: :object, properties: [
+ { name: 'ID', type: 'integer', control_type: 'integer' },
+ { name: 'Name' }
+ ] },
+ { name: 'Type', type: :object, properties: [
+ { name: 'Name' },
+ { name: 'CostMarkup', type: 'number', control_type: 'number' },
+ { name: 'PaymentTerm' },
+ { name: 'PaymentDay', type: 'integer', control_type: 'number' }
+ ] },
+ { name: 'Contacts', type: 'object', properties: [
+ { name: 'Contact', type: :array, of: :object, properties: [
+ { name: 'ID' },
+ { name: 'IsPrimary', type: 'boolean', control_type: 'checkbox' },
+ { name: 'Name' },
+ { name: 'Salutation' },
+ { name: 'Addressee' },
+ { name: 'Mobile' },
+ { name: 'Email' },
+ { name: 'Phone' },
+ { name: 'Position' }
+ ] }
+ ] },
+ { name: 'Notes', type: 'object', properties: [
+ { name: 'Note', type: 'array', of: 'object', properties: [
+ { name: 'Title' },
+ { name: 'Text' },
+ { name: 'Folder' },
+ { name: 'Date', type: 'date_time', control_type: 'date_time' },
+ { name: 'CreatedBy' }
+ ] }
+ ] }
+
+ ]
+ end
+ },
+
+ quote: {
+ fields: lambda do |_connection, _config|
+ [
+ { name: 'ID' },
+ { name: 'Type' },
+ { name: 'State' },
+ { name: 'Name' },
+ { name: 'Description' },
+ { name: 'Budget', type: 'number', control_type: 'number' },
+ { name: 'OptionExplanation', type: 'string',
+ control_type: 'text-area' },
+ { name: 'Date', type: 'date_time', control_type: 'date_time' },
+ { name: 'ValidDate', type: 'date_time', control_type: 'date_time',
+ label: 'Valid to' },
+ { name: 'EstimatedCost', type: 'number', control_type: 'number' },
+ { name: 'EstimatedCostTax', type: 'number',
+ control_type: 'number' },
+ { name: 'EstimatedCostIncludingTax', type: 'number',
+ control_type: 'number' },
+ { name: 'Amount', type: 'number', control_type: 'number' },
+ { name: 'AmountTax', type: 'number', control_type: 'number' },
+ { name: 'AmountIncludingTax', type: 'number',
+ control_type: 'number' },
+ { name: 'Client', type: 'object', properties: [
+ { name: 'ID', type: 'integer', control_type: 'number' },
+ { name: 'Name' }
+ ] },
+ { name: 'Contact', type: 'object', properties: [
+ { name: 'ID', type: 'integer', control_type: 'number' },
+ { name: 'Name' }
+ ] },
+ { name: 'Tasks', type: 'object', properties: [
+ { name: 'Task', type: 'array', of: 'object', properties: [
+ { name: 'Name' },
+ { name: 'Description' },
+ { name: 'EstimatedMinutes', type: 'integer',
+ control_type: 'number' },
+ { name: 'BillableRate', type: 'number',
+ control_type: 'number' },
+ { name: 'Billable' },
+ { name: 'Amount', type: 'number', control_type: 'number' },
+ { name: 'AmountTax', type: 'number', control_type: 'number' },
+ { name: 'AmountIncludingTax', type: 'number',
+ control_type: 'number' }
+ ] }
+ ] },
+ { name: 'Options', type: 'object', properties: [
+ { name: 'Option', type: 'array', of: 'object', properties: [
+ { name: 'Note' },
+ { name: 'Code' },
+ { name: 'Quantity', type: 'number', control_type: 'number' },
+ { name: 'UnitCost', type: 'number', control_type: 'number' },
+ { name: 'UnitPrice', type: 'number', control_type: 'number' },
+ { name: 'Amount', type: 'number', control_type: 'number' },
+ { name: 'AmountTax', type: 'number', control_type: 'number' },
+ { name: 'AmountIncludingTax', type: 'number',
+ control_type: 'number' },
+ { name: 'Description' }
+ ] }
+ ] },
+ { name: 'Costs', type: 'object', properties: [
+ { name: 'Cost', type: 'array', of: 'object', properties: [
+ { name: 'Note' },
+ { name: 'Code' },
+ { name: 'Billable' },
+ { name: 'Quantity', type: 'number', control_type: 'number' },
+ { name: 'UnitCost', type: 'number', control_type: 'number' },
+ { name: 'UnitPrice', type: 'number', control_type: 'number' },
+ { name: 'Amount', type: 'number', control_type: 'number' },
+ { name: 'AmountTax', type: 'number', control_type: 'number' },
+ { name: 'AmountIncludingTax', type: 'number',
+ control_type: 'number' },
+ { name: 'Description' }
+ ] }
+ ] }
+ ]
+ end
+ },
+
+ supplier: {
+ fields: lambda do |_variable|
+ [
+ { name: 'UUID' },
+ { name: 'Name' },
+ { name: 'Address', type: 'string', control_type: 'text-area' },
+ { name: 'City' },
+ { name: 'Region' },
+ { name: 'PostCode' },
+ { name: 'PostalAddress', type: 'string', control_type: 'text-area' },
+ { name: 'PostalCity' },
+ { name: 'PostalRegion' },
+ { name: 'PostalPostCode' },
+ { name: 'PostalCountry' },
+ { name: 'Phone', type: 'string', control_type: 'phone' },
+ { name: 'Fax' },
+ { name: 'Website' },
+ { name: 'Contacts', type: 'object', properties: [
+ { name: 'Contact', type: 'array', of: 'object', properties: [
+ { name: 'ID' },
+ { name: 'Name' },
+ { name: 'Mobile' },
+ { name: 'Email' },
+ { name: 'Phone' },
+ { name: 'Position' }
+ ] }
+ ] },
+ { name: 'Notes', type: 'object', properties: [
+ { name: 'Note', type: 'array', of: 'object', properties: [
+ { name: 'Title' },
+ { name: 'Text' },
+ { name: 'Folder' },
+ { name: 'Date', type: 'date_time', control_type: 'date_time' },
+ { name: 'CreatedBy' }
+ ] }
+ ] }
+ ]
+ end
+ },
+
+ contact: {
+ fields: lambda do |_|
+ [
+ { name: 'UUID' },
+ { name: 'Name' },
+ { name: 'Mobile' },
+ { name: 'Email' },
+ { name: 'Phone' },
+ { name: 'Position' }
+ ]
+ end
+ },
+
+ payment: {
+ fields: lambda do |_|
+ [
+ { name: 'Date', type: 'date_time', control_type: 'date_time' },
+ { name: 'Amount', type: 'number', control_type: 'number' },
+ { name: 'Reference' }
+ ]
+ end
+ }
+
+ },
+
+ actions: {
+ search_clients: {
+ title: 'Search clients',
+ subtitle: 'Search clients in Workflowmax by query',
+ description: "Search clients in " \
+ "WorkflowMax",
+ input_fields: lambda do |_object_definitions|
+ [
+ { name: 'query',
+ label: 'Client name',
+ optional: false,
+ hint: 'Search based on client name' }
+ ]
+ end,
+ execute: lambda do |_connection, input|
+ response = get('client.api/search', input).
+ format_xml('response').dig('Response', 0) || [{}]
+ {
+ clients: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Client Contact Note]).
+ dig('Clients', 'Client') || []
+ }
+ end,
+ output_fields: lambda do |object_definitions|
+ [
+ { name: 'clients', type: 'array', of: 'object',
+ properties: object_definitions['client'] }
+ ]
+ end,
+ sample_output: lambda do |_object_definitions|
+ response = get('client.api/list?detailed=true').
+ format_xml('response').dig('Response', 0) || [{}]
+ {
+ clients: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Client Contact Note]).
+ dig('Clients', 'Client', 0) || []
+ }
+ end
+ },
+
+ get_client_details_by_uuid: {
+ title: 'Get client details by UUID',
+ subtitle: 'Get client details in WorkflowMax by UUID',
+ description: "Get client details by UUID " \
+ "in WorkflowMax",
+ input_fields: lambda do |_|
+ [
+ { name: 'uuid', label: 'Client UUID',
+ optional: false,
+ hint: 'e.g. c8f691b8-c26c-475d-9da4-fd3837d2bbaf' }
+ ]
+ end,
+ execute: lambda do |_connection, input|
+ response = get('client.api/get/' + input['uuid']).
+ format_xml('response').dig('Response', 0) || {}
+
+ call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Client Contact Note]).
+ dig('Client', 0) || {}
+ end,
+ output_fields: lambda do |object_definitions|
+ object_definitions['client']
+ end,
+ sample_output: lambda do |_connection|
+ response = get('client.api/list?detailed=true').
+ format_xml('response').dig('Response', 0) || {}
+
+ call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Client Contact Note']).
+ dig('Clients', 'Client', 0) || {}
+ end
+ },
+
+ get_all_suppliers: {
+ title: 'Get all suppliers',
+ subtitle: 'Get all suppliers details in WorkflowMax',
+ description: "Get all suppliers in " \
+ "WorkflowMax",
+ execute: lambda do |_connection, _input|
+ response = get('supplier.api/list?detailed=true').
+ format_xml('response').dig('Response', 0) || [{}]
+ {
+ suppliers: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Supplier Contact Note]).
+ dig('Suppliers', 'Supplier') || []
+ }
+ end,
+ output_fields: lambda do |object_definitions|
+ [
+ { name: 'suppliers', type: 'array', of: 'object',
+ properties: object_definitions['supplier'] }
+ ]
+ end,
+ sample_output: lambda do |_connection|
+ response = get('supplier.api/list?detailed=true').
+ format_xml('response').dig('Response', 0) || [{}]
+ {
+ suppliers: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Supplier Contact Note]).
+ dig('Suppliers', 'Supplier', 0) || []
+ }
+ end
+ },
+
+ get_supplier_details_by_uuid: {
+ title: 'Get supplier details by UUID',
+ subtitle: 'Get supplier details in WorkflowMax by UUID',
+ description: "Get supplier by UUID in " \
+ "WorkflowMax",
+ input_fields: lambda do |_|
+ [
+ { name: 'uuid', label: 'Supplier UUID',
+ optional: false,
+ hint: 'e.g. c8f691b8-c26c-475d-9da4-fd3837d2bbaf' }
+ ]
+ end,
+ execute: lambda do |_connection, input|
+ response = get('supplier.api/get/' + input['uuid']).
+ format_xml('response').dig('Response', 0) || {}
+
+ call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Supplier Contact Note]).
+ dig('Supplier', 0) || {}
+ end,
+ output_fields: lambda do |object_definitions|
+ object_definitions['supplier']
+ end,
+ sample_output: lambda do |_connection|
+ response = get('supplier.api/list?detailed=true').
+ format_xml('response').dig('Response', 0) || {}
+
+ call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Supplier Contact Note]).
+ dig('Suppliers', 'Supplier', 0) || {}
+ end
+ },
+
+ get_supplier_contact_by_uuid: {
+ title: 'Get supplier contact by UUID',
+ subtitle: 'Get supplier contact details in WorkflowMax by UUID',
+ description: "Get supplier contact " \
+ "by UUID in WorkflowMax",
+ input_fields: lambda do |_|
+ [
+ { name: 'uuid', label: 'Contact UUID',
+ optional: false,
+ hint: 'e.g. c8f691b8-c26c-475d-9da4-fd3837d2bbaf' }
+ ]
+ end,
+ execute: lambda do |_connection, input|
+ response = get('supplier.api/contact/' + input['uuid']).
+ format_xml('response').dig('Response', 0) || {}
+
+ call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => []).dig('Contact') || {}
+ end,
+ output_fields: lambda do |object_definitions|
+ object_definitions['contact']
+ end,
+ sample_output: lambda do |_connections|
+ response = get('supplier.api/list?detailed=true').
+ format_xml('response').dig('Response', 0) || {}
+
+ call('parse_xml_to_hash',
+ 'xml' => response, 'array_fields' => []).
+ dig('Suppliers', 'Supplier', 'Contacts', 'Contact') || {}
+ end
+ },
+
+ search_quotes: {
+ title: 'Search quotes',
+ subtitle: 'Search quotes in WorkflowMax',
+ description: "Search issued quotes " \
+ "for given date range inWorkflowMax",
+ input_fields: lambda do |_object_definitions|
+ [
+ { name: 'from',
+ type: 'date',
+ control_type: 'date',
+ optional: false,
+ hint: 'Return quotes created on or after this date.' },
+ { name: 'to',
+ type: 'date',
+ control_type: 'date',
+ optional: false,
+ hint: 'Return quote created on or before this date.' }
+ ]
+ end,
+ execute: lambda do |_connection, input|
+ response = get('quote.api/list').
+ params(from: input['from'].strftime('%Y%m%d'),
+ to: input['to'].strftime('%Y%m%d'),
+ detailed: 'true').format_xml('response').
+ dig('Response', 0) || [{}]
+ {
+ quotes: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Quote Task Option Cost]).
+ dig('Quotes', 'Quote') || []
+ }
+ end,
+ output_fields: lambda do |object_definitions|
+ [
+ { name: 'quotes', type: 'array', of: 'object',
+ properties: object_definitions['quote'] }
+ ]
+ end,
+ sample_output: lambda do |_connections|
+ response = get('quote.api/current?detailed=true').
+ format_xml('response').dig('Response', 0) || [{}]
+ {
+ quotes: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Quote Task Option Cost]).
+ dig('Quotes', 'Quote', 0) || []
+ }
+ end
+ },
+
+ get_quote_by_number: {
+ title: 'Get quote by number',
+ subtitle: 'Get quote details in WorkflowMax by quote number',
+ description: "Get quote details by quote" \
+ " number in WorkflowMax",
+ input_fields: lambda do |_object_definitions|
+ [
+ { name: 'quote_number',
+ optional: false,
+ hint: 'e.g. Q000123' }
+ ]
+ end,
+ execute: lambda do |_connection, input|
+ response = get('quote.api/get/' + input['quote_number']).
+ format_xml('response').dig('Response', 0) || {}
+ call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Task Cost Option]).dig('Quote') || {}
+ end,
+ output_fields: lambda do |object_definitions|
+ object_definitions['quote']
+ end,
+ sample_output: lambda do |_connection|
+ response = get('quote.api/current?detailed=true').
+ format_xml('response').dig('Response', 0) || {}
+ call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Quote Task Cost Option]).
+ dig('Quotes', 'Quote', 0) || {}
+ end
+ },
+
+ get_current_quotes: {
+ title: 'Get current quotes',
+ subtitle: 'Get current quote details in WorkflowMax',
+ description: "Get current quotes in " \
+ "WorkflowMax",
+ help: 'Return a list of current quotes(issued) in WorkflowMax',
+ execute: lambda do |_connection, _input|
+ response = get('quote.api/current?detailed=true').
+ format_xml('response').dig('Response', 0) || [{}]
+ {
+ quotes: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Quote Task Cost Option]).
+ dig('Quotes', 'Quote') || [{}]
+ }
+ end,
+ output_fields: lambda do |object_definitions|
+ [
+ { name: 'quotes', type: 'array', of: 'object',
+ properties: object_definitions['quote'] }
+ ]
+ end,
+ sample_output: lambda do |_connection|
+ response = get('quote.api/current?detailed=true').
+ format_xml('response').dig('Response', 0) || [{}]
+
+ {
+ quotes: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Quote Task Option Cost]).
+ dig('Quotes', 'Quote', 0) || []
+ }
+ end
+ },
+
+ search_invoices: {
+ title: 'Search invoices',
+ subtitle: 'Search invoices in WorkflowMax',
+ description: "Search invoices for given " \
+ "date range in WorkflowMax",
+ input_fields: lambda do |_object_definitions|
+ [
+ { name: 'from',
+ type: 'date',
+ control_type: 'date',
+ optional: false,
+ hint: 'Return invoices created on or after this date.' },
+ { name: 'to',
+ type: 'date',
+ control_type: 'date',
+ optional: false,
+ hint: 'Return invoices created on or before this date.' }
+ ]
+ end,
+ execute: lambda do |_connection, input|
+ response = get('invoice.api/list').
+ params(from: input['from'].strftime('%Y%m%d'),
+ to: input['to'].strftime('%Y%m%d'),
+ detailed: 'true').format_xml('response').
+ dig('Response', 0) || [{}]
+
+ {
+ invoices: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Invoice Job Task Cost]).
+ dig('Invoices', 'Invoice') || []
+ }
+ end,
+ output_fields: lambda do |object_definitions|
+ [
+ { name: 'invoices', type: 'array', of: 'object',
+ properties: object_definitions['invoice'] }
+ ]
+ end,
+ sample_output: lambda do |_connection|
+ response = get('invoice.api/current?detailed=true').
+ format_xml('response').dig('Response', 0) || [{}]
+ {
+ invoices: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Invoice Task Cost Job]).
+ dig('Invoices', 'Invoice', 0) || [{}]
+ }
+ end
+ },
+
+ get_invoice_by_number: {
+ title: 'Get invoice by number',
+ subtitle: 'Get invoice details in WorkflowMax by invoice number',
+ description: "Get invoice details by " \
+ "invoice number in WorkflowMax",
+ input_fields: lambda do |_object_definitions|
+ [
+ { name: 'invoice_number',
+ optional: false,
+ hint: 'e.g. I000123' }
+ ]
+ end,
+ execute: lambda do |_connection, input|
+ response = get('invoice.api/get/' + input['invoice_number']).
+ format_xml('response').dig('Response', 0) || {}
+ call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Job Task Cost]).dig('Invoice') || {}
+ end,
+ output_fields: lambda do |object_definitions|
+ object_definitions['invoice']
+ end,
+ sample_output: lambda do |_connections|
+ response = get('invoice.api/current?detailed=true').
+ format_xml('response').dig('Response', 0) || {}
+ call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Invoice Task Cost Job]).
+ dig('Invoices', 'Invoice', 0) || {}
+ end
+ },
+
+ get_job_invoices: {
+ title: 'Get job invoices',
+ subtitle: 'Get invoices details in WorkflowMax for specific job',
+ description: "Get list of invoices " \
+ "for a specific job in WorkflowMax",
+ input_fields: lambda do |_object_definitions|
+ [
+ { name: 'job_number',
+ optional: false,
+ hint: 'e.g. J000123' }
+ ]
+ end,
+ execute: lambda do |_connection, input|
+ response = get('invoice.api/job/' + input['job_number']).
+ format_xml('response').dig('Response', 0) || [{}]
+ {
+ invoices: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Invoice Job Task Cost]).
+ dig('Invoices', 'Invoice') || []
+ }
+ end,
+ output_fields: lambda do |object_definitions|
+ [
+ { name: 'invoices', type: 'array', of: 'object',
+ properties: object_definitions['invoice'] }
+ ]
+ end,
+ sample_output: lambda do
+ response = get('invoice.api/current?detailed=true').
+ format_xml('response').dig('Response', 0) || [{}]
+
+ {
+ invoices: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Invoice Job Task Cost]).
+ dig('Invoices', 'Invoice', 0) || []
+ }
+ end
+ },
+
+ get_current_invoices: {
+ title: 'Get current invoices',
+ subtitle: 'Get current invoice in WorkflowMax',
+ description: "Get current invoices in " \
+ "WorkflowMax",
+ help: 'Get current invoices (Approved) in WorkflowMax',
+ execute: lambda do |_connection, _input|
+ response = get('invoice.api/current?detailed=true').
+ format_xml('response').dig('Response', 0) || [{}]
+ {
+ invoices: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Invoice Task Cost Job]).
+ dig('Invoices', 'Invoice') || [{}]
+ }
+ end,
+ output_fields: lambda do |object_definitions|
+ [
+ { name: 'invoices', type: 'array',
+ of: 'object', properties: object_definitions['invoice'] }
+ ]
+ end,
+ sample_output: lambda do |_connection|
+ response = get('invoice.api/current?detailed=true').
+ format_xml('response').dig('Response', 0) || [{}]
+ {
+ invoices: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => %w[Invoice Task Cost Job]).
+ dig('Invoices', 'Invoice', 0) || [{}]
+ }
+ end
+ },
+
+ get_invoice_payments: {
+ title: 'Get inovice payments',
+ subtitle: 'Get inovice payments in WorkflowMax',
+ description: "Get payments of invoice" \
+ " in WorkflowMax",
+ input_fields: lambda do |_object_definitions|
+ [
+ { name: 'invoice_number', optional: false,
+ hint: 'e.g. I000123' }
+ ]
+ end,
+ execute: lambda do |_connection, input|
+ response = get('invoice.api/payments/' + input['invoice_number']).
+ format_xml('response').dig('Response', 0) || [{}]
+ {
+ payments: call('parse_xml_to_hash',
+ 'xml' => response,
+ 'array_fields' => ['Payment']).
+ dig('Payments', 'Payment') || [{}]
+ }
+ end,
+ output_fields: lambda do |object_definitions|
+ [
+ { name: 'payments', type: 'array', of: 'object',
+ properties: object_definitions['payment'] }
+ ]
+ end
+ }
+ },
+
+ pick_lists: {
+ invoice_status: lambda do |_connection|
+ [
+ %w[Approved Approved],
+ %w[Paid Paid],
+ %w[Draft Draft],
+ %w[Cancelled Cancelled]
+ ]
+ end
+ }
+
+}