Difference between revisions of "Context Logic"
CarlosRuiz (talk | contribs) (Initial Documentation - Conditional Context Logic) |
CarlosRuiz (talk | contribs) m |
||
| (15 intermediate revisions by the same user not shown) | |||
| Line 6: | Line 6: | ||
== Conditional Context Logic == | == Conditional Context Logic == | ||
| + | |||
| + | {| class="wikitable" | ||
| + | ! Column | ||
| + | ! Class | ||
| + | ! Comments | ||
| + | |- | ||
| + | | AD_Column.AlwaysUpdatableLogic | ||
| + | AD_Field.AlwaysUpdatableLogic | ||
| + | AD_UserDef_Field.AlwaysUpdatableLogic | ||
| + | | org.compiere.model.GridField.isEditable | ||
| + | | | ||
| + | * if the logic starts with <code>@SQL=</code> is parsed with [[#Evaluator.parseSQLLogic]] | ||
| + | * otherwise is parsed using [[#Evaluator.evaluateLogic]] with the value from GridField or DefaultEvaluatee | ||
| + | |- | ||
| + | | AD_Tab.DeleteConfirmationLogic | ||
| + | | org.compiere.model.GridTab.getDeleteConfirmationLogic | ||
| + | | | ||
| + | * first calls FileUtil.parseTitle, which calls Env.parseVariable when related a PO record or Env.parseContext if not | ||
| + | * then calls Msg.parseTranslation, which replaces context using AD_Message or AD_Element | ||
| + | * [https://docs.idempiere.org/docs/new-features/v10/delete-record-with-confirmation-logic Documented here] | ||
| + | |- | ||
| + | | AD_UserDef_Tab.DeleteConfirmationLogic | ||
| + | |- | ||
| + | | AD_Attribute.DisplayLogic | ||
| + | |- | ||
| + | | AD_Field.DisplayLogic | ||
| + | |- | ||
| + | | AD_InfoColumn.DisplayLogic | ||
| + | |- | ||
| + | | AD_InfoProcess.DisplayLogic | ||
| + | |- | ||
| + | | AD_InfoRelated.DisplayLogic | ||
| + | |- | ||
| + | | AD_PrintFormatItem.DisplayLogic | ||
| + | |- | ||
| + | | AD_Process_Para.DisplayLogic | ||
| + | |- | ||
| + | | AD_StyleLine.DisplayLogic | ||
| + | |- | ||
| + | | AD_Tab.DisplayLogic | ||
| + | |- | ||
| + | | AD_ToolBarButton.DisplayLogic | ||
| + | |- | ||
| + | | AD_UserDef_Field.DisplayLogic | ||
| + | |- | ||
| + | | AD_UserDef_Info_Column.DisplayLogic | ||
| + | |- | ||
| + | | AD_UserDef_Info_Related.DisplayLogic | ||
| + | |- | ||
| + | | AD_UserDef_Proc_Parameter.DisplayLogic | ||
| + | |- | ||
| + | | AD_UserDef_Tab.DisplayLogic | ||
| + | |- | ||
| + | | AD_Workflow.DocValueLogic | ||
| + | |- | ||
| + | | AD_Column.MandatoryLogic | ||
| + | |- | ||
| + | | AD_Field.MandatoryLogic | ||
| + | |- | ||
| + | | AD_Process_Para.MandatoryLogic | ||
| + | |- | ||
| + | | AD_UserDef_Field.MandatoryLogic | ||
| + | |- | ||
| + | | AD_UserDef_Proc_Parameter.MandatoryLogic | ||
| + | |- | ||
| + | | REST_ViewColumn.MandatoryLogic | ||
| + | |- | ||
| + | | AD_ToolBarButton.PressedLogic | ||
| + | |- | ||
| + | | AD_Column.ReadOnlyLogic | ||
| + | |- | ||
| + | | AD_Field.ReadOnlyLogic | ||
| + | |- | ||
| + | | AD_Process_Para.ReadOnlyLogic | ||
| + | |- | ||
| + | | AD_Tab.ReadOnlyLogic | ||
| + | |- | ||
| + | | AD_ToolBarButton.ReadOnlyLogic | ||
| + | |- | ||
| + | | AD_UserDef_Field.ReadOnlyLogic | ||
| + | |- | ||
| + | | AD_UserDef_Proc_Parameter.ReadOnlyLogic | ||
| + | |- | ||
| + | | AD_UserDef_Tab.ReadOnlyLogic | ||
| + | |- | ||
| + | | REST_ViewColumn.ReadOnlyLogic | ||
| + | |- | ||
| + | | AD_Window.TitleLogic | ||
| + | |- | ||
| + | | AD_Scheduler.WebSessionLogic | ||
| + | |- | ||
| + | | AD_ZoomCondition.ZoomLogic | ||
| + | |} | ||
| + | |||
=== Used in === | === Used in === | ||
| Line 16: | Line 110: | ||
| AD_InfoProcess.DisplayLogic || org.adempiere.model.MInfoProcess.isDisplayed | | AD_InfoProcess.DisplayLogic || org.adempiere.model.MInfoProcess.isDisplayed | ||
|- | |- | ||
| − | | AD_Field | + | | AD_Field.DisplayLogic<br>AD_UserDef_Field.DisplayLogic<br>AD_Process_Para.DisplayLogic || org.compiere.model.GridField.isDisplayed |
|- | |- | ||
| − | | AD_Column | + | | AD_Column.ReadOnlyLogic<br>AD_Field.ReadOnlyLogic<br>AD_UserDef_Field.ReadOnlyLogic || org.compiere.model.GridField.isEditable |
|- | |- | ||
| AD_Process_Para.ReadOnlyLogic || org.compiere.model.GridField.isEditablePara | | AD_Process_Para.ReadOnlyLogic || org.compiere.model.GridField.isEditablePara | ||
|- | |- | ||
| − | | AD_Column | + | | AD_Column.MandatoryLogic<br>AD_Field.MandatoryLogic<br>AD_UserDef_Field.MandatoryLogic<br>AD_Process_Para.MandatoryLogic || org.compiere.model.GridField.isMandatory |
|- | |- | ||
| AD_Tab.DisplayLogic || org.compiere.model.GridTab.isDisplayed<br>org.adempiere.webui.adwindow.AbstractADTabbox.isDisplay<br>org.adempiere.webui.adwindow.CompositeADTabbox.updateBreadCrumb / updateTabState | | AD_Tab.DisplayLogic || org.compiere.model.GridTab.isDisplayed<br>org.adempiere.webui.adwindow.AbstractADTabbox.isDisplay<br>org.adempiere.webui.adwindow.CompositeADTabbox.updateBreadCrumb / updateTabState | ||
|- | |- | ||
| − | | AD_Tab | + | | AD_Tab.ReadOnlyLogic<br>AD_UserDef_Tab.ReadOnlyLogic || org.compiere.model.GridTab.isReadOnly |
|- | |- | ||
| AD_InfoColumn.DisplayLogic || org.compiere.model.MInfoColumn.isDisplayed | | AD_InfoColumn.DisplayLogic || org.compiere.model.MInfoColumn.isDisplayed | ||
| Line 70: | Line 164: | ||
| <pre>@AnyVariable:Default@</pre> || <pre>@0|C_Tax_ID:0@</pre> || At the end of any of the variables described above, you can set a default to be set when the variable is null or it doesn't exist, the default is defined at the end of the variable after a colon : | | <pre>@AnyVariable:Default@</pre> || <pre>@0|C_Tax_ID:0@</pre> || At the end of any of the variables described above, you can set a default to be set when the variable is null or it doesn't exist, the default is defined at the end of the variable after a colon : | ||
|- | |- | ||
| − | | <pre>@AnyVariable.Column@</pre> || <pre>@AD_Org_ID.Name@</pre> || This is a way to obtain and compare values from foreign tables, in the example it gets the Name from the table AD_Org for comparison | + | | <pre>@AnyVariable.Column@</pre> || <pre>@AD_Org_ID.Name@</pre> || This is a way to obtain and compare values from foreign tables, in the example it gets the Name from the table AD_Org for comparison. |
| + | NOTES: | ||
| + | |||
| + | * In process parameters this syntax just works for columnnames where the tablename is implicit in the name (like Table Direct). | ||
| + | * In Tab Display Logic this notation doesn't work | ||
| + | |- | ||
| + | |<pre>@$env.VARIABLE@</pre> | ||
| + | |<pre>@$env.USER@</pre> | ||
| + | |Obtain the value from an operating system environment variable ([https://idempiere.atlassian.net/browse/IDEMPIERE-4939 since r8.2]). | ||
| + | Example: | ||
| + | |||
| + | * <code>@$env.USER@</code> will be rendered as the username of the operating system | ||
| + | * <code>@$env.LANG@</code> will return the language of the operating system | ||
| + | |- | ||
| + | |<pre>@$sysconfig.VARIABLE@</pre> | ||
| + | |<pre>@$sysconfig.ZK_MAX_UPLOAD_SIZE@</pre> | ||
| + | |Obtain the value from a [https://wiki.idempiere.org/en/System_Configurator_(Window_ID-50006) System Configurator] variable ([https://idempiere.atlassian.net/browse/IDEMPIERE-6596 since r12]). | ||
| + | Example: | ||
| + | |||
| + | * <code>@$sysconfig.ZK_MAX_UPLOAD_SIZE@</code> will return the value of the System Configurator ZK_MAX_UPLOAD_SIZE | ||
|} | |} | ||
* Note that when checking a context variable ending with _ID the null is replaced with a zero value | * Note that when checking a context variable ending with _ID the null is replaced with a zero value | ||
| Line 100: | Line 213: | ||
|} | |} | ||
| + | == Evaluator.parseSQLLogic == | ||
| + | |||
| + | Logic based on a SQL query works like this: | ||
| + | * no row returned means false | ||
| + | * row(s) returned means true | ||
| + | |||
| + | The SQL logic must start with <code>@SQL=</code> and it uses commonly context variables. | ||
| + | |||
| + | Preceding the query with a <code>!</code> sign, this is, starting with <code>@SQL=!</code>, inverts the logic (no rows is true, otherwise false) | ||
| + | |||
| + | Example: | ||
| + | |||
| + | <syntaxhighlight lang="SQL"> | ||
| + | @SQL=!SELECT 1 FROM WS_WebService_Para WHERE WS_WebServiceType_ID = @WS_WebServiceType_ID:0@ | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | The evaluator calls a tab <code>Env.parseContext</code> with <code>ignoreUnparsable=false</code>, which means a bad context variable will make the SQL empty, log a warning and returns false. | ||
| + | |||
| + | There is a cache of 500 milliseconds for the result of a query, this means, if the query is executed again less than half second after finished the result from the cache is returned (to avoid extra visits to the database). | ||
| − | == | + | == Evaluator.evaluateLogic == |
| − | + | This calls [https://jenkins-artifacts.idempiere.org/javadocdev/org/idempiere/expression/logic/LogicEvaluator.html#evaluateLogic(org.compiere.util.Evaluatee,java.lang.String) LogicEvaluator.evaluateLogic] which evaluates logic according to what is explained in this javadoc. | |
== Context Variables Replacement == | == Context Variables Replacement == | ||
Latest revision as of 13:08, 4 September 2026
Context Logic Explained
Note, this page is work in progress, please feel free to contribute and help completing the documentation
There are many places within iDempiere where the application manages Context Logic and is difficult to keep track of all the possibilities of every field. This wiki page tries to collect the documentation about the fields and the possibilities of each logic.
Conditional Context Logic
| Column | Class | Comments |
|---|---|---|
| AD_Column.AlwaysUpdatableLogic
AD_Field.AlwaysUpdatableLogic AD_UserDef_Field.AlwaysUpdatableLogic |
org.compiere.model.GridField.isEditable |
|
| AD_Tab.DeleteConfirmationLogic | org.compiere.model.GridTab.getDeleteConfirmationLogic |
|
| AD_UserDef_Tab.DeleteConfirmationLogic | ||
| AD_Attribute.DisplayLogic | ||
| AD_Field.DisplayLogic | ||
| AD_InfoColumn.DisplayLogic | ||
| AD_InfoProcess.DisplayLogic | ||
| AD_InfoRelated.DisplayLogic | ||
| AD_PrintFormatItem.DisplayLogic | ||
| AD_Process_Para.DisplayLogic | ||
| AD_StyleLine.DisplayLogic | ||
| AD_Tab.DisplayLogic | ||
| AD_ToolBarButton.DisplayLogic | ||
| AD_UserDef_Field.DisplayLogic | ||
| AD_UserDef_Info_Column.DisplayLogic | ||
| AD_UserDef_Info_Related.DisplayLogic | ||
| AD_UserDef_Proc_Parameter.DisplayLogic | ||
| AD_UserDef_Tab.DisplayLogic | ||
| AD_Workflow.DocValueLogic | ||
| AD_Column.MandatoryLogic | ||
| AD_Field.MandatoryLogic | ||
| AD_Process_Para.MandatoryLogic | ||
| AD_UserDef_Field.MandatoryLogic | ||
| AD_UserDef_Proc_Parameter.MandatoryLogic | ||
| REST_ViewColumn.MandatoryLogic | ||
| AD_ToolBarButton.PressedLogic | ||
| AD_Column.ReadOnlyLogic | ||
| AD_Field.ReadOnlyLogic | ||
| AD_Process_Para.ReadOnlyLogic | ||
| AD_Tab.ReadOnlyLogic | ||
| AD_ToolBarButton.ReadOnlyLogic | ||
| AD_UserDef_Field.ReadOnlyLogic | ||
| AD_UserDef_Proc_Parameter.ReadOnlyLogic | ||
| AD_UserDef_Tab.ReadOnlyLogic | ||
| REST_ViewColumn.ReadOnlyLogic | ||
| AD_Window.TitleLogic | ||
| AD_Scheduler.WebSessionLogic | ||
| AD_ZoomCondition.ZoomLogic |
Used in
| Column | Class |
|---|---|
| AD_Tab.DisplayLogic | org.adempiere.impexp.GridTabCSVExporter.export |
| AD_InfoProcess.DisplayLogic | org.adempiere.model.MInfoProcess.isDisplayed |
| AD_Field.DisplayLogic AD_UserDef_Field.DisplayLogic AD_Process_Para.DisplayLogic |
org.compiere.model.GridField.isDisplayed |
| AD_Column.ReadOnlyLogic AD_Field.ReadOnlyLogic AD_UserDef_Field.ReadOnlyLogic |
org.compiere.model.GridField.isEditable |
| AD_Process_Para.ReadOnlyLogic | org.compiere.model.GridField.isEditablePara |
| AD_Column.MandatoryLogic AD_Field.MandatoryLogic AD_UserDef_Field.MandatoryLogic AD_Process_Para.MandatoryLogic |
org.compiere.model.GridField.isMandatory |
| AD_Tab.DisplayLogic | org.compiere.model.GridTab.isDisplayed org.adempiere.webui.adwindow.AbstractADTabbox.isDisplay org.adempiere.webui.adwindow.CompositeADTabbox.updateBreadCrumb / updateTabState |
| AD_Tab.ReadOnlyLogic AD_UserDef_Tab.ReadOnlyLogic |
org.compiere.model.GridTab.isReadOnly |
| AD_InfoColumn.DisplayLogic | org.compiere.model.MInfoColumn.isDisplayed |
| AD_ZoomCondition.ZoomLogic | org.compiere.model.MZoomCondition.findZoomWindowByTableId / findZoomWindowByTableId |
| AD_Workflow.DocValueLogic | org.compiere.wf.DocWorkflowManager.process |
| AD_StyleLine.DisplayLogic | org.adempiere.webui.adwindow.GridTabRowRenderer.applyFieldStyle org.adempiere.webui.editor.WEditor.buildStyle org.adempiere.webui.adwindow.GridTabRowRenderer.applyFieldStyle |
| AD_ToolBarButton.DisplayLogic | org.adempiere.webui.adwindow.ToolbarCustomButton.dynamicDisplay org.adempiere.webui.adwindow.ToolbarProcessButton.dynamicDisplay |
Syntax
format := {expression} [{logic} {expression}]
expression := @{context}@{operand}{value} or @{context}@{operand}{value}
logic := {|}|{&}
context := any global or window context
value := strings or numbers
logic operators := AND{&} or OR{|} with the previous result from left to right
operand := eq{=}, gt{>}, le{<}, not{~^!}
In other words, a conditional context logic is composed by one or several expressions (comparisons) processed from left to right with AND or OR operators, in this statement is important to note:
- Expression: means a comparison between a context variable and a constant (also between two constants or two context variables)
- Context variable can be:
| Syntax | Example | Description |
|---|---|---|
@#Variable@ |
@#AD_Org_ID@ |
These variables starting with # are set at login time |
@$Variable@ |
@$C_AcctSchema_ID@ |
Accounting variables (starting with $) also set at login time |
@Variable@ |
@C_Tax_ID@ |
This usually refers to a field in the current window (or another process parameter in the process dialog) |
@TabNo|Variable@ |
@0|C_Tax_ID@ |
This refers to a field on the specified tab (tab numbering starts with zero) |
@~Variable@ |
@~C_Tax_ID@ |
When the variable starts with ~ that means a field in the CURRENT tab, do not look for fields in the other tabs |
@P|Variable@ |
@P|C_Country_ID@ |
These are preferences, sometimes defined at login time, sometimes defined by the user |
@AnyVariable:Default@ |
@0|C_Tax_ID:0@ |
At the end of any of the variables described above, you can set a default to be set when the variable is null or it doesn't exist, the default is defined at the end of the variable after a colon : |
@AnyVariable.Column@ |
@AD_Org_ID.Name@ |
This is a way to obtain and compare values from foreign tables, in the example it gets the Name from the table AD_Org for comparison.
NOTES:
|
@$env.VARIABLE@ |
@$env.USER@ |
Obtain the value from an operating system environment variable (since r8.2).
Example:
|
@$sysconfig.VARIABLE@ |
@$sysconfig.ZK_MAX_UPLOAD_SIZE@ |
Obtain the value from a System Configurator variable (since r12).
Example:
|
- Note that when checking a context variable ending with _ID the null is replaced with a zero value
- Constants are strings or numeric values, the constants don't need to be surrounded by quotes, but if they are surrounded by quotes they are properly managed
- The constant empty string is defined as two quotes:
- The expression then requires a comparison operator, these are:
- Equals =
- Greater than >
- Less than <
- Different ! or ^ or ~
- Several expressions can be evaluated FROM LEFT TO RIGHT using AND or OR logical operators
- the AND operator is &
- the OR operator is |
Examples
| Condition | Description |
|---|---|
1=2 |
This is evaluated always as false |
@ElementType@=A & @IsSummary@=N & @IsDetailBPartner@=Y |
If the field ElementType contains an A, and the flag IsSummary is unchecked, and the flag IsDetailBPartner is checked |
@#AD_Client_ID@>0 |
When the field AD_Client_ID is greater than zero, this means false in System client, and true for all the other clients |
Evaluator.parseSQLLogic
Logic based on a SQL query works like this:
- no row returned means false
- row(s) returned means true
The SQL logic must start with @SQL= and it uses commonly context variables.
Preceding the query with a ! sign, this is, starting with @SQL=!, inverts the logic (no rows is true, otherwise false)
Example:
@SQL=!SELECT 1 FROM WS_WebService_Para WHERE WS_WebServiceType_ID = @WS_WebServiceType_ID:0@
The evaluator calls a tab Env.parseContext with ignoreUnparsable=false, which means a bad context variable will make the SQL empty, log a warning and returns false.
There is a cache of 500 milliseconds for the result of a query, this means, if the query is executed again less than half second after finished the result from the cache is returned (to avoid extra visits to the database).
Evaluator.evaluateLogic
This calls LogicEvaluator.evaluateLogic which evaluates logic according to what is explained in this javadoc.
Context Variables Replacement
TBD
