Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

F.ex. you may want to have a custom field which displays the average of the values in 2 other custom fields, but only include the values that are larger than 1000. This can be done with the following script:

n

...

=

...

0
sum

...

=

...

0
if

...

this.custom200

...

>

...

1000
 

...

n++
 

...

sum

...

+=

...

this.custom200
if

...

this.custom201

...

>

...

1000
 

...

n++
 

...

sum

...

+=

...

this.custom201
if

...

n

...

==

...

0
 

...

return

...

""
return

...

sum

...

/

...

n

Example 1 - average of custom fields with values > 1000

The script functionality is only available if it has been enabled by Ventu. Currently only tasks, companies, users, invoices, persons, projects, quotations and equipment provide script custom fields.

...

We recommend that you use exactly one SPACE in these situations, however these are just recommendations:

  • on either side of = or += etc in assignments, e.g.:  x += 4 

  • after a keyword, unless it is the last thing on a line, e.g.:  for i in [4, 5, 6]

  • on either side of operators in expressions, e.g. :  res = x + 4 - (4 * y + 2)

  • after the comma in arrays and dicts and argument lists, and after the : in dicts , but not after left brackets or before right

    brackets  

    brackets  

Obviously there are places where it is necessary to have at least 1 SPACE to prevent ambiguity.

...

Blocks are defined by being indented by 2 SPACEs. Other languages use curly brackets { } to define blocks. A block ends at the next line with less indentation, or at the end of the script:

if

...

this.custom200

...

>

...

1000
 

...

n++
if

...

this.custom201

...

>

...

1000

...

if

...

this.custom202

...

>

...

1000

...

n++

...

else

...

n--

Example 2 - indentation

Functions

Functions are defined by the keyword def, followed by the function name, followed by the arguments in brackets; the function body must be indented. A function may return a value, using the keyword return.

def

...

positive_sum(a,b,c)
 

...

sum

...

=

...

0
 

...

if

...

a

...

>

...

0
 

...

 

...

sum

...

+=

...

a
 

...

if

...

b

...

>

...

0
 

...

 

...

sum

...

+=

...

b
 

...

if

...

c

...

>

...

0
 

...

 

...

sum

...

+=

...

c
 

...

return

...

sum

Example 3 - simple function

Names

Variables and functions must have names that begin with A-Z, a-z or _ (underscore), and may only include characters A-Z, a-z, 0-9 and _ (underscore).

...

Also,  // or # after an expression also indicates that the rest of the line is a comment.

//

...

example

...

of

...

comments
a

...

=

...

1  //

...

this

...

is

...

a

...

comment
b

...

=

...

2

...

#

...

this

...

is

...

also

...

a

...

comment

Example 4 - comments 

Variable types

The following types are supported:

Type

Explanation

Examples

string

Text is always in UTF-8, use double quotes "  "

headline = "Microbizz script"

number

The decimal point is . (full stop)

price = 12.34

array

This is a comma seperated list of values, types may be mixed.

Access a non-existing key will return an error; use array.append(value) to add elements to the array. 

myarray = [1, 2, 3,"Some text", [4, 5, 6]]

sometext = myarray[4]

dict

A list of key:value pairs, the syntax is much like the Javascript object syntax, or JSON.

Use double  quotes " for key names and textual values.

Keys are always strings; if you use a number as key it will be converted to a string.

Accessing a non-existing key will return an empty string.

peter = {name: "Peter", "age": 15, height: 160}

age = peter.age

age = peter["age"]

object

title = this.title

today = Date.date()

data

Expressions

Expression syntax is pretty standard. The operators are described below. 

Variables are assigned using =. Variables can be updated using += or -= etc.

Operators

* / %  ^

Arithmetic; notice that it is valid to divide by 0

+ -

Arithmetic, but + also works for strings and arrays;

a+b means string concatenation if either a or b is a string

||  &&  |  & ^

Boolean and bitwise

==  !=  <  <=  >=  >  ===  !==

Comparisons, the result is 0 or 1

.

Object access

(bool) (number) (array) (string) (int)

Cast, convert a value to another type of value

!

Logical negation

= += -= *= /= &= |= ^=

Assignment

Controls structures

The if-elseif-else and while control structures are supported. while supports break and continue.

res

...

=

...

0
if

...

this.custom200

...

<

...

1000
 

...

res

...

=

...

this.custom200
elseif

...

this.custom201

...

<

...

1000
 

...

res

...

=

...

this.custom201
else
 

...

res

...

=

...

1

while

...

res

...

>

...

2
 

...

res

...

/=

...

2

Example 5 - control structures

Loops can be made using the for keyword.  This iterates through the values in some type of iterable value, which can either be a the result of the range() function, or a string or array or dict. for loops support continue and break.

for

...

i

...

in

...

range(1,

...

100)
 

...

do_something(i)
for

...

letter

...

in

...

"ABCDEFG"
 

...

do_something(letter)
for

...

prime

...

in

...

[1,

...

2,

...

3,

...

5,

...

7,

...

11,

...

13]
 

