109 cfs subparams

This commit is contained in:
msyu
2025-05-19 15:48:41 +03:00
parent e4832ee878
commit e51a2c0cf5
6 changed files with 194 additions and 137 deletions
+1 -1
View File
@@ -51,7 +51,7 @@
//variables.framework.docs={};
variables.framework.docs.APIName="Deck API";
variables.framework.docs.APIVersion="0.108"; /*$ git config --global --unset user.password*/
variables.framework.docs.APIVersion="0.109"; /*$ git config --global --unset user.password*/
variables.framework.globalHeaders = structNew();
+1 -1
View File
@@ -74,7 +74,7 @@
where 1=1 <m:filter_build filter=#filter#/>
AND (b.contragent_id = <cfqueryparam cfsqltype="cf_sql_integer" value=#arguments.contragentId# null=#!isNumeric(arguments.contragentId)#/>
OR b.contragent_id=-1)/*общая букмарка*/
order by sort desc
order by b.contragent_id desc, b.sort asc
<!--- <m:order_build sortCollection=#this.helper.parseNumericOrder(local.titleMap, arguments.orderBy)# fieldCount=0/>--->
limit #maxrows#
</cfquery>
+8 -46
View File
@@ -146,15 +146,17 @@
"svcId":#local.qInstanceOperation.service_id#,
"contractId":#arguments.contractId#
}/> <!--- если появятся новые аргументы у новых функций, будем добавлять их сюда --->
<cfset local.qCfsParam.value_list=generateValueList(argumentCollection=#args#)/> <!--- можно перечислить именованные аргументы обычным порядком, но с коллекцией потенциально более гибко --->
<!--- <cfdump var=#local.qCfsParam#/><cfabort/> --->
<!--- <cfset local.qCfsParam.value_list=generateValueList(argumentCollection=#args#)/> --->
<cfinvoke component="instance_operation_cfs_param" method="generateValueList" argumentCollection=#args# returnVariable="local.qCfsParam.value_list"/>
<!--- можно перечислить именованные аргументы обычным порядком, но с коллекцией потенциально более гибко --->
<cfif len(trim(local.qCfsParam.value_list)) AND listLen(local.qCfsParam.value_list) EQ 1>
<cfset local.qCfsParam.default_value=local.qCfsParam.value_list/>
</cfif>
</cfif><!--- преобразование к массиву выполняется при финальном форматировании резалтсета --->
</cfif>
<cfif data_type EQ "map">
<cfset var map={}/>
<cfinvoke component="instance_operation_cfs_param" method="processMap" qParam=#local.qCfsParam#/>
<!--- <cfset var map={}/>
<cftry>
<cfset var map=deserializeJson(param_value)/>
<cfcatch type="any"><cfrethrow/></cfcatch>
@@ -223,7 +225,7 @@
</cfloop>
<cfset local.qCfsParam.data_descriptor = mapDescriptor/>
<cfset local.qCfsParam.param_value = serializeJson(map)/>
<cfset local.qCfsParam.param_value = serializeJson(map)/> --->
</cfif><!---/map --->
</cfloop>
@@ -250,47 +252,7 @@
<cfreturn representationOf(out) />
</cffunction>
<!--- *** дублируются --->
<cffunction name="getAvailableResourceRealms" returnType="string">
<cfargument name="svcId"/>
<cfargument name="contractId"/>
<cfset var local={}/>
<cfquery name="local.qAvailableResourceRealm"><!--- *** distinct халява, но придумывать корректную формулировку времени мало --->
select distinct r.resource_realm, r.sort
from resource_realm r
join resource_realm_access a on
(r.resource_realm_id=a.resource_realm_id
AND (a.contract_id=<cfqueryparam cfsqltype="CF_SQL_INTEGER" value=#arguments.contractId# null=#!isValid("integer", arguments.contractId)#/>
OR a.contract_id=0) /*0 means access to any contract*/
AND a.is_enabled)
join svc s on r.resource_realm_type_id=s.resource_realm_type_id
where s.svc_id=<cfqueryparam cfsqltype="CF_SQL_INTEGER" value=#arguments.svcId# null=#!isValid("integer", arguments.svcId)#/>
order by r.sort, r.resource_realm
</cfquery> <!--- <cfdump var=#arguments#/> cfdump здесь провоцирует NPE --->
<cfreturn valueList(local.qAvailableResourceRealm.resource_realm)/>
</cffunction>
<cffunction name="generateValueList" returntype="string">
<cfargument name="functionName" type="string" required="true"/>
<!--- остальные атрибуты необязательные, в argumentCollection (еще вопрос, насколько безопасно объявлять один из аргументов без остальных) --->
<cfswitch expression=#arguments.functionName#>
<cfcase value="">
<cfreturn ""/>
</cfcase>
<cfcase value="getAvailableResourceRealms">
<cfreturn getAvailableResourceRealms(arguments.svcId, arguments.contractId)/>
</cfcase>
<cfcase value="getSampleList"><!--- for debug --->
<cfreturn "dummy1,dummy2"/>
</cfcase>
<cfdefaultcase>
<cfreturn "function not found"/>
</cfdefaultcase>
</cfswitch>
</cffunction>
</cfcomponent>
+141 -77
View File
@@ -22,7 +22,7 @@
<cfset local={}/>
<cfquery name="local.qRead" result="local.result">
<cfquery name="local.qCfsParam" result="local.result">
select
<m:field_set titleMapOut="local.titleMap" lengthOut="fieldCount">
<m:field>iop.instance_operation_cfs_param_uid::text as instance_operation_cfs_param_uid</m:field>
@@ -36,9 +36,11 @@
<m:field>sop.svc_operation_cfs_param</m:field>
<m:field>sop.data_type</m:field>
<m:field>null as data_descriptor</m:field>
<m:field formatter=#function(x){return listToArray(x);}#>sop.value_list</m:field>
<m:field>u.login as creator_login</m:field>
<m:field>u.shortname as creator_shortname</m:field>
<m:field formatter=#request.castToBool#>sop.is_sensitive</m:field>
<m:field>sop.func</m:field>
</m:field_set>
from instance_operation_cfs_param iop
join svc_operation_cfs_param sop on (iop.svc_operation_cfs_param_id=sop.svc_operation_cfs_param_id)
@@ -50,89 +52,32 @@
AND si.specification_id=<cfqueryparam cfsqltype="cf_sql_integer" value=#arguments.specificationId#/>
</cfquery>
<cfif local.qRead.recordCount EQ 0>
<cfif local.qCfsParam.recordCount EQ 0>
<cfreturn representationOf(this.helper.formatMessage("Not Found")).withStatus(404)/>
</cfif>
<cfif len(local.qCfsParam.func)><!--- приоритет отдается функции перед списком значений--->
<cfset var args = {
"functionName":"#func#",
"svcId":#local.qInstanceOperation.service_id#,
"contractId":#arguments.contractId#
}/> <!--- если появятся новые аргументы у новых функций, будем добавлять их сюда --->
<cfset local.qCfsParam.value_list=generateValueList(argumentCollection=#args#)/> <!--- можно перечислить именованные аргументы обычным порядком, но с коллекцией потенциально более гибко --->
<!--- <cfdump var=#local.qCfsParam#/><cfabort/> --->
<cfif len(trim(local.qCfsParam.value_list)) AND listLen(local.qCfsParam.value_list) EQ 1>
<cfset local.qCfsParam.default_value=local.qCfsParam.value_list/>
</cfif>
</cfif>
<cfif local.qCfsParam.data_type EQ "map">
<cfset processMap(local.qCfsParam)/><!--- query passed by reference --->
</cfif>
<cfif local.qRead.data_type EQ "map">
<cfset var map={}/>
<cftry>
<cfset var map=deserializeJson(local.qRead.param_value)/>
<cfcatch type="any"><cfrethrow/></cfcatch>
</cftry>
<cfquery name="local.qSubparam">
select
sp.svc_operation_cfs_param_id
,sp.svc_operation_cfs_subparam_id
,sp.svc_operation_cfs_subparam
,sp.label
,sp.data_type
,sp.value_list
,sp.is_required
,sp.descr
,sp.man
,sp.default_value
,sp.minlength
,sp.maxlength
,sp.regex
,sp.sort
,sp.is_sensitive
from svc_operation_cfs_subparam sp
where sp.svc_operation_cfs_param_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#local.qRead.svc_operation_cfs_param_id#"/>
order by sp.sort
</cfquery>
<cfquery name="local.qInstSubparam">
select
sp.instance_operation_cfs_param_uid::text as instance_operation_cfs_param_uid
,sp.instance_operation_cfs_subparam
,sp.note
,sp.sort
,sp.is_sensitive
from instance_operation_cfs_subparam sp
where sp.instance_operation_cfs_param_uid=<cfqueryparam cfsqltype="cf_sql_other" value="#local.qRead.instance_operation_cfs_param_uid#" null=#!isValid("guid",local.qRead.instance_operation_cfs_param_uid)#/>
order by sp.sort
</cfquery>
<cfset var mapDescriptor=structNew("linked")/>
<cfloop query="local.qSubparam">
<cfset structInsert(mapDescriptor, local.qSubparam.svc_operation_cfs_subparam,
{
"man":"#local.qSubparam.man#",
"isSensitive":#request.castToBool(local.qSubparam.is_sensitive)#
}, true
)
/>
<cfif local.qSubparam.is_sensitive AND structKeyExists(map,local.qSubparam.svc_operation_cfs_subparam)>
<cfset map["#local.qSubparam.svc_operation_cfs_subparam#"] = "********"/>
</cfif>
</cfloop>
<cfloop query="local.qInstSubparam">
<cfset structInsert(mapDescriptor, local.qInstSubparam.instance_operation_cfs_subparam,
{
"note":"#local.qInstSubparam.note#",
"isSensitive":#request.castToBool(local.qInstSubparam.is_sensitive)#
}, true
)
/>
<cfif local.qInstSubparam.is_sensitive AND structKeyExists(map,local.qInstSubparam.instance_operation_cfs_subparam)>
<cfset map["#local.qInstSubparam.instance_operation_cfs_subparam#"] = "********"/>
</cfif>
</cfloop>
<cfset local.qCfsParam.data_descriptor = mapDescriptor/>
<cfset local.qCfsParam.param_value = serializeJson(map)/>
</cfif><!---/map --->
<cfset var out=structNew("linked")/>
<cfset "out.queryDurationMs"=getTickCount() - request.startTickCount/>
<cfset "out.instanceOperationCfsParam" = this.helper.appendRecord(
structNew("linked"), "", local.titleMap, local.qRead, this.helper.snake2camel
structNew("linked"), "", local.titleMap, local.qCfsParam, this.helper.snake2camel
)/>
<cfset "out.runDurationMs"=getTickCount() - request.startTickCount/>
@@ -222,5 +167,124 @@
<cfset CreateObject("component", "instance_operation_cfs_param_ls").checkParam(local.qCheck.svc_operation_cfs_param_id, arguments.paramValue, arguments.instanceOperationCfsParamUid)/>
</cffunction>
<cffunction name="processMap" returntype="void" access="public">
<cfargument name="qParam" type="query" required=true/>
<cfset var map={}/>
<cftry>
<cfset var map=deserializeJson(arguments.qParam.param_value)/>
<cfcatch type="any"><cfrethrow/></cfcatch>
</cftry>
<cfquery name="local.qSubparam">
select
sp.svc_operation_cfs_param_id
,sp.svc_operation_cfs_subparam_id
,sp.svc_operation_cfs_subparam
,sp.label
,sp.data_type
,sp.value_list
,sp.is_required
,sp.descr
,sp.man
,sp.default_value
,sp.minlength
,sp.maxlength
,sp.regex
,sp.sort
,sp.is_sensitive
from svc_operation_cfs_subparam sp
where sp.svc_operation_cfs_param_id=<cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.qParam.svc_operation_cfs_param_id#"/>
order by sp.sort
</cfquery>
<!--- <cfdump var=#local.qSubparam#/><cfabort/> --->
<cfquery name="local.qInstSubparam">
select
sp.instance_operation_cfs_param_uid::text as instance_operation_cfs_param_uid
,sp.instance_operation_cfs_subparam
,sp.note
,sp.sort
,sp.is_sensitive
from instance_operation_cfs_subparam sp
where sp.instance_operation_cfs_param_uid=<cfqueryparam cfsqltype="cf_sql_other" value="#arguments.qParam.instance_operation_cfs_param_uid#" null=#!isValid("guid",arguments.qParam.instance_operation_cfs_param_uid)#/>
order by sp.sort
</cfquery>
<cfset var mapDescriptor=structNew("linked")/>
<cfloop query="local.qSubparam">
<cfset structInsert(mapDescriptor, local.qSubparam.svc_operation_cfs_subparam,
{
"man":"#local.qSubparam.man#",
"isSensitive":#request.castToBool(local.qSubparam.is_sensitive)#,
"isModifiableDefinition":false
}, true
)
/>
<cfif local.qSubparam.is_sensitive AND structKeyExists(map,local.qSubparam.svc_operation_cfs_subparam)>
<cfset map["#local.qSubparam.svc_operation_cfs_subparam#"] = "********"/>
</cfif>
</cfloop>
<cfloop query="local.qInstSubparam">
<cfset structInsert(mapDescriptor, local.qInstSubparam.instance_operation_cfs_subparam,
{
"note":"#local.qInstSubparam.note#",
"isSensitive":#request.castToBool(local.qInstSubparam.is_sensitive)#,
"isModifiableDefinition":true
}, true
)
/>
<cfif local.qInstSubparam.is_sensitive AND structKeyExists(map,local.qInstSubparam.instance_operation_cfs_subparam)>
<cfset map["#local.qInstSubparam.instance_operation_cfs_subparam#"] = "********"/>
</cfif>
</cfloop>
<cfset arguments.qParam.data_descriptor = mapDescriptor/>
<cfset arguments.qParam.param_value = serializeJson(map)/>
</cffunction>
<cffunction name="generateValueList" returntype="string" access="public">
<cfargument name="functionName" type="string" required="true"/>
<!--- остальные атрибуты необязательные, в argumentCollection (еще вопрос, насколько безопасно объявлять один из аргументов без остальных) --->
<cfswitch expression=#arguments.functionName#>
<cfcase value="">
<cfreturn ""/>
</cfcase>
<cfcase value="getAvailableResourceRealms">
<cfreturn getAvailableResourceRealms(arguments.svcId, arguments.contractId)/><!--- *** неочевидно, но ожидаются в argumentCollection --->
</cfcase>
<cfcase value="getSampleList"><!--- for debug --->
<cfreturn "dummy1,dummy2"/>
</cfcase>
<cfdefaultcase>
<cfreturn "function not found"/>
</cfdefaultcase>
</cfswitch>
</cffunction>
<cffunction name="getAvailableResourceRealms" returnType="string" access="public">
<cfargument name="svcId"/>
<cfargument name="contractId"/>
<cfset var local={}/>
<cfquery name="local.qAvailableResourceRealm"><!--- *** distinct халява, но придумывать корректную формулировку времени мало --->
select distinct r.resource_realm, r.sort
from resource_realm r
join resource_realm_access a on
(r.resource_realm_id=a.resource_realm_id
AND (a.contract_id=<cfqueryparam cfsqltype="CF_SQL_INTEGER" value=#arguments.contractId# null=#!isValid("integer", arguments.contractId)#/>
OR a.contract_id=0) /*0 means access to any contract*/
AND a.is_enabled)
join svc s on r.resource_realm_type_id=s.resource_realm_type_id
where s.svc_id=<cfqueryparam cfsqltype="CF_SQL_INTEGER" value=#arguments.svcId# null=#!isValid("integer", arguments.svcId)#/>
order by r.sort, r.resource_realm
</cfquery> <!--- <cfdump var=#arguments#/> cfdump здесь провоцирует NPE --->
<cfreturn valueList(local.qAvailableResourceRealm.resource_realm)/>
</cffunction>
</cfcomponent>
@@ -55,7 +55,8 @@
<cfset var maxrows=arguments.pageSize*arguments.page/>
<cfset var startrow=arguments.pageSize*(arguments.page-1)+1/>
<cfquery name="local.qRead" result="local.result">
<!--- *** обширное дублирование с instance_operation_cfs_param.cfc --->
<cfquery name="local.qCfsParam" result="local.result">
select
<m:field_set titleMapOut="local.titleMap" lengthOut="fieldCount">
<m:field title="instance_operation_cfs_param_uid">iop.instance_operation_cfs_param_uid::text as instance_operation_cfs_param_uid</m:field>
@@ -70,6 +71,12 @@
<m:field>sop.svc_operation_cfs_param</m:field>
<m:field>sop.sort</m:field>
<m:field formatter=#request.castToBool#>sop.is_sensitive</m:field>
<m:field>sop.data_type</m:field>
<m:field formatter=#function(x){return listToArray(x);}#>sop.value_list</m:field>
<m:field>sop.default_value</m:field>
<m:field>sop.func</m:field>
<m:field>null as data_descriptor</m:field>
<m:field>e.service_id</m:field>
</m:field_set>
from instance_operation_cfs_param iop
join instance_operation io on (iop.instance_operation_uid=io.instance_operation_uid)
@@ -89,18 +96,40 @@
from instance_operation_cfs_param iop
where iop.instance_operation_uid=<cfqueryparam cfsqltype="cf_sql_other" value="#arguments.instanceOperationUid#" null=#!isValid('guid',arguments.instanceOperationUid)#/>
</cfquery>
<cfloop query="local.qCfsParam">
<cfif len(func)><!--- приоритет отдается функции перед списком значений--->
<!--- *** отличается от аналогичных вызовов --->
<cfset var args = {
"functionName":"#func#",
"svcId":#local.qCfsParam.service_id#,
"contractId":#arguments.contractId#
}/> <!--- если появятся новые аргументы у новых функций, будем добавлять их сюда --->
<!--- <cfset local.qCfsParam.value_list=generateValueList(argumentCollection=#args#)/> --->
<cfinvoke component="instance_operation_cfs_param" method="generateValueList" argumentCollection=#args# returnVariable="local.qCfsParam.value_list"/><!--- *** тут засада с форматом списка: массив или лист --->
<!--- можно перечислить именованные аргументы обычным порядком, но с коллекцией потенциально более гибко --->
<cfif len(trim(local.qCfsParam.value_list)) AND listLen(local.qCfsParam.value_list) EQ 1>
<cfset local.qCfsParam.default_value=local.qCfsParam.value_list/>
</cfif>
</cfif>
<cfif data_type EQ "map">
<cfinvoke component="instance_operation_cfs_param" method="processMap" qParam=#local.qCfsParam#/>
</cfif>
</cfloop>
<cfset "out.queryDurationMs"=getTickCount() - request.startTickCount/>
<cfset "out.total"=#local.qTotal.cnt#/>
<cfset "out.resultSetSize"=#local.qRead.recordCount#/>
<cfset "out.resultSetSize"=#local.qCfsParam.recordCount#/>
<cfset "out.pageSize"=#arguments.pageSize*1#/>
<cfset "out.page"=#arguments.page*1#/>
<cfset "out.orderBy"=#arguments.orderBy#/>
<cfset var resultCollection=[]/>
<cfloop query=#local.qRead# startRow=#startrow# endRow=#(startrow+maxrows-1)#>
<cfloop query=#local.qCfsParam# startRow=#startrow# endRow=#(startrow+maxrows-1)#>
<cfset var rec={}/>
<cfset this.helper.appendRecord(rec, "", local.titleMap, local.qRead, this.helper.snake2camel)/>
<cfset this.helper.appendRecord(rec, "", local.titleMap, local.qCfsParam, this.helper.snake2camel)/>
<cfset arrayAppend(resultCollection, rec)/>
</cfloop>
+10 -8
View File
@@ -111,16 +111,17 @@
"svcId":#local.qSvcOperation.svc_id#,
"contractId":#arguments.contractId#
}/> <!--- если появятся новые аргументы у новых функций, будем добавлять их сюда --->
<cfset local.qCfsParam.value_list=generateValueList(argumentCollection=#args#)/> <!--- можно перечислить именованные аргументы обычным порядком, но с коллекцией потенциально более гибко --->
<!--- <cfdump var=#local.qCfsParam#/><cfabort/> --->
<!--- <cfset local.qCfsParam.value_list=generateValueList(argumentCollection=#args#)/> --->
<cfinvoke component="instance_operation_cfs_param" method="generateValueList" argumentCollection=#args# returnVariable="local.qCfsParam.value_list"/>
<cfif len(trim(local.qCfsParam.value_list)) AND listLen(local.qCfsParam.value_list) EQ 1>
<cfset local.qCfsParam.default_value=local.qCfsParam.value_list/><!--- *** не очень красиво перетирать query--->
<cfset local.qCfsParam.default_value=local.qCfsParam.value_list/><!--- *** не очень красиво перетирать query, но делаем это довольно часто --->
</cfif>
</cfif>
<cfif data_type EQ "map">
<!--- аналогично instance_operation.cfm, только без полей инстанса, только шаблон --->
<cfif data_type EQ "map"><!--- *** частичное дублирование с instance_operation_cfs_param.processMap --->
<!--- без полей инстанса, только шаблон --->
<cfquery name="local.qSubparam">
select
sp.svc_operation_cfs_param_id
@@ -149,7 +150,8 @@
<cfset structInsert(mapDescriptor, local.qSubparam.svc_operation_cfs_subparam,
{
"man":"#local.qSubparam.man#",
"isSensitive":#request.castToBool(local.qSubparam.is_sensitive)#
"isSensitive":#request.castToBool(local.qSubparam.is_sensitive)#,
"isModifiableDefinition":false
}, true
)
/>
@@ -213,7 +215,7 @@
</cffunction>
<cffunction name="getAvailableResourceRealms" returnType="string">
<!--- <cffunction name="getAvailableResourceRealms" returnType="string">
<cfargument name="svcId"/>
<cfargument name="contractId"/>
@@ -253,7 +255,7 @@
<cfreturn "function not found"/>
</cfdefaultcase>
</cfswitch>
</cffunction>
</cffunction> --->
</cfcomponent>