# DSL and Snippet

## Basic Concept

DSL (Domain Specific Language) refers to a computer language that focuses on implementing application domain behavior.  
Our DSL is based on the Groovy language, combined with the custom grammar commonly applicable to insurance related business scenario, which finally becomes a fast-starting, easy-to-use language to facilitate system configuration.

Snippet in the other hand is a bundle of typical script examples which might combine several behaviors of DSL and Snippet together.


## User Scenario

For anybody who wants to use our platform to query existing DSL or even extend a new DSL.

## Basic Concept Introduction

#### Groovy

To start with configuration, we need to first know about the Groovy.   
Groovy, in essence, is the programming language that adapts well with Java. It is used to implement general logic, such as defining variables, judging existence, making comparative judgment or perform array loops. 

This is the official [Groovy website](http://groovy-lang.org/index.html) and an abstract about Groovy is as follows:
> Groovy is an agile dynamic language for the Java platform with many features inspired by languages such as Python, Ruby, and Smalltalk, allowing Java developers to use Java-like syntax to use them.

Compared to other programming languages, Groovy is a simpler one, which has a simplified syntax and works efficiently. It is suitable for flexible and dynamic scenarios, such as rule-based scenarios. 

Groovy is like a common programming language. Based on Groovy, we have encapsulated a series of DSL to achieve insurance business domain behaviors and interact with our base APIs.

#### DSL

DSL is a domain-specific programming language. It’s used to achieve insurance domain related actions such as retrieval of special field values like premium in policy, coverage or to trigger underwriting when needed.  

Based on the insurance business characteristics, insureMO has encapsulated a series of DSLs based on Groovy to implement the following major types of actions:

| Function Set | Description |
| ------ | ------ |
| Domain Object Function | Model processing such as acquisition and update of field elements. |
| Date Function | Date processing functions such as special date comparison. |
| Rule Action Function | Rule processing functions such as sending underwriting and notification letter. |
| Message Function | Message processing functions such as message acquisition and parameter logging. |
| Rating Function | Relevant calculation functions such as acquiring rate table and rounding etc. |

Now DSL is used in multiple system modules such as:

*  Rating Engine
*  Rule Engine
   -   Underwriting
   -   Attach Element
   -   Attach Form
   -   Complex validation rules
*  Numbering Template
*  Index Field
*  Model Filtering

DSL is generically provided by system which is different from snippet, which is more like a script example and can bundle multiple DSLs to achieve a typical scenario.

In the latest version, both DSL and Snippet can be maintained via UI and selected during rule configuration to further facilitate system configuration process.

At platform level, we are constantly maintaining our DSL pool to help user configuration journey easier and easier. Also, you can extend your own DSL tailored to your business scenario as well.


#### Snippet

Unlike Groovy or DSL which provides atomic operator to achieve system logics, snippet works as a combination of Groovy and DSL to achieve a sample function logic.

It helps orchestrate multiple Groovy and DSL operator together and serves as a typical example of certain script pattern so as to further facilitate users in the configuration process.

There are multiple default snippets maintained at platform level and tenant can extend your own snippet when feels necessary.


## DSL Script UI Operation

<div class="docs-caution"><span class="docs-admonitions-text">caution</span>

*  All operations in this text need to be performed in the portal Master Configuration environment (MC env). They are not allowed in other environments unless for troubleshooting purposes.
*  Please make sure you have all read and write authority to make the operation beforehand.

</div> 

#### DSL Script Operation

  The **DSL Script** supports to customize **DSL Script** by the tenant.

  *  Name: according to the coded function name or the name you will customize it.
  *  Module: choose the option according to your design.
  *  Group: choose the option according to your design. If no option matches, please add the group under the menu **Public Setting** > **Configuration Group**, select the **Resource Type** as the **Dsl Script**.
  *  Type:
     *  Configuration: code the related logic in the UI. System will load it when called from rating or rule.
     *  Code in Service: The logic coded in application codes. Here just provide an introduction to it.
  *  Microservice Name: choose the option according to your design. If the service name is not in the dropdown list, just input it manually.
  *  Running Scope: choose the option according to your design.

   ![DSL Script](./image/dsl/edit_dsl.png)
   
  
#### DSL Script Configuration
   If you want to customize some DSL functions, you can set the DSL Script Type to be Configuration.
   
   ![Customized DSL Script](./image/dsl/customized_dsl.png)
   
   Then you can invoke it in rule or rating formula.
   
   ![Invoke Customized DSL Script](./image/dsl/customized_dsl_invoke.png)
   
   The related tracking log is as below.
 
   ![Invoke Customized DSL Script Tracking](./image/dsl/customized_dsl_invoke_tracking.png)

## Config Snippet UI Operation

<div class="docs-caution"><span class="docs-admonitions-text">caution</span>

*  All operations in this text need to be performed in the portal Master Configuration environment (MC env). They are not allowed in other environments unless for troubleshooting purposes.
*  Please make sure you have all read and write authority to make the operation beforehand.

</div> 

   The **Config Snippet** supports to maintain the typical example of combination of multiple DSLs.

  *  Title: according to the coded function name or the name you will customize it.
  *  Module: choose the option according to your design.
  *  Group: choose the option according to your design. If no option matches, please add the group under the menu **Public Setting** > **Configuration Group**, select the **Resource Type** as the **Config Snippet**.

   ![Config Snippet](./image/dsl/edit_configsnippet.png)


## Typical DSL Syntax Illustration

In this section, we will introduce the basic syntax of Groovy commonly used in DSL. If you want to learn more about Groovy language, you can visit its official website.

### Comments

The annotated code will not be executed to alert itself and subsequent maintainers to the code.
Use "//" or "/\*\*\*.......\*\*\*/" for code comments, such as:

```groovy
// a standalone single line comment
println "hello world"		// a comment till the end of the line
/* a standalone multiline comment
	spanning two lines*/
println " hello world " 	/* a multiline comment starting
							at the end of a statement*/
println "hello" /*a standalone in-line comment*/ + "world "
```

### Identifiers

In Groovy, variables are generally defined using ***def***, and variable names have the following requirements:

+ Consist of **ascii letters** (a-z, A-Z),**number** (0-9) or **underscore** (\_)
+ First place **cannot** be number.
+ [Keywords](#keywords1) **cannot** be used as variable names.
+ We recommend hump naming in lowercase letters.

The following definitions can be used:

```groovy
def name
def abc123
def under_score
def camelCase
```

The following definitions will generate an error:

```groovy
def 1a       // Cannot start with a number
def a+b      // Cannot contain other characters "+"
def a#b      // Cannot contain other characters "#"
def this     // Cannot contain keyword this
```

You can also set initial values for defined variables:

```groovy
def str = "hello world"	// Define a string
def num = 1				// Define an integer
def rate = 1.00			// Define a BigDecimal
```

### Keywords

#### Groovy Keywords

<table>
  <tr>
    <td>as </td>
    <td>assert</td>
    <td>break</td>
    <td>case </td>
    <td>catch </td>
    <td>class </td>
  </tr>
  <tr>
    <td>const </td>
    <td>continue</td>
    <td>def </td>
    <td>default</td>
    <td>do </td>
    <td>else </td>
  </tr>
  <tr>
    <td>enum </td>
    <td>extends</td>
    <td>false </td>
    <td>finally</td>
    <td>for </td>
    <td>goto </td>
  </tr>
  <tr>
    <td>if </td>
    <td>implements</td>
    <td>import </td>
    <td>in</td>
    <td>instanceof </td>
    <td>interface </td>
  </tr>
  <tr>
    <td>new </td>
    <td>null</td>
    <td>package </td>
    <td>return</td>
    <td>super </td>
    <td>switch </td>
  </tr>
  <tr>
    <td>this </td>
    <td>throw</td>
    <td>throws </td>
    <td>trait</td>
    <td>true </td>
    <td>try </td>
  </tr>
</table>


#### System Keywords


<table>
  <tr>
    <td>boolean </td>
    <td>byte</td>
    <td>char</td>
    <td>double </td>
  </tr>
  <tr>
    <td>float </td>
    <td>int </td>
    <td>long </td>
    <td>short</td>
  </tr>
  <tr>
    <td>null </td>
    <td>void</td>
    <td>abstract </td>
    <td>final </td>
  </tr>
  <tr>
    <td>native </td>
    <td>static</td>
    <td>strictfp </td>
    <td>synchronized</td>
  </tr>
  <tr>
    <td>transient </td>
    <td>volatile </td>
    <td>do </td>
    <td>context</td>
  </tr>
  <tr>
    <td>currentObject </td>
    <td>dataMessageList</td>
    <td>operationLogMap </td>
    <td>scriptId </td>
  </tr>
  <tr>
    <td>operationId </td>
    <td>user</td>
    <td>log </td>
    <td>scriptLogService</td>
  </tr>
  <tr>
    <td>Env </td>
    <td>dslService </td>
    <td>println </td>
    <td>supportService</td>
  </tr>
  <tr>
    <td>SpringContextUtils </td>
    <td>Policy</td>
    <td>Endorsement </td>
    <td>PolicyLog </td>
  </tr>
</table>


### Operators

#### Arithmetic Operators

- \+    *addition*
- \-    *subtraction*
- \*    *multiplication*
- /    *division*
- %   *remainder*
- \*\*   *power*

```groovy
def a = 10
def b = 4
def c = a + b		// 14
def d = a - b		// 6
def e = a * b		// 40
def f = a / b		// 2.5
def g = a % b		// 2
def h = a ** b		// 10000
```

#### Relational and Logical Operators

- ==          *equal*
- !=           *different*
- <, <=    *less than, less than or equal*
- \>, >=    *greater than, greater than or equal*
- &&         *and*
- ||            *or*
- !             *not*

```groovy
def a = 10
def b = 4
def c = a == b					// false
def d = a != b					// true
def e = a < b					// false
def f = a >= b					// true
def g = true && false 			 // false
def h = false || true			 // true
def I = !false					// true
```

#### Ternary Operator

\(condition) ? \(exprIfTrue) : \(exprIfFalse)

```groovy
def a = 10
def b = 4
def c = a > b ? a : b 		// if a is greater than b, take a; otherwise, take b
```

### Lists

Groovy's list is separated by square brackets and commas. Groovy's list and java.util. List are a concept. Groovy doesn't define its own collection class. By default, the list is implemented as java.util.ArrayList. Note that the subscript of the list starts at 0.

#### Create A List

```groovy
def a = []	 			// Create an empty list
def b = [0, 1, 2, 3] 	 // Create a number list
def c = ['a','b','c']	 // Create a string list
```

#### Get Value in A List

<p class="danger">If the corner is larger than the actual list size, an IndexOutOfBoundsException will be thrown.</p>

```groovy
def list = ['a','b','c','d']  
def b = list[0] 			// a
def c = list[-1]			// b
def d = list[0..2]			// ['a','b','c']
```

#### Modify A List

```groovy
def list = ['a','b','c','d']  
list + ['e']			// ['a','b','c','d','e']  
list - ['a']			// ['b','c','d']  
list.add('e','f')		// ['a','b','c','d','e','f']  
list.remove(0)			// ['b','c','d']
```

#### Others

```groovy
def list = ['a','b','d','c','c']  
def a = list.size()   		// 5  Get size of a list
def b = list.empty  		// false  Determine if a list is empty
def c = list.sort()  		// ['a','b','c','c','d']    Sort a list
def d = list.unique()  		// ['a','b','c','d']    Deduplication a list
```

### Maps

Groovy's Map uses square brackets, keys and values separated by colons, and key-value pairs separated by commas.

```groovy
def emptyMap = [:]			// Create an empty map
def map = ['a':1,'b':2]		 // Create a map
def a = map['a']			// 1
def b = map.a				// 1
map['b'] = 3				// ['a':1,'b':3]
map.b = 3					// ['a':1,'b':3]
```

### Control Structures

The control structure allows the programming language to control the execution flow through code. In Groovy, there are simple versions of the daily control structures, such as if-else, switch and for.

#### If-else

```groovy
def a = 0
def b = 1
if ( a == b ) {
    println("a == b")		// Does not meet the conditions, will not print
}
if ( a > b ) {
    println("a > b")		// Does not meet the conditions, will not print
} else {
    println("a <= b")		// Execute else, print "a <= b"
}	
```

Multiple judgments can be:

```groovy
if ( ... ) {   ...   } 
else if (...) {    ...   } 
else {    ...    }
```

#### Switch-case

Groovy switch statements can handle any type of switch value and perform different types of matches.

```groovy
def x = 1
def result = ""
switch ( x ) {
    case [4, 5, 6, 'inList']:		 // Not in the list
        result = "list"
        break
    case 0..4:						// Between 0 and 4
        result = "in range"			 // No break, will continue to execute the case
    case Number:					// Is the number
        result += "number"		
        break						// Break, interrupt
    case { it < 0 }: 
        result = "negative"
        break
    default:
        result = "default"
}
return result						// return result "in rangenumber"
```

#### Loop

The for loop in Groovy is much simpler and can be used with any type of array, collection, map, etc.

```groovy
for (it in 0..9) {					// Loop integer
   println(it)
}
def list = ['a','b','c']			 // Use 'for' loop list
for (it in list) {
   println(it)
}
list.each{it -> println(it)}		 // Use '.each' loop list
def map = ['a':1,'b':2]
for (it in map){				    // Use 'for' loop map
    println(it.key + it.value)
}
map.each(k, v -> println(k + v))	 // Use '.each' loop map
```

### Other Commands

#### Return

```groovy
def a = "abc"
return a
```

#### Type Convert

```groovy
def a = "1"				
def b = a.toLong()		// b == 1
def c = b.toDouble()	// c == 1.00
def e = c.toString()	// d == "1.00"
```

#### Find

```groovy
["a","b","c"].find( it -> it == "a")	// return "a", find a single element
[1,2,3,4].findAll( it -> it < 3)		// return [1,2]，find multiple elements
```



## DSL Script - Model

### Model

Model is used based on DD models.

#### Get the current level or a parent model

```groovy
/**  Current model is PolicyRisk  **/
def risk = PolicyRisk()		// Get PolicyRisk, current model
def policy = Policy()		// Get Policy, parent model
```

#### Get a submodel

```groovy
/**  Current model is Policy  **/
def risk = PolicyRisk("C100000")	// Get a PolicyRisk of code C100000
```

#### Get a list of submodels

```groovy
/**  Current model is Policy  **/
def risks = PolicyRisks()		// Get list of PolicyRisk
def cts = PolicyRisk("C1000").PolicyCoverages()	// Get the list of PolicyCoverage with code C1000
```

#### Get the parent model

```groovy
/**  Current model is PolicyRisk  **/
def lob = PolicyRisk().getParent()  // Get parent model of PolicyRisk - PolicyLob
def policy = PolicyRisk().parent.parent	// Get parent model of parent model of PolicyRisk - Policy
```

#### Get product element model

```groovy
/**  Current model is PolicyRisk  **/
def productElement = PolicyRisk().getReferenceObject()	// Get the product elements on the Risk
```

#### Get the policy of previous version

<p class="warning"> Only for endorsement scenario.</p>

```groovy
/**  Current model is PolicyRisk  **/
def riskLog= PolicyRisk().getLog()	// Get the last modified version model on the Risk
```

#### Get the Java model for method invocation

```groovy
/**  Current model is PolicyRisk  **/
def risk = PolicyRisk().currentObject	// Get the java model of the Risk
```

### Field


#### Get value of a field

```groovy
/**  Current model is Policy  **/
def premium = Policy().Premium.val	// Get value of Premium in Policy
```

####  Determine if a field value is empty

```groovy
/**  Current model is Policy  **/
def premium = Policy().Premium.isEmpty	// Determine Premium in Policy is empty
```

#### Determine if a field is bound

```groovy
/**  Current model is Policy  **/
def premium = Policy().Premium.isBound	// Determine Premium is bound in Policy
```

### Update value of a field

```groovy
/**  Current model is Policy  **/
def premium = Policy().Premium.update("100.00")	  // Update Premium
```


## DSL Script - Platform

### Number

#### nullToZero

> nullToZero(value)

​	*Convert null values to 0.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  value   </span>   	*number, Necessary, The value to be converted.*

> Returns

​	<span style="color:#0070c0" class="field_name">  number   </span>     *Returns 0 if value is empty, or value if value is not empty.*

> Example

```groovy
def a = 1
def b = nullToZero(a)		// return a
def c = nullToZero(null)	// return 0
```

#### sum

> sum(value...)

​	*Sum multiple values.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  value   </span>   	*array(number), Necessary/Variable, array of type numbers, values to be summed.*

> Returns

​	<span style="color:#0070c0" class="field_name">  number   </span>     *The sum of the values in the array.*

> Example

```groovy
def a = 1
def b = 2
def c = 3
return sum(a, b, c)		// return 1+2+3 = 6
```

#### average

> average(value...)

​	*Average multiple values.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  value   </span>   	*array(number), Necessary/Variable, array of type numbers, values to be averaged.*

> Returns

​	<span style="color:#0070c0" class="field_name">  number   </span>     *The average of the values in the array.*

> Example

```groovy
def a = 1
def b = 2
def c = 3
def d = 4
return average(a, b, c, d)		// return (1+2+3+4)/4= 2.5
```

#### max

> max(value1,value2...)

​	*Get the maximum of multiple values.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  value   </span>   	*array(number), Necessary/Variable, array of type numbers, values to be get maximum.*

> Returns

​	<span style="color:#0070c0" class="field_name">  number   </span>     *The maximum of the values in the array.*

> Example

```groovy
def a = -1.1
def b = 23333
return max(a, b)			// return 23333
```

#### maxInList(From V22.03.X)

> maxInList(list)

​	*Get the maximum of multiple values.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  list   </span>   	*array(number), Necessary/Variable, array of type numbers, values to be get maximum.*

> Returns

​	<span style="color:#0070c0" class="field_name">  number   </span>     *The maximum of the values in the array.*

> Example

```groovy
def a = -1.1
def b = 2
def c = 2333
return maxInList(a,b,c)			// return 23333
```


#### min

> min(value...)

​	*Get the minimum of multiple values.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  value   </span>   	*array(number), Necessary/Variable, array of type numbers, values to be get minimum.*

> Returns

​	<span style="color:#0070c0" class="field_name">  number   </span>     *The minimum of the values in the array.*

> Example

```groovy
def a = -1.1
def b = 2
return min(a, b)			// return -1.1
```

#### minInList(From V22.03.X)

> minInList(list)

​	*Get the minimum of multiple values.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  list   </span>   	*array(number), Necessary/Variable, array of type numbers, values to be get minimum.*

> Returns

​	<span style="color:#0070c0" class="field_name">  number   </span>     *The minimum of the values in the array.*

> Example

```groovy
def a = -1.1
def b = 2
def c = 23333
return minInList(a, b, c)			// return -1.1
```


#### multi

> multi(value...)

​	*Multiply multiple values.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  value   </span>   	*array(number), Necessary/Variable, array of type numbers, values to be get multiplied.*

> Returns

​	<span style="color:#0070c0" class="field_name">  number   </span>     *The product of the values in the array.*

> Example

```groovy
def a = 1.1
def b = 2
def c = 10
return multi(a, b, c)		// return a * b * c = 22
```

#### round

> round(precision)

​	*Round according to a precision.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  precision   </span>   	*Integer, Necessary, Number of decimal places to retain.*

> Returns

​	<span style="color:#0070c0" class="field_name">  BigDecimal   </span>     *The value after rounding according to the precision.*

> Example

```groovy
def a = 1.5551111
def b = a.round(3)			// a keep three decimals as 1.555
def c = b.round(1)			// b keep one decimal as 1.6
```

#### roundCeiling

> roundCeiling(precision)

​	*Round up according to a precision.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  precision   </span>   	*Integer, Necessary, Number of decimal places to retain.*

> Returns

​	<span style="color:#0070c0" class="field_name">  BigDecimal   </span>     *The value after rounding up according to the precision.*

> Example

```groovy
def a = 1.5551111
def b = a.roundCeiling(3)		// a keep three decimals as 1.556
def c = b.roundCeiling(1)		// b keep one decimal as 1.6
```

#### roundFloor

> roundFloor(precision)

​	*Round down according to a precision.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  precision   </span>   	*Integer, Necessary, Number of decimal places to retain.*

> Returns

​	<span style="color:#0070c0" class="field_name">  BigDecimal   </span>     *The value after rounding down according to the precision.*

> Example

```groovy
def a = 1.5551111
def b = a.roundCeiling(3)		// a keep three decimals as 1.555
def c = b.roundCeiling(1)		// b keep one decimal as 1.5
```

### Date
#### now

> now()

​	*Get current date and time.*

> Returns

​	<span style="color:#0070c0" class="field_name">  LocalDateTime   </span>     *Current date and time.*

> Example

```groovy
return now()		// return current date and time
```

#### date

> date(str)

​	*Convert a string to time.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  str   </span>   	*String, Necessary, Date string without time zone following ISO8601 specification.*

> Returns

​	<span style="color:#0070c0" class="field_name">  LocalDateTime   </span>     *The time format of the string.*

> Example

```groovy
def a = date("2015-01-01")			// return Jan.1, 2015
def a = date("2015-01-01 12:09:09")	// return Jan.1, 2015 12:9:9
```

#### getDayOfMonth

> getDayOfMonth(date)

​	*Get number of days in a date.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  date   </span>   	*LocalDateTime, Necessary, date to get number of days.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Integer   </span>     *number of days.*

> Example

```groovy
def a = date("2015-01-01")
return getDayOfMonth(a)			// return 1
```

#### getMonth

> getMonth(date)

​	*Get number of months in a date.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  date   </span>   	*LocalDateTime, Necessary, date to get number of months.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Integer   </span>     *number of months.*

> Example

```groovy
def a = date("2015-01-01")
return getMonth(a)			// return 1
```

#### getYear

> getYear(date)

​	*Get number of years in a date.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  date   </span>   	*LocalDateTime, Necessary, date to get number of years.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Integer   </span>     *number of years.*

> Example

```groovy
def a = date("2015-01-01")
return getYear(a)			// return 2015
```

#### getDateFromDateTime

> getDateFromDateTime(date)

​	*The start time of a date.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  date   </span>   	*LocalDateTime, Necessary, date to get start time.*

> Returns

​	<span style="color:#0070c0" class="field_name">  LocalDateTime   </span>     *0 o'clock on the day.*

> Example

```groovy
def a = date("2015-01-01 12:09:09")
return getDateFromDateTime(a)		// return Jan.1, 2015 0:0:0
```

#### daysBetween

> daysBetween(date1, date2)

​	*Get the difference in days between two dates.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  date1   </span>   	*LocalDateTime, Necessary, Start time.*

​	<span style="color:#0070c0" class="field_name">  date2   </span>   	*LocalDateTime, Necessary, End time.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Integer   </span>     *The number of days between two dates..*

> Example

```groovy
def a = date("2015-01-01")
def b = date("2015-02-01")
return daysBetween(a, b)			// return 31
```

#### daysBetweenRoundingUp

> daysBetweenRoundingUp(date1, date2)

​	*Get the difference in days between two dates and rounding up.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  date1   </span>   	*LocalDateTime, Necessary, Start time.*

​	<span style="color:#0070c0" class="field_name">  date2   </span>   	*LocalDateTime, Necessary, End time.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Integer   </span>     *The number days between two dates and rounding up.*

> Example

```groovy
def a = date("2015-01-01 12:00:00")
def a = date("2015-02-01")
return daysBetweenRoundingUp(a, b)		// return 31
```

#### daysBetweenDateWithoutTime

> daysBetweenDateWithoutTime(date1, date2)

​	*Get the difference in days between two dates without time.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  date1   </span>   	*LocalDateTime, Necessary, Start time.*

​	<span style="color:#0070c0" class="field_name">  date2   </span>   	*LocalDateTime, Necessary, End time.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Integer   </span>     *The number of days between two dates without time.*

> Example

```groovy
def a = date("2015-01-01 12:00:00")
def a = date("2015-02-01 13:00:00")
return daysBetweenDateWithoutTime(a, b)		// return 31
```

#### monthsBetween

> monthsBetween(date1, date2)

​	*Get the difference in months between two dates*

> Arguments

​	<span style="color:#0070c0" class="field_name">  date1   </span>   	*LocalDateTime, Necessary, Start time.*

​	<span style="color:#0070c0" class="field_name">  date2   </span>   	*LocalDateTime, Necessary, End time.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Integer   </span>     *The number of months between two dates.*

> Example

```groovy
def a = date("2015-01-01")
def b = date("2015-05-05")
return monthsBetween(a, b)		// return 4
```

#### monthsBetweenRoundingUp

> monthsBetweenRoundingUp(date1, date2)

​	*Get the difference in months between two dates and rounding up.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  date1   </span>   	*LocalDateTime, Necessary, Start time.*

​	<span style="color:#0070c0" class="field_name">  date2   </span>   	*LocalDateTime, Necessary, End time.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Integer   </span>     *The number of months between two dates and rounding up.*

> Example

```groovy
def a = date("2015-01-01")
def b = date("2015-05-05")
return monthsBetweenRoundingUp(a, b)	// return 5
```

#### yearsBetween

> yearsBetween(date1, date2)

​	*Get the difference in years between two dates.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  date1   </span>   	*LocalDateTime, Necessary, Start time.*

​	<span style="color:#0070c0" class="field_name">  date2   </span>   	*LocalDateTime, Necessary, End time.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Integer   </span>     *The number of years between two dates.*

> Example

```groovy
def a = date("2015-01-01")
def b = date("2017-05-05")
return yearsBetween(a, b)		// return 2
```

#### yearsBetweenRoundingUp

> yearsBetweenRoundingUp(date1, date2)

​	*Get the difference in years between two dates and rounding up.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  date1   </span>   	*LocalDateTime, Necessary, Start time.*

​	<span style="color:#0070c0" class="field_name">  date2   </span>   	*LocalDateTime, Necessary, End time.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Integer   </span>     *The number of years between two dates and rounding up.*

> Example

```groovy
def a = date("2015-01-01")
def b = date("2017-05-05")
return yearsBetweenRoundingUp(a, b)		// return 3
```

#### totalDaysOfYear

> totalDaysOfYear(date)

​	*The number of days in the year after the date is obtained, which is used to process the number of days in the year or leap year.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  date   </span>   	*LocalDateTime, Necessary, Start time.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Integer   </span>     *The number of days in a year after the date.*

> Example

```groovy
def a = date("2015-01-01")
return totalDaysOfYear(a)		// return 365
```

### Messages

#### message(From V22.03.X)

> message(message)

​	*Throw an error and interrupt the process.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  message   </span>   	*String, Necessary, Message content or message code.*


> Throws

​	<span style="color:#0070c0" class="field_name">  BusinessException   </span>     *Throw an exception message.*

> Example

```groovy
return message("CODE")		
```

#### messageWithParams(From V22.03.X)

> error(message, [params])

​	*Throw an error and interrupt the process.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  message   </span>   	*String, Necessary, Message content or message code.*

​	<span style="color:#0070c0" class="field_name">  [params]   </span>   	*array(Object), Unnecessary, Agruments of message content.*

> Throws

​	<span style="color:#0070c0" class="field_name">  BusinessException   </span>     *Throw an exception message.*

> Example

```groovy
return messageWithParams("CODE", [a,b,c] as Object[])		
```


#### error

> error(message, [params])

​	*Throw an error and interrupt the process.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  message   </span>   	*String, Necessary, Message content or message code.*

​	<span style="color:#0070c0" class="field_name">  [params]   </span>   	*array(Object), Unnecessary, Agruments of message content.*

> Throws

​	<span style="color:#0070c0" class="field_name">  BusinessException   </span>     *Throw an exception message.*

> Example

```groovy
error("error!")		// throw "error!"
```

#### warn

> warn(message, [params])

​	*Throw warnings without interrupting the process.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  message   </span>   	*String, Necessary, Message content or message code.*

​	<span style="color:#0070c0" class="field_name">  [params]   </span>   	*array(Object), Unnecessary, Agruments of message content.*

> Throws

​	<span style="color:#0070c0" class="field_name">  response header   </span>     *Throw a warning message in the response header.*

> Example

```groovy
warn("warning!")			// throw "warning!"
```

#### information

> information(message, [params])

​	*Throw information without interrupting the process.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  message   </span>   	*String, Necessary, Message content or message code.*

​	<span style="color:#0070c0" class="field_name">  [params]   </span>   	*array(Object), Unnecessary, Agruments of message content.*

> Throws

​	<span style="color:#0070c0" class="field_name">  response header   </span>     *Throw an information in the response header.*

> Example

```groovy
info("info!")			// throw "info!"
```

### Code Table

#### codeI18nDescByUserLang(From V22.04.X)

> codeI18nDescByUserLang(String codeTableName, String valueCode)

​	*According to the code  table name & id , return code table related lang's description of current user language.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  codeTableName  </span>   	*String, Necessary, Code table name.*

​	<span style="color:#0070c0" class="field_name">  valueCode   </span>   	*String, Necessary, query conditions.*


> Returns

​	<span style="color:#0070c0" class="field_name">  String </span>     *The description of the code table id.*

> Example

```groovy
codeI18nDescByUserLang("Action", "11")		// return "Product Synchronization Update"(en_US)
```


#### codeI18nDescByLangId(From V22.04.X)

> codeI18nDescByLangId(String codeTableName, String valueCode, String langId)

​	*According to the code  table name & id & required langId , return code table related description of the required language.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  codeTableName  </span>   	*String, Necessary, Code table name.*

​	<span style="color:#0070c0" class="field_name">  valueCode   </span>   	*String, Necessary, query conditions.*

​	<span style="color:#0070c0" class="field_name">  langId   </span>   	*String, Necessary, query conditions.*

> Returns

​	<span style="color:#0070c0" class="field_name">  String </span>     *The description of the code table id.*

> Example

```groovy
codeI18nDescByLangId("Action", "11", "zh_CN")		// return "Product Synchronization Update"
```

```groovy
codeI18nDescByLangId("Action", "11", "vi_VN")		// return "Cập nhật đồng bộ hóa sản phẩm"
```

#### codeI18nDescByLangId


### Configuration Table(Rate Table)

#### lookup

> lookup(rateTableCode, params, [date])

​	*According to the rate table code and arguments query rate table results, return a single record.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  rateTableCode   </span>   	*String, Necessary, Rate table code.*

​	<span style="color:#0070c0" class="field_name">  params   </span>   	*Map<String, Object>, Necessary, query conditions.*

​	<span style="color:#0070c0" class="field_name">  [date]   </span>   	*Date/LocalDateTime, Unnecessary, Time for getting version.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Map<String,Object>   </span>     *The result of the rate table.*

> Example

```groovy
return lookup("code", ["condition1":"condition"])		// return ["result1": "result"]
```

#### lookupWithDefault(From V24.01)

>  lookupWithDefault(rateTableCode,  params,  versionDate,  releaseDate, Map<String, Object> defaultValue)
>  lookupWithDefault( rateTableCode,params, Map<String, Object> defaultValue)

 ​  *If result found, return the result found, if not, return the default value set.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  rateTableCode   </span>   	*String, Necessary, Rate table code.*

​	<span style="color:#0070c0" class="field_name">  params   </span>   	*Map<String, Object>, Necessary, query conditions.*

​	<span style="color:#0070c0" class="field_name">  [date]   </span>   	*Date/LocalDateTime, Unnecessary, Time for getting version.*

​	<span style="color:#0070c0" class="field_name">  defaultValue   </span>     Map<String,Object> *The result of the rate table.*
> Returns

​	<span style="color:#0070c0" class="field_name">  Map<String,Object>   </span>     *The result of the rate table.*



> Example

No default is set,

```groovy
 lookup("0_Test240314", ["Coverage": "C3101-1", "PostCodeRange":"09330545", "Rule":"999","Age":10,"EffDate":effDay, "ExpDate": effDay,"Gender":"F", "Age2":10,"Age3":10])

```

Set default value if no result found,

```groovy
 lookupWithDefault("0_Test240314", ["Coverage": "C3101-1", "PostCodeRange":"09330545", "Rule":"999"],["Decision7":"Test", "Decision6":"Test", "Decision5":"Test", "Decision4":"Test", "Decision3":"Test", "Decision2":"Test", "Decision":"Test", "FatorFreq":99])

```


#### lookupByVersionDate(From V22.03.X)

> lookupByVersionDate (rateTableCode, params, LocalDateTime versionDate)

​	*According to the rate table code and arguments query rate table results, return a single record.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  rateTableCode   </span>   	*String, Necessary, Rate table code.*

​	<span style="color:#0070c0" class="field_name">  params   </span>   	*Map<String, Object>, Necessary, query conditions.*

​	<span style="color:#0070c0" class="field_name">  [versionDate]   </span>   	*Date/LocalDateTime, Unnecessary, Time for getting version.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Map<String,Object>   </span>     *The result of the rate table.*

> Example

```groovy
return lookupByVersionDate("code", ["condition1":"condition"], "versionDate")		// return ["result1": "result"]
```
#### lookupByVersionReleaseDate(From V22.03.X)

> lookupByVersionReleaseDate(rateTableCode, params, LocalDateTime versionDate, LocalDateTime releaseDate)

​	*According to the rate table code and arguments query rate table results, and return a single record.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  rateTableCode   </span>   	*String, Necessary, Rate table code.*

​	<span style="color:#0070c0" class="field_name">  params   </span>   	*Map<String, Object>, Necessary, query conditions.*

​	<span style="color:#0070c0" class="field_name">  [versionDate]   </span>   	*Date/LocalDateTime, Unnecessary, Time for getting version.*

​	<span style="color:#0070c0" class="field_name">  [releaseDate]   </span>   	*Date/LocalDateTime, Unnecessary, Time for release version.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Map<String,Object>   </span>     *The result of the rate table*

> Example

```groovy
return lookupByVersionReleaseDate("code", ["condition1":"condition"],"versionDate","releaseDate")		// return ["result1": "result"]
```

#### lookupForList

> lookupForList(rateTableCode, params, [date])

​	*According to the rate table code and arguments query rate table results, return multiple records.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  rateTableCode   </span>   	*String, Necessary, Rate table code.*

​	<span style="color:#0070c0" class="field_name">  params   </span>   	*Map<String, Object>, Necessary, query conditions.*

​	<span style="color:#0070c0" class="field_name">  [date]   </span>   	*Date/LocalDateTime, Unnecessary, Time for getting version.*

> Returns

​	<span style="color:#0070c0" class="field_name">  List< Map < String,Object>>   </span>     *The results of the rate table.*

> Example

```groovy
return lookupForList("code", ["condition1":"condition"])	// return [["result1": "result1"], ["result2": "result2"]]
```

#### lookupForListByVersionDate(From V22.03.X)

> lookupForListByVersionDate(rateTableCode, params, LocalDateTime versionDate) 

#### lookupForListByVersionReleaseDate(From V22.03.X)

> lookupForListByVersionReleaseDate(rateTableCode, params, LocalDateTime versionDate) 

#### lookupByName

> lookupByName(rateTableName, params, [date])

​	*According to the rate table name and arguments query rate table results, return a single record. Applicable to the same rate table name in different contexts.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  rateTableCode   </span>   	*String, Necessary, Rate table name.*

​	<span style="color:#0070c0" class="field_name">  params   </span>   	*Map< String, Object>, Necessary, query conditions.*

​	<span style="color:#0070c0" class="field_name">  [date]   </span>   	*Date/LocalDateTime, Unnecessary, Time for getting version.*

> Returns

​	<span style="color:#0070c0" class="field_name">  List< Map< String,Object>>   </span>     *The result of the rate table.*

>  Example

```groovy
return lookupByName("name", ["condition1":"condition"])	// return ["result1": "result"]
```

#### lookupByNameAndVersionDate(From V22.03.X)

> lookupByNameAndVersionDate(rateTableName, params, LocalDateTime versionDate)

#### lookupByNameAndVersionReleaseDate(From V22.03.X)

> lookupByNameAndVersionReleaseDate(rateTableName, params, LocalDateTime versionDate, LocalDateTime ratingBaseDate)


#### lookupDataTable
>  lookupDataTable(String name, Map<String, Object> conditions)

*According to the data table name and condition query data table, return a List< Map< String, Object>>.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  name   </span>   	*String, Necessary, Data table name.*

​	<span style="color:#0070c0" class="field_name">  conditionMap   </span>   	*Map< String, String>, Necessary, query conditions.*

> Returns

​	<span style="color:#0070c0" class="field_name">  List< Map< String, Object>>   </span>     *The result of the data table.*

>  Example without condition

```groovy
List<Map\> values=lookupDataTable("AbsoluteDeductible",null) 
for(Map m in values) {
		println m["Id"]
		println m["AbsoluteDeductible"]
	}
```

 Print Log:
```groovy
4:println() Y
5:println() Absolute Deductible
4:println() N
5:println() Relative Deductible
```
>  Example with condition

```groovy
values=lookupDataTable("IntegrationModelConvertRule",["RuleType":"Remove"]) 
for(Map m in values) {
		println m["RuleType"]
		println m["SrcModel"]
        println m["TargetModel"]
}
```

Print Log：
```groovy
0:println() Remove
11:println() *
12:println() N/A
```

## DSL Script - Advance
### Calcuation
#### allocate

It is used very few. No example here, if do really need it, please reach AD for help.

### Policy Admin

#### uwResult

>  uwResult(String code, Object... params)

​	*uwResult with code & message needed params.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  code   </span>   	*String, Necessary, Rate table name.*

​	<span style="color:#0070c0" class="field_name">  params   </span>   	*Map< String, Object>, Unnecessary, params need transfer to Message.*


> Returns

​	<span style="color:#0070c0" class="field_name">  UnderwritingMessage (code, params)  </span>     *The result of the rate table.*

>  Example

`return uwResult("TenantCode-PA-Validation-B3103", [riskNameNAList,prdDefGender] as Object[])`




#### uwResultWithUwLevel

>  uwResultWithUwLevel(String code,String uwLevelCode, Object... params)

​	*uwResult with code, uwLevelCode & message needed params.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  code   </span>   	*String, Necessary, Rate table name.*

   <span style="color:#0070c0" class="field_name">  uwLevelCode   </span>     	*String, Necessary, uw Level Code.*

​	<span style="color:#0070c0" class="field_name">  params   </span>   	*Map< String, Object>, Unecessary, params need transfer to Message.*


> Returns

​	<span style="color:#0070c0" class="field_name">  UnderwritingMessage(code, params)  </span>     *The result of the rate table.*

>  Example

` return uwResultWithUwLevel("TenantCode-PA-Validation-B3103","U1", [riskNameNAList,prdDefGender] as Object[]) `




#### attachForm

>  attachForm(PolicyElement policyElement, String elementCode)

​	*attach Forms.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  policyElement   </span>   	*String, Necessary, parent element to attach the form.*
​	<span style="color:#0070c0" class="field_name">  elementCode   </span>   	*String, Necessary, element code of the form.*

#### attachElement(From V22.05)

>  attachElement(PolicyElement policyElement, String elementCode)

​	*attach Elements.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  policyElement     </span>     *String, Necessary,  parent element to attach the element.*  
​	<span style="color:#0070c0" class="field_name">  elementCode   </span>   	*String, Necessary, code of the element.*


> Returns


>  Example

```
if(PolicyRisk().RiskName.val == "AutoTest"){
  attachElement(PolicyCoverage().currentModel,"L100301")
}

def ctList =PolicyRisk().PolicyCoverages().ProductElementCode.val
if (("C100417" in ctList)==false ){
  attachElement(PolicyRisk().currentModel,"C100417")
}

```

From Version 23.06, system support to attach casacaded elements once.  There is Clause Form CF001 with child element Coverage C101077, the Coverage C101077 has chile elemnt benefit B00251.
If we want attach all of them once in a event or a rule, the DSL can be set as below,

```
  def cf001=attachElement(PolicyLob().currentModel,"CF001")     
  def c101077=attachElement(cf001,"C101077")    
  attachElement(c101077,"B00251")
```


#### getPlan

>  getPlan(String planCode)

​	*Get Plan Info.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  planCode   </span>   	*String, Necessary, Plan Code.*

> Returns

>  Example

```
def planCode = PolicyRisk().PlanCode.val
planCode=(planCode == null)?PolicyLob().PlanCode.val:planCode
if(planCode in ["","PlanCode",null]){
context["PlanCalMethod"]="1"
}else{
context["PlanCalMethod"]=getPlan(planCode).CalculationMethod.val
if(context["PlanCalMethod"] == "3"){
context["PlanDiscount"] = getPlan(planCode).PremuimRate.val
}else if(context["PlanCalMethod"] == "2"){
context["PlanRatingType"] = getPlan(planCode).RatingType.val//1-Premium;2-Rate
}
}
```
#### getPlanDef(From V22.07)

>  getPlanDef(String planCode)

​	*Get Plan Details.*

> Arguments

​	<span style="color:#0070c0" class="field_name">  planCode   </span>   	*String, Necessary, Plan Code.*

> Returns

>  Example

```
def planA=getPlanDef("TBTI20220001")
def ctList = planA.ProductPlanCoverages()
println(ctList.size())
for (ct in ctList){
  println (ct.ProductElementCode.val)
  println (ct.ProductElementName.val)
  println (ct.IsSelectedByDefault.val)  
  
  def limitList = ct.ProductPlanLimits()
  println(limitList.size())
  for (lmt in limitList){
    println (lmt.ProductElementCode.val)
    println (lmt.LimitDeductibleValueType.val)
    println (lmt.LimitDeductibleUnit.val)  
    println (lmt.LimitDeductibleAmount.val)  
    println (lmt.LimitDeductibleName.val)  
    println (lmt.LimitDeductibleUnit.val)  
    println (lmt.DeductibeType.val)  
    println (lmt.DefaultContent.val)      
  }
  
   def fieldList = ct.ProductPlanCoverageFields()
   println(fieldList.size())
   for (f in fieldList){
      println (f.FieldName.val)
     println (f.DefaultValue.val)   
   }
 
}

```

#### getReferenceObject

>  getReferenceObject()

​	*get product element details.*

> Arguments

> Returns

>  Example

```
PolicyCoverage().getReferenceObject().CalculationFormula.val in ["101"]

```

#### MasterPolicy

>  MasterPolicy()

​	*get Master Policy.*

> Arguments

> Returns

>  Example

```
def pType=Policy().PolicyType.val
if(pType =="4"){
  def mastercts=MasterPolicy().PolicyCoverages().ProductElementCode.val
 for(ct in mastercts){
   println(ct) 
  }
  def masterpt=MasterPolicy().PolicyType.val
  println(masterpt)
}
```

## Call in the Java Program
### Call DSL
#### Simple Call

Only model, field values and groovy native syntax are supported. Custom DSL is not supported.

> expressionDSLEngine.run(expression, context, model)

​	...platform.dsl.engine.expression.ExpressionDSLEngine

> Arguments

​	<span style="color:#0070c0" class="field_name">  expressionDSLEngine    </span>   	*Spring Bean ExpressionDSLEngine.*

​	<span style="color:#0070c0" class="field_name">  expression   </span>   	*String, Not nullable, dsl expression.*

​	<span style="color:#0070c0" class="field_name">  context   </span>   	*Map<String, Object>, nullable, context of runtime.*

​	<span style="color:#0070c0" class="field_name">  model   </span>   	*DomainModel, Not nullable, The model.*

> Returns

​	<span style="color:#0070c0" class="field_name">  Object   </span>     *Execution result of the expression.*

> Example

```java
@Autowired
private ExpressionDSLEngine expressionDSLEngine;

@Test
public void test(){
   String expression = "Policy().Premium.val > 100";
   Policy policy = ….
   Object result = expressionDSLEngine.runDSL(expression, null, policy);
   if (result){
      throw new Exception("Premium is too high!");
   }
}
```


### Custom DSL

please refer to [DSL Script Configuration](#dsl-script-configuration).


## DSL Scenario Examples

#### Vehicle age more than 6 Months then cover A can not applicable
1. set the rule to be PolicyCoverage Level, Object Code is the code of the coverA 
2. logic is

````
def regDate=PolicyRisk().RegistrationDate.val
def effectDate= Policy().EffectiveDate.val
def agegg = regDate.plusMonths(6).minusSeconds(1)

if(agegg<effectDate){
  return "message code"
}
````

#### Set the duration of policy to be 3 Years
The plusYears will auto calculate the leap year and 

````
def effectDate= Policy().EffectiveDate.val
def expDate= Policy().ExpiryDate.val
def endDate=effectDate.plusYears(3).minusSeconds(1)
if(expDate !=endDate){
  return "message code"
}
````

#### Fields are not input or input value is null

If we need to take null as Zero, we can use func-**nullToZero**.

for exapmle, we always use the logic:

````
def si=SumInsured.val
if(si==null){
  si=0
}
````

we can use th below logic:

````
def si=nullToZero(SumInsured.val)
````

```
def aa= nullToZero(AdjustedPremium.val)
println(aa.getClass())  //integer
def bb= nullToZeroDecimal(AdjustedPremium.val)
println(bb.getClass()) //BigDecimal
def bbb = bb.round(2)  //pass
def aaa = aa.round(2)   //failed, integer can not round to digital

=======================
1:val() get AdjustedPremium value: null
1:nullToZero() 0
2:println() class java.lang.Integer
3:val() get AdjustedPremium value: null
3:nullToZero() 0
4:println() class java.math.BigDecimal
```

#### Requirement

The effective date of policy shall come into effect at 0:00 of the second day of insurance and shall not exceed two months.

Related Fields: PolicyEffectiveDate

1.  getDateFromDateTime(now()).plusDyas(1)  

now(): get current time

getDateFromDateTime: start time of the day when the policy it gotten（00:00)

plusDays(1):  plus 1 day

````
if(PolicyEffectiveDate.val<getDateFromDateTime(now()).plusDyas(1)){
   return "message code"
}
````

1. getDateFromDateTime(now()).plusMonths(2) 

plusMonths(2): plus 2 months

````
if(PolicyEffectiveDate.val>getDateFromDateTime(now()).plusMonths(2)){
   return "message code"
}
````

#### Rate table has no result
````
try{
/////TO DO
}catch(Exception e){
if(e.message != null && e.message.startsWith("Can not find result in rate table")){
  println "Can not find result in rate table, return 0"
  return 0
} else {
throw e;
}
}
````

#### Rate table has no result with default value(From V24.01)

```
lookupWithDefault(String rateTableCode, Map<String, Object> params, LocalDateTime versionDate, LocalDateTime releaseDate, Map<String, Object> defaultValue)
lookupWithDefault(String rateTableCode, Map<String, Object> params, Map<String, Object> defaultValue)

```

No default is set,

```
 lookup("0_Test240314", ["Coverage": "C3101-1", "PostCodeRange":"09330545", "Rule":"999","Age":10,"EffDate":effDay, "ExpDate": effDay,"Gender":"F", "Age2":10,"Age3":10])

```

Set default value if no result found,

```
 lookupWithDefault("0_Test240314", ["Coverage": "C3101-1", "PostCodeRange":"09330545", "Rule":"999"],["Decision7":"Test", "Decision6":"Test", "Decision5":"Test", "Decision4":"Test", "Decision3":"Test", "Decision2":"Test", "Decision":"Test", "FatorFreq":99])

```

#### uwResult with parameters


**DSL**：
```
return uwResult("TOKIOMARINE-PA-UW-U1003", ["PolicyHolder",IdNo] as Object[])

```

**Contex  > Message**:
```
BlackList Check Result: The {} IDNo {} is Blacked, can not apply!

```
**It will show as**:
```
BlackList Check Result: The PolicyHolder IDNo {IdNo} is Blacked, can not apply!

```

#### Rating log shows message which contains TemplateAttribute
**This is because the used parameter is not defined before.**

```
def net=BeforeVatPremium.val
def vat=net* rate
```
Here the rate is not defined, then the similar error will occur.

```
Executing calculation step (step name:Risk Delta Premium, step ID:371803844) 
error:Executing formula (formula name:Risk Delta Premium, formula 
ID:371803844, current object:PolicyRisk, current object code:R10005) 
error:No signature of method: java.math.BigDecimal.multiply() is applicable for argument types: 
(...platform.dsl.engine.groovy.TemplateAttribute) values: 
[...platform.dsl.engine.groovy.TemplateAttribute()]

Possible solutions: multiply(java.math.BigDecimal), multiply(java.lang.Character), multiply(java.lang.Double), 
multiply(java.lang.Number), multiply(java.math.BigInteger), 
multiply(java.math.BigDecimal, java.math.MathContext)

```

#### The lookup fuction, get data record from rate tablel, support to input the versions start and end compare with date
Default, the versions' start&end based on the system time(now(),currenttime()).  
If we need to set it based on policy start date, Then we should input the [date] parameter of  lookup function:
````
lookup(rateTableCode, params, **[date]**)
lookupByName(rateTableName, params, **[date]**)

````
Example:
without Date：
````
def flatlist = lookupByName("ThirdPartyBasicPremium",["IsElectricVeh":iselec,"EngineCapacity":param.toLong()])
````
Change it to the one based on policy start date:
````
def effDate=(Policy().EffectiveDate.val).toDate()
def flatlist = lookupByName("ThirdPartyBasicPremium",["IsElectricVeh":iselec,"EngineCapacity":param.toLong()],effDate)

````

And it can work.

#### Update some fields in the same logic one by one in the same level
For example:

Current node is set to PolicyCoverage.
````
def parent=PolicyCoverage().getparent()

parent.GrossPremium.update(GrossPremium.val)
parent.BeforeVatPremium.update(BeforeVatPremium.val)
parent.Vat.update(Vat.val)
parent.DuePremium.update(DuePremium.val)

````

We can use list as:
Then if the fields are needed more or less, we just need to change the fieldList.
````
def fieldList=["GrossPremium","BeforeVatPremium","Vat","DuePremium" ]

def parent=PolicyCoverage().getparent()
def currentLevel=PolicyCoverage()

for (field in  fieldList){
   parent[field].update(currentLevel[field].val)
}

````

#### Lookup the same ratetable more than 1 times under the same condition

````
def productCode=Policy().ProductCode.val
def productVersion=Policy().ProductVersion.val
def minComm=lookup("ProductParameter",["ProductCode":productCode,"ProductVersion":productVersion]).MinimumCommission
def defComm=lookup("ProductParameter",["ProductCode":productCode,"ProductVersion":productVersion]).DefaultCommission
def maxComm=lookup("ProductParameter",["ProductCode":productCode,"ProductVersion":productVersion]).MaximumCommission

````

**Recommanded usage**:

````
def productCode = Policy().ProductCode.val
def productVersion = Policy().ProductVersion.val
def commissions = lookup("ProductParameter",["ProductCode":productCode,"ProductVersion":productVersion])

def minComm = commissions.MinimumCommission
def defComm = commissions.DefaultCommission
def maxComm = commissions.MaximumCommission
````


#### Calculate Insured Age


rude:
````
def age = ((daysBetween(dateOfBirth,Policy().EffectiveDate.val)/365).toLong()

````

details：
````
def dob = PolicyRisk().DateOfBirth.val
def effDate=Policy().EffectiveDate.val

def yearsBetween = getYear(effDate)-getYear(dob)
def monthsBetween = getMonth(effDate)-getMonth(dob)
def days0=dob.toString().split('T')[0].split('-')[2].toLong()
def days1=effDate.toString().split('T')[0].split('-')[2].toLong()
def daysBetween = days1-days0

def age=yearsBetween
if(monthsBetween < 0){
   age =yearsBetween-1
}else if(monthsBetween==0){
  if(daysBetween <0){
    age =yearsBetween-1
  }
}else{
  age=yearsBetween 
}

return age
````

#### totalDaysOfYear()

```
1: def POIDay = daysBetweenDateWithoutTime(EffectiveDate.val,ExpiryDate.val)
2: def ActualDaysinCalendar = totalDaysOfYear(EffectiveDate.val)
3: def Rate=POIDay/ActualDaysinCalendar
4: return Rate
```

#### Get the total days of this year and if 366 then it is leap year


DSL：
```
def actualDaysinCalendar = totalDaysOfYear(EffectiveDate.val)
println(actualDaysinCalendar)
```

Output log:
```
1:date days:() 2019-07-22T00:00  366
2:println() 366
```

#### If policy start date is 18-Mar-2021, then master policy number will be Plan-18032021

DSL：
```
def dt = EffectiveDate.val

def dd = dt.getDayOfMonth()
def mm = dt.getMonthValue()
def yy = dt.getYear()
mm = mm > 10 ? mm : "0"+mm
dd = dd > 10 ? dd : "0"+dd
def masterPolicyNo= "Plan-"+ dd +mm +yy
println(masterPolicyNo)

```

Output log:
```
1:val() get EffectiveDate value: 2019-04-22T00:00
9:println() Plan-22042019
```



#### Validate platform owned field length

  Some platform owned fields do not limit the length.


rude DSL：
```
5: def pva=ProductVersion.val
6: println pva.length()
```

Output log:
```
5:val() get ProductVersion value: 1.0
6:println() 3
```


delicate DSL

create data table for the validation fields


| Model                     | Field           | FieldLength | LimitType |
| ------------------------- | --------------- | ----------- | --------- |
| Policy                    | ProductVersion  | 3           | EQ        |
| Policy                    | ChannelType     | 6           | EQ        |
| Policy                    | BusinessType    | 3           | EQ        |
| PolicyCustomer            | MemberId        | 8           | EQ        |
| PolicyCustomer            | CustomerNumber  | 8           | EQ        |
| PolicyRisk                | InsuredRelation | 2           | EQ        |
| PolicyRisk                | InsuredGender   | 1           | EQ        |
| PolicyRisk                | InsuredAddress  | 120         | MAX       |
| PolicyRisk                | SumInsured      | 9           | MAX       |
| PolicyRisk                | InsuredEmail    | 48          | MAX       |
| PolicyRisk                | InsuredIdNo     | 12          | EQ        |
| PolicyRisk                | InsuredType     | 1           | EQ        |
| PolicyRisk                | IdNo            | 12          | EQ        |
| PolicyRisk                | TaxCode         | 6           | EQ        |
| PolicyDeliveryAddressList | Address         | 120         | MAX       |
| PolicyCoverage            | SumInsured      | 9           | MAX       |
| PolicyBenefit             | SumInsured      | 9           | MAX       |




DSL:


```
8: def fieldList = lookupDataTable("Flied_Length_Validation",["Model":"Policy"])
9: for ( f in fieldList ){
10:    def ffieldName = f["Field"]
11:    println ffieldName
12:    def fvalue=Policy()[ffieldName].val
13:    println fvalue
14:    def flimit = f["FieldLength"]
15:    println flimit
16:   if(fvalue != null && fvalue != ""){
17:     println fvalue.length()
18:     if(fvalue.length() != flimit ){
19:      println "eeeeeeeeeeeee~"
20:   }
21:   }22:   
23: }
```


Output Log:
```
11:println() ProductVersion
12:val() get ProductVersion value: 1.0
13:println() 1.0
15:println() 3
17:println() 3
11:println() ChannelType
12:val() get ChannelType value: ABC
13:println() ABC
15:println() 6
17:println() 3
19:println() eeeeeeeeeeeee~
11:println() BusinessType
12:val() get BusinessType value: null
13:println() null
15:println() 3
```