...

do_something(prime)
dictionary

...

=

...

{a:

...

1,

...

b:

...

2,

...

c:

...

3}
for

...

key

...

in

...

dictionary
 

...

do_something(key,

...

dictionary[key])

Example 6 - for loops

Variable scope

Variables that are created outside a function are global. To use a global variable from inside a function, you need to use the global keyword to specify the variable:

myname

...

=

...

"Microbizz"
mytitle

...

=

...

"Mr."
def

...

getmyname()
 

...

global

...

myname,

...

mytitle
 

...

return

...

"My

...

name

...

is

...

"+myname

Example 7 - globalglobal variables

Variables that are created inside a function only exist until the program leaves the function. You cannot have variables that are local to a block.

...

When you pass variables as arguments to a function, scalar/primitive variables (strings and numbers) are passed by value, whereas arrays/dicts/objects are passed by reference. This means that the function may modify arrays/dicts/objects that are passed, but not strings and numbers.

myname

...

= {name:"Microbizz"}
mytitle

...

=

...

"Mr."
changename(myname,

...

mytitle)
//

...

myname.name

...

may

...

now

...

have

...

changed,

...

but

...

mytitle

...

is

...

the

...

same

Example 8 - pass by reference

Escaping

Strings are in UTF-8, unicode character codes may be inserted using \uXXXX.

...

Notice that the new syntax is still very experimental, you should probably use the old syntax.

Microbizz object

Documentation

List of connected objects

Customer

Micropedia - the "customer" object

this.person

this.user

EdiInvoice

Micropedia - the "edi" object

this.todo

this.user

this.customer

Equipment

Micropedia - the "tool" object

this.placeofhome

this.user

Invoice

Micropedia - the "invoice" object

this.user

this.customer

InvoiceLine

Micropedia - the "invoiceline" object

this.todo

this.customer

Person

Micropedia - the "person" object

Project

Micropedia - the "project" object

this.user

this.customer

Registration

Micropedia - the "registrationentry" object

this.todo

this.user

this.customer

Task

Micropedia - the "todo" API object

this.customer

this.user

this.project (same for both new and old projects)

User

Micropedia - the "user" object

Product

Micropedia - the "product" object

Planning

Micropedia - the "prodplanentry" object

Quotation

Micropedia - the "salescontract" object

this.customer

this.user

Appointment

Micropedia - the "event" object

this.user

this.customer

Script return value

When the script is run to generate the value for a custom field, the return value is specified by the keyword return outside of a function, this will also stop execution of the script; the return value is what is displayed in Microbizz.

area

...

=

...

"nowhere"
if

...

this.postcode

...

>=

...

1000

...

&&

...

this.postcode

...

<=

...

2999
 

...

area

...

=

...

"capital"
elseif

...

this.postcode

...

<

...

9999
 

...

area

...

=

...

"countryside"
return

...

area

Example 9 - return value

The return value may either be text, as in the example above, or it may be HTML generated by the HTML object.

...

Microbizz logs various script related things in the System log.

Microbizz.Log("The

...

script

...

was

...

started")
//

...

first

...

argument

...

should

...

be

...

a

...

string,

...

second

...

argument

...

is

...

optional

...

and

...

may

...

be

...

an

...

array

...

or

...

dict

...

or

...

string

...

or

...

number
Microbizz.Log("Some

...

data",

...

[123,"ABC"])

Example 10 - logging

Sandbox

You may test the plugins/scripts by running them in a simple "sandbox", which prevent certain functions for doing anything; there is a Run in sandbox checkbox in the script editor for this.

...

F.ex. there may be complicated pricing calculations that depend on the date and postcode of a task. This might be developed by Ventu and could then become available as a new script object providing access to the calculations. In the unrealistic example below, a new Tax object provides two new functions:

taxrule

...

=

...

Tax.getRule(this.zip,

...

this.createdate)
return

...

Tax.calculate(this.price,

...

taxrule)

Example 11 - unrealistic extension

Real world examples

Copy a custom field from the company to the task whenever a task is saved

This requires that the custom fields are marked as "show in app". We assume that the company custom field has id=321 and the task custom field has id=123.

cus

...

=

...

this.customer
if

...

cus.indb()
 

...

this.sv("custom123",

...

cus.custom321)
 

...

this.save()

Example 12 - copy custom field

Copy a custom field from a project task to all subtasks whenever the project task is saved

This requires that the custom field is marked as "show in app". We assume that the custom field has id=321.

if

...

this.tasktype

...

==

...

5

...

&&

...

this.parenttodo

...

==

...

0

...

subtodos

...

=

...

this.subtodos

...

if

...

isarray(subtodos)

...

for

...

id

...

in

...

subtodos

...

todo

...

=

...

Microbizz.GetTodoByID(id)

...

todo.sv("custom322",

...

this.custom321)

...

todo.save()

Example 13 - copy custom field

Known problems

1)

If an array holds a dict as an element, then accessing an element in the dict using eg.

...