201 intermediate commit for state navigation

This commit is contained in:
2026-01-24 12:07:12 +03:00
parent d843620292
commit ee9331e6cd
11 changed files with 222 additions and 22 deletions
+14 -1
View File
@@ -160,6 +160,8 @@
<m:field>sop.config::text as config</m:field>
<m:field>null as nested_ref_data</m:field><!--- placeholder for future data --->
<m:field>sop.state_path</m:field>
<m:field>sop.depends_on_cfs_params</m:field>
<m:field>sop.expression</m:field>
<m:field formatter=#request.castToBool#>sop.is_sensitive</m:field>
</m:field_set>
from svc_operation_cfs_param sop
@@ -206,8 +208,19 @@
argumentCollection=#args#
returnVariable="local.qCfsParam.value_list"
/>
<cfelseif len(local.qCfsParam.expression) AND len(local.qCfsParam.instance_operation_cfs_param_uid)>
<cfset local.qCfsParam.value_list = createObject("component","lib.expression_parser")
.eval(
local.qCfsParam.expression,
{/*context*/
component:"resources.instance_operation_cfs_param",
keys:{"instanceOperationCfsParamUid"=#local.qCfsParam.instance_operation_cfs_param_uid#},
params:{}
}
)
/>
</cfif>
<!--- *** боюсь, где-то тут нужно будет делать вычисления субпараметров --->
<cfif data_type EQ "map" OR data_type EQ "map-fixed" OR data_type EQ "array-map-fixed">
<cfinvoke component="instance_operation_cfs_param" method="processMap" qParam=#local.qCfsParam#/>
</cfif><!---/map --->
+27 -4
View File
@@ -36,7 +36,7 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
<cfset this.instance_uid = "00000000-0000-0000-0000-000000000000"/><!--- *** костыль default=--->
<cfif structKeyExists(arguments.keys,"instanceOperationCfsParamUid")>
<cfset this.instance_operation_cfs_param_uid=arguments.keys.instanceOperationCfsParamUid/>
<cfset this.instance_operation_cfs_param_uid=arguments.keys.instanceOperationCfsParamUid/><!--- *** camelCase!!! --->
<cfquery name="local.qResolve">
select p.instance_operation_uid, o.instance_uid, p.svc_operation_cfs_param_id
from instance_operation_cfs_param p
@@ -274,7 +274,12 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
AND s.svc_operation_cfs_param = <cfqueryparam cfsqltype="cf_sql_varchar" value=#arguments.param#/>
</cfquery>
<cfif structKeyExists(arguments,"subparam")><!--- *** не изящно, но просто и понятно --->
<cfreturn deserializeJson(local.qCfsParam.param_value)[arguments.subparam]/>
<cfset var value = deserializeJson(local.qCfsParam.param_value)/>
<cfif isStruct(value) AND structKeyExists(value, arguments.subparam)>
<cfreturn value[arguments.subparam]/>
<cfelse>
<cfreturn ""/><!--- *** а надо выбросить 404 --->
</cfif>
<cfelse>
<cfreturn local.qCfsParam.param_value/>
</cfif>
@@ -628,6 +633,8 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
,sp.regex
,sp.sort
,sp.is_sensitive
,sp.depends_on_cfs_params
,sp.expression
--,sp.func
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#"/>
@@ -649,6 +656,7 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
<!--- формируем дескриптор --->
<cfset var mapDescriptor=structNew("linked")/>
<cfset var parser=createObject("component","lib.expression_parser")/>
<cfloop query="local.qSubparam">
<cfset structInsert(mapDescriptor, local.qSubparam.svc_operation_cfs_subparam,
@@ -657,7 +665,19 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
"svcOperationCfsSubparam":"#local.qSubparam.svc_operation_cfs_subparam#",
"label":"#local.qSubparam.label#",
"dataType":"#local.qSubparam.data_type#",
"valueList":"#local.qSubparam.value_list#",
"valueList":'#(len(local.qSubparam.expression)?
(parser.eval(
qSubparam.expression,
{
component:"resources.instance_operation_cfs_param",
keys:{
instanceOperationCfsParamUid:"#toString(arguments.qParam.instance_operation_cfs_param_uid)#", /*note camelCase*/
svcOperationCfsParamId:"#toString(arguments.qParam.svc_operation_cfs_param_id)#" /*note camelCase*/
},
params:{}
}
))
: local.qSubparam.value_list)#',
"minlength":"#local.qSubparam.minlength#",
"maxlength":"#local.qSubparam.maxlength#",
"regex":"#local.qSubparam.regex#",
@@ -667,7 +687,10 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
<!--- "func":"#local.qSubparam.func#", --->
"isRequired":#request.castToBool(local.qSubparam.is_required)#,
"isSensitive":#request.castToBool(local.qSubparam.is_sensitive)#,
"isModifiableDefinition":false
"isModifiableDefinition":false,
"dependsOnCfsParams":"#local.qSubparam.depends_on_cfs_params#",
"expression":"#local.qSubparam.expression#"
}, true
)
/>
@@ -31,7 +31,8 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
login={prefix="iop", type="string"},
creator_id={prefix="iop", type="integer"},
sort={prefix="sop", type="integer"},
is_sensitive={prefix="sop", type="boolean"}
is_sensitive={prefix="sop", type="boolean"},
depends_on_cfs_params={prefix="sop", type="string"}
<!--- ,
dt_updated={prefix="e", type="date"},
service_id={prefix="e", type="integer"},
@@ -91,6 +92,7 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
<m:field>sop.default_value</m:field>
<m:field>sop.func</m:field>
<m:field>sop.man</m:field>
<m:field>sop.depends_on_cfs_params</m:field>
<m:field>null as data_descriptor</m:field>
<m:field>e.service_id</m:field>
</m:field_set>
+6 -3
View File
@@ -95,7 +95,7 @@
<m:field>p.config::text</m:field><!--- в таком виде конфиг доступен для кода, но не выводится в респонсе --->
<m:field>null as nested_ref_data</m:field>
<m:field>p.state_path</m:field>
<m:field>p.depends_on_params</m:field>
<m:field>p.depends_on_cfs_params</m:field>
<m:field>p.expression</m:field>
<m:field formatter=#request.castToBool#>(
select 1 from svc_operation_cfs_param m
@@ -160,6 +160,8 @@
,sp.label
,sp.data_type
,sp.value_list
,sp.depends_on_cfs_params
,sp.expression
,sp.is_required
,sp.descr
,sp.man
@@ -176,7 +178,7 @@
</cfquery>
<cfset var mapDescriptor=structNew("linked")/>
<!--- *** выдавать на фронт expression нам ни к чему, это временное явление --->
<cfloop query="local.qSubparam">
<cfset structInsert(mapDescriptor, local.qSubparam.svc_operation_cfs_subparam,
{
@@ -185,13 +187,14 @@
"label":"#local.qSubparam.label#",
"dataType":"#local.qSubparam.data_type#",
"valueList":"#local.qSubparam.value_list#",
"dependsOnCfsParams":"#local.qSubparam.depends_on_cfs_params#",
"expression":"#local.qSubparam.expression#",
"minlength":"#local.qSubparam.minlength#",
"maxlength":"#local.qSubparam.maxlength#",
"regex":"#local.qSubparam.regex#",
"man":"#local.qSubparam.man#",
"descr":"#local.qSubparam.descr#",
"defaultValue":"#local.qSubparam.default_value#",
<!--- "func":"#local.qSubparam.func#", --->
"isRequired":#request.castToBool(local.qSubparam.is_required)#,
"isSensitive":#request.castToBool(local.qSubparam.is_sensitive)#,
"isModifiableDefinition":false
+2
View File
@@ -59,6 +59,8 @@
<m:field>r.mgmt_api_url</m:field>
<m:field>p.resource_realm as parent</m:field>
<m:field>t.resource_realm_type</m:field>
<m:field>r.descr</m:field>
<m:field>r.man</m:field>
<m:field>to_char(r.dt_created, 'YYYY-MM-DD"T"HH24:MI:SS.FF3TZHTZM') as dt_created</m:field>
<m:field>to_char(r.dt_updated, 'YYYY-MM-DD"T"HH24:MI:SS.FF3TZHTZM') as dt_updated</m:field>
</m:field_set>
+1
View File
@@ -51,6 +51,7 @@
<m:field>p.descr</m:field>
<m:field>p.man</m:field>
<m:field>p.sort</m:field>
<m:field>p.depends_on_cfs_params</m:field>
<m:field formatter=#request.castToBool#>(
select 1 from svc_operation_cfs_param m
join svc_operation om on (m.svc_operation_id=om.svc_operation_id)
@@ -38,7 +38,7 @@ arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //In
<cftry>
<cfset this.helper.validateField(arguments, "svcOperationCfsParamId", "integer")/>
<cfset this.helper.validateField(arguments, "svcOperationCfsSubparamId", "integer", false)/>
<!--- <cfset this.helper.validateField(arguments, "svcOperationCfsSubparamId", "integer", false)/> --->
<cfset this.helper.validateField(arguments, "keys", "json")/> <!--- *** может, не лучшая идея передавать ключ в контексте --->
<cfset this.helper.validateField(arguments, "params", "json")/>
<cfcatch type="invalidParamValue">
@@ -0,0 +1,98 @@
<cfcomponent extends="taffy.core.resource" taffy:uri="/svcOperationCfsSubparams/compute/{svcOperationCfsSubparamId}" hint="вычисляет выражение в поле expression">
<!---
вычисляет выражение в поле expression
для этого нужен контекст - как минимум, сохраненные параметры, но это не работает при создании нового инстанса,
поэтому нужно инициализировать контекст и набивать его всей необходимой информацией
что особенно важно для зависимых параметров - нам нужно положить в контекст все параметры, от которых мы зависим
чтобы знать, какие параметры передавать - конструкцией для параметра предусмотрено поле depends_on_params (надо будет его сделать вычисляемым), а для субпараметра пока не
--->
<!--- Все методы неявно получают
arguments.usrId
arguments.contragentId
arguments.contractId
arguments.specificationId
arguments.requestArguments.usrId=usrCustomerInfo.usrId; //Integer!
arguments.requestArguments.contragentId=usrCustomerInfo.contragentId; //Integer
arguments.requestArguments.contractId=usrCustomerInfo.contractId; //Integer
arguments.requestArguments.specificationId=usrCustomerInfo.specificationId; //Integer
--->
<cfsilent>
<cfimport prefix="m" taglib="../lib"/>
<cfset this.helper=CreateObject("component","lib.rest_api_helper")/><!---*** странно, почему мы его видим?---><!---вынести в апп?--->
</cfsilent>
<cffunction name="get" hint="вычисление возможных значений cубпараметра CFS параметра операции, в текущем контексте">
<!--- <cfargument name="instanceOperationCfsParamUid" type="string" required=true hint="type:guid"/> а вот ни фига--->
<!--- *** Важно: мы должны уметь посчитать параметр, если он не сохранен, то есть мы знаем его класс, а не инстанс --->
<!--- Вероятно, нам не очень нужно вычислять набор значений для инстанса параметра, мы всегда знаем класс --->
<!--- контест: --->
<cfargument name="svcOperationCfsSubparamId" type="string" required=false hint="type:integer"/>
<cfargument name="keys" type="string" default={} hint="type:json keys we depend on: of the param uid itself, or operation uid, instance uid, service operation cfs param - if not all entities intstantiated yet"/>
<cfargument name="params" type="string" default="{}" hint="type:json any posted parameters we depend on"/>
<cftry>
<cfset this.helper.validateField(arguments, "svcOperationCfsSubparamId", "integer")/>
<cfset this.helper.validateField(arguments, "keys", "json")/> <!--- *** может, не лучшая идея передавать ключ в контексте --->
<cfset this.helper.validateField(arguments, "params", "json")/>
<cfcatch type="invalidParamValue">
<cfreturn representationOf(this.helper.formatBadRequestError(cfcatch)).withStatus(400)/>
</cfcatch>
</cftry>
<cfset local={}/>
<cfset local.expression = ""/> <!--- нет смысла выносить это в поля класса, оно нужно только локально --->
<cfset local.calculatedValueList = ""/>
<cfset local.keys = deserializeJson(arguments.keys)/>
<cfset local.params = deserializeJson(arguments.params)/>
<cfset local.keys.svcOperationCfsSubparamId = arguments.svcOperationCfsSubparamId/> <!--- *** сомнительное дело гонять аргументы туда-сюда --->
<cfquery name="local.qCfsSubparam" result="local.result">
select
<m:field_set titleMapOut="local.titleMap" lengthOut="fieldCount">
<m:field>sop.data_type</m:field>
<m:field>sop.svc_operation_cfs_subparam</m:field>
<m:field>sop.expression</m:field>
</m:field_set>
from svc_operation_cfs_subparam sop
where sop.svc_operation_cfs_subparam_id
= <cfqueryparam cfsqltype="cf_sql_integer" value=#arguments.svcOperationCfsSubparamId# null=#!isValid('integer',arguments.svcOperationCfsSubparamId)#/>
</cfquery>
<cfif local.qCfsSubparam.recordCount EQ 0>
<cfreturn representationOf(this.helper.formatMessage("Service Operation CFS Parameter Not Found")).withStatus(404)/>
</cfif>
<cfset local.expression=local.qCfsSubparam.expression/>
<!--- *** можно обратить внимание, что мы инстанциируем не субпараметр, а параметр (цинично пользуясь их функциональной идентичностью... но некрасиво) --->
<cfif len(local.expression)>
<cfset calculatedValueList=createObject("component","lib.expression_parser")
.eval(
local.expression,
{/*context*/
component:"resources.instance_operation_cfs_param", /*param, not subparam*/
keys:#local.keys#,
params:#local.params#
}
)
/>
<cfelse>
<cfreturn representationOf(this.helper.formatMessage("Expression Not Found")).withStatus(404)/>
</cfif>
<!--- Тут нам еще придется сформатировать лист в массив. Но обошлось довольно просто --->
<cfset var out=structNew("linked")/>
<cfset "out.queryDurationMs"=getTickCount() - request.startTickCount/>
<cfset "out.values" = listToArray(local.calculatedValueList)/>
<cfset "out.runDurationMs"=getTickCount() - request.startTickCount/>
<cfreturn representationOf(out) />
</cffunction><!--- get --->
</cfcomponent>