Other useful information
- Henrik Bjerregaard
This page contains information which may be useful when implementing a full app, or when using the API to synchronize data with Microbizz.
See also /wiki/spaces/DEV/pages/29033638
Synchronization
You will often want to maintain up-to-date list of the most important objects, like customers, tasks, persons, equipments etc. That way you can lookup details of eg. a customer instantly, without having to communicate with the Microbizz server. This is usually called 'synchronization', and requires that you call eg. GetCustomersByLastChange regularly, eg. every 10 minutes or 1/2 hour or whatever you find reasonable.
API calls whose name end in …ByLastChange require that you specify the date+time of the last time you call the API call. The API call then returns all the objects that have changed since then.
The API calls may return a 'resumekey' value. This indicates that the call didn't return all the objects that have changed. You should then call the same API call again, with the same date+time and also specify the resumekey value that you just received. Repeat this until the API call no longer returns a resumekey value. The API call will return date+time of when Microbizz received the request. This should be used as date+time the next time you synchronize.
F.ex.:
getcustomersbylastchange_date = '1970-01-01' getcustomersbylastchange_time = '00:00:00' function synccustomers() resumekey = false do data = GetCustomersByLastChange(getcustomersbylastchange_date, getcustomersbylastchange_time, resumekey) if (data.resumekey) resumekey = data.resumekey while (data.resumekey) // remember date+time for next time getcustomersbylastchange_date = data.date getcustomersbylastchange_time = data.time endfunction
Complex types that are objects
The following complex types are objects that should preferably be available when an app is offline. Other complex types (like budgetarea, eventtype, mainpagebox, persontype and many more) are considered part of the setup of Microbizz and need only be read during synchronization. Typically the offline objects are those that the app may send to Microbizz, whereas the remaining objects are only read by the app.
call, customer, directorderline, event, depotorderline, document, feature, invoiceline, message, tmessage, mbmessage, note, partuse, person, prodplanentry, product, registrationentry, salescontact, salescontractline, todo, todoitem, tool, thread, unit, user
Which objects are sent to the app (the "Limit objects..." setting)
Notice that there may be a difference between what is sent to the app, and what the user can access in the app. Just because a task is sent to the app doesn't necessarily mean that the user can see or edit the task. F.ex. if the user doesn't have access to a task, then the app may still receive the task so that it can display the name of the task in certain situations, but the user will not be able to access the task.
There is a setting in Microbizz called “Limit which objects are available in the app” which reduces the number of objects sent to the app. The behavious depends on the type of object.
For the new app this settings is assumed to be ON when reading tasks.
Without the setting
Tasks
All tasks except those that were closed more than 2 weeks ago.
Customers
All customers that aren't deactivated.
Persons
All persons.
Equipment
All equipment that aren't deactivated.
With the setting
For persons and customers this is the same as without the setting.
Tasks
Tasks that fulfill any of these criteria:
belongs to a pool which belongs to one of the user's teams
user is responsible or is an additional user or is in a “user” custom field
belongs to one of the user's teams
- is planned to the user within +/- one month from now
but not if the task fulfills any of these criteria:
was last changed more than a year ago
“next action” is more than a month away (in the past or future)
Equipment
Old app
The old app reads all equipment that isn't deactivated.
New app
The new app only reads equipment that isn't deactivated and that do not have a “place of home”.
When accessing the equipment list of a task or customer, the new app reads all equipment that are relevant for that task/customer.
Notice
The app may specify that closed objects (tasks/customers/etc) should be ignored, in which case no closed task or deactivated customer or inactive user etc. is included.
Discussion of synchronization
The initial configuration and subsequent synchronization requires reading a lot of data from the Microbizz server. On this page we try to describe an efficient way of doing this, and describe which data to read, which API calls to call.
Often there are multiple ways of reading the data, f.ex. you may either
A) read all hour registrations using GetRegistrationsByLastChange during the synchronization, or
B) read the registrations using GetRegistrationByDate whenever you need to access the registrations.
A) means that all registrations are available to the app all the time, but it slows down synchronization. B) means faster synchronization, but it slows down access to the tasks that need to display summary of registrations.
Generel details about synchronization
Order
It is often a good idea to read certain data before other certain other data, f.ex. it might be a good idea to call GetCustomFields before GetTodosByLastChange, GetCustomersByLastChange etc. as GetCustomFields describes what fields will be available in objects returned by the other calls.
The current app (the one from 2015-2019) uses this order (more or less):
GetMobileAppSettings
GetCustomFields
GetTodosByLastChange
GetCustomersByLastChange
GetPersonsByLastChange
GetToolsByLastChange
the other Get…ByLastChange
GetMyTools
GetPendingQuestionRequests
the rest of the calls (see below).
Other data
Besides the various Get…ByLastChange calls it will usually also be desirable to read other types of data when synchronizing, f.ex. the list of task states and equipment states (GetTodoStates, GetToolStates). The current app also calls these API calls during synchronization:
GetCurrentUserID
GetCustomFields
GetMyPendingCalls
GetMyTools
GetPendingQuestionRequests
GetCustomAppLinks
GetTodoTemplates
GetPersonalDocuments
GetToolTypes
GetWorkareas
GetGPSConfig
GetCheckIn
GetTodoStates
GetToolStates
GetProductStates
GetCheckpoints
GetInternalRegistrations
GetPastRegistrations
GetCustomerTypes
GetEventTypes
GetStocks
GetTeams
GetToolServiceProtocols
GetPlannedTodos
GISGetCustomBaselayers
GetQuestionForms
GetPlanDestinations
GetIcons
GetColumnGroups
GetProductUnits
Perhaps these should be read slightly less often than Get…ByLastChange.
The order is not terribly important.
Performance
A full synchronization currently involves more than 50 API calls. Luckily many calls may be combined into a single request, which will speed up things. The Get…ByLastChange calls cannot be combined into a single request.
Initial configuration
The initial configuration (when the user has just entered a XXXX-XXX configuration code) should be slightly different from the normal, regular synchronization. During the initial configuration the Get…ByLastChange calls that support the ignoreclosed
parameter should have that parameter set to 1.
ignoreclosed
means that Microbizz will skip some objects which it knows are of no use to the app, but which would otherwise be included because they fulfill the criteria for being included. F.ex. a deleted product will be skipped if ignoreclosed
is set, as the app doesn't need to know about deleted products. However, the normal synchronization should detect if an existing product has just been deleted so that it can be discarded from the app database, and therefore ignoreclosed
should not be set during the normal synchronization.
GetMobileAppSettings should be the first call.
Threads and messages
When reading threads and messages you can either
A) read all threads and messages during the synchronization, or
B) only read the threads and the read the messages whenever the user opens a thread.
Since there can be many thousands of thread, the second solution B) is preferred, if the app allows it. To use B) simply add the parameter exclmessages
= 1 to the GetThreadsByLastChange API call. That way you will get only the threads, not the messages for each thread.
Normal synchronization
GetMobileAppSettings should be the first call.
The order of API calls is probably not important, as long as all API calls are executed.
Registrations
Initial config.
During the initiel config. the app should read the last 60 registrations, using GetRegistrationByDate.
Normal sync.
Do nothing.
Other times
When the app wants to display the regs for a task etc it should read the regs. using GetRegistrations.
When displaying list of daily worksheet for a week, the app should read all registrations for that week, using GetRegistrationByDate. Similarly, when displaying the list of previous registrations, the list of 60 days should be reread the same way.
Threads/Notes
Initial config.
GetThreadsByLastChange should be called with the parameter onlysubscriber
set to 1 and ignoreclosed
set to 1.
Until 2019-11-19 we said that the parameter exclmessages
should be set.
Normal sync.
Like the initial config.
Other times
When the app needs to display the threads for an object, it should read them using GetThreads. When the app needs to display the notes in a thread, it should read them using GetThreadByID and set exclmessages
to 0.
Messages
Appointments / planning
Initial config.
Read appointments and planning for the previous month and the next month (ie. +/- 30 days) using GetEventsByUserAndDate and GetProductionByUserAndDate.
Normal sync
The app should try to keep the calendar for the next 30 days up to date, by calling GetEventsByUserAndDate and GetProductionByUserAndDate for the date 30 days ahead. This should be done just once a day.
Other times
Use GetEventsByUserAndDate and GetProductionByUserAndDate when displaying the calendar. If a date has been read within the last minute or so then don't read it again.
Tasks
Initial config.
Call GetTodosByLastChange (starting at 1970-01-01 as always) and specify the parameter limitnumobjects
set to 1, and ignoreclosed
set to 1.
When the Microbizz has returned all the tasks, the startdate should be reset to 1970 and the normal sync should then the started. This way the app will first read the most important tasks, and then read all the tasks in the normal sync.
Normal sync
Just use GetTodosByLastChange, don't specify the parameter limitnumobjects
, but specify the parameter ignoreclosed
set to 1.
Companies/customers
Just use GetCustomersByLastChange in all situations, specify the parameter ignoreclosed
set to 1.
Equipment
GetMobileAppSettings may now return a new 'function' named LimitNumObjects. If this isn't set then the app should just call GetToolsByLastChange (with ignoreclosed
=1) during the initial config., and also call GetToolsByLastChange (with ignoreclosed
=0) during the normal sync.
If LimitNumObjects is set, then the app should do as described below.
Initial config.
This only applies if LimitNumObjects is set.
Call GetToolsByLastChange with the parameter ignoreclosed
set to 1 and the parameter placeofhome
set to 2.
GetToolsByLastChange will also return a list of companies for which there may be tools that are also important. The app should read those tools using GetToolsByField, see “Other times” below.
INTERNAL MEMO: Microbizz should detect when the planning for a user is changed and list the affected customers so that they can be returned to the app whenever GetToolsByLastChange is called.
Normal sync
This only applies if LimitNumObjects is set.
At the very least call GetToolsByLastChange with the parameter ignoreclosed
set to 1 and the parameter placeofhome
set to 2.
GetToolsByLastChange will also return a list of companies for which there may be tools that are also important. The app should read those tools using GetToolsByField, see “Other times” below.
Other times
This only applies if LimitNumObjects is set.
When the user opens the equipment list for a company/customer or for a task/todo then it should read the list of tools for that company or task. If the list of tools has been read within the last minute or so then it is not necessary to read the list again.
For companies use GetToolsByField and specify the parameters field
= custref
and value
= the ID of the company. Possibly specify the knowntools
parameter, to reduce the number of tools that need to be read.
For tasks use GetToolsByTodoID. Possibly specify the knowntools
parameter, to reduce the number of tools that need to be read.
Products
The initial config. should only the those products that the user is likely to be using the most.
Initial config.
Use GetProductsByLastChange with the parameter onlyfavorites
set to 1 and ignoreclosed
set to 1.
Normal sync
Use GetProductsByLastChange without the parameter onlyfavorites
and without the parameter ignoreclosed
.
Product use
Initial config.
The initial config. should not read any product use.
Normal sync
The normal sync. should not read any product use.
Other times
Product use for tasks/todos and tools/equipments should be read when the details about the task or tool is displayed. To read product use for a task, use GetProductUseByTodoID. To read product use for a tool, use GetProductUseByToolID.
Deletion of data
Deleting data in Microbizz may pose a problem for the app. If an object (eg. an equipment) disappears from the Microbizz database, then the object will no longer appear when Microbizz checks to see which objects have changed since last, f.ex. when the apps calls GetToolsByLastChange, because the object simply doesn't exist anymore.
For many object types Microbizz will not delete the object from the database, but will instead set a field to indicate that the object is to be considered deleted. This field is typically called isdeleted
, and tells the rest of Microbizz that the object should be ignored, so it will not appear in search results etc. However, the object still exists in the database, and so API calls like GetToolsByLastChange will be able to detect that the object has changed, and will be able to send the object to the app, now with the isdeleted
field set.
Notice that the isdeleted
field is sometimes used to indicate that the object should not be available in the app for other reasons, f.ex. if a task was closed more than a few das ago.
Also notice that there are "naughty" ways of deleting data in Microbizz, which are only used in special circumstances, and which break all rules.
object type | handling | notes |
---|---|---|
todo (task) | The isdeleted field indicates if the task should be invisible within the app, not if the task exists. | Tasks are usually only ever deleted when their company is also deleted; large amounts of other data is deleted at the same time; this is an extreme situation. If a task is deleted, the app will not discover it. |
customer (company) | The isdeleted field indicates that the company should be invisible within the app. | Deleting a company means that the company's tasks are deleted, along with lots of other data, but the company continues to exist in Microbizz, but with all fields/data cleared; this is an extreme situation. The app will be notified at the next GetCustomersByLastChange. |
tool (equipment) | The isdeleted field indicates that the equipment should be invisible within the app. | The equipment continues to exist in Microbizz, but lots of other data is deleted or cleared. The app will be notified at the next GetToolsByLastChange. |
person | The isdeleted field indicates that the person should be invisible within the app. | The person continues to exist in Microbizz, but lots of other data is deleted or cleared. The app will be notified at the next GetPersonsByLastChange. |
todoitem (product use) | The isdeleted field indicates that the product use should be invisible within the app. | The product use continues to exist in Microbizz. The app will be notified at the next GetProductUseByLastChange. |
product | The isdeleted field indicates that the product should be invisible within the app. | The product continues to exist in Microbizz. The app will be notified at the next GetProductsByLastChange. |
thread | The isdeleted field indicates that the thread should be invisible within the app. | The thread continues to exist in Microbizz. The app will be notified at the next GetThreadsByLastChange. |
Mainpages
Main pages consist of a number of “boxes”, each box displays some kind of info from the object.
The definition of the main pages are read using GetMainPages. There is one mainpage object for each object type (task, customer, person or equipment); the mainpage object includes a field named boxes which holds a list of mainpagebox objects which describe what to display.
Types of boxes
There are different types of boxes for each object type, and some types of boxes may appear in several object types.
The type of a mainpagebox is specified in the field box
. If a box has a type that is unknown to the app then the box should not be displayed.
type | explanation |
---|---|
columngroup<XX> | the type starts with columngroup , also the field iscolumngroup is set |
checklist | special box for task checklists, see below |
reminders | special box for reminders, see below |
procedures | special box for procedures, see below |
subcustomers | special box for subcustomers, see below |
toolservice | special box for equipment service, see below |
tooltake | special box for taking equipment, see below |
address | special box for listing addresses, see below |
persons | special box for listing persons, see below |
users | special box for listing users, see below |
description | special box for descriptions, see below |
companies | special box for persons, see below |
Any object type - Column group
If the field iscolumngroup
is set set to 1 then the box should simply display a column group. The column group is specified by the field columngroupid
. See GetColumnGroups for details about how to display a column group.
The box title should be the title of the column group.
Any object type - Address
If the box
field is set to address
then the box should display the addresses that are relevant for the object. The relevant addresses depend on the object type, see below. Some addresses have a latitude+longitude; these should be shown with a distance from the current location. If latitude or longitude is 0 then that means “no location”. Clicking on an address should provide driving direction or show a map or similar.
object type | address | fields | lat+lon field |
---|---|---|---|
todo | Delivery | address ,address2 ,zip ,city ,country | latitude ,longitude |
customer | Address | address ,address2 ,zip ,city ,country | latitude ,longitude |
customer | Invoice | invoiceaddress ,invoiceaddres2 ,invoicezip ,invoicecity ,invoicecountry | |
person | Address | address ,address2 ,zip ,city ,country |
The name of each address should be the text in the “address” column in the table above.
If the object has one or more custom field of the type address then these should be included in the box. Notice that the custom field uses the field names adress
,adress2
,zip
,city
,country
,lat
,lon
. For custom fields the name of the address should be the title of the custom field.
The todo object has an addresses
field which contains a list of other addresses (address objects) which may have relevance for the task. These should also be displayed in the box. For these fields the name of the address should be the type
field on the address.
Any object type - persons
If the box
field is set to persons
then the box should display the persons that are relevant for the object.
Currently this should be supported for these object types:
object type | person fields | other persons |
---|---|---|
customer | see GetRelationsByLastChange | |
tool | personid | |
todo | personid |
If there are no persons for an object then the box should not be shown.
The persons should be listed with name and optional title, and with buttons for phoning/emailing the person.
The second line is the “role”, not to be confused with the title of the person. For the field personid
the role is “Contact person”. For persons from GetRelationsByLastChange the role is the title
field from the relation. If the person is also the person specified in the theirreference
field on the company then the person also has the role of “Contact person” and both roles should be displayed.
Any object type - users
If the box
field is set to users
then the box should display the users that are relevant for the object.
Currently this should be supported for these object types:
object type | users fields | other users |
---|---|---|
customer | ourreference , sellerid | any customfield of type 9 (user) |
tool | userid | any customfield of type 9 (user) |
todo | userid , additionaluserids | any customfield of type 9 (user) |
If there are no users for an object then the box should not be shown.
The users should be listed with name and “role”, and with buttons for phoning/emailing the user.
The role is determined by the field that held the user ID. For custom fields the role is the name of the custom field; for fields named userid
or ourreference
the role is “Responsible”, for sellerid
is “Seller”, for additionaluserids
the role is “Additional user”.
Task - Checklist
If the box
field is set to checklist
then the box should display the checkpoints for the task
Each task has a list of checkpoints which may be selected/deselected; the checkpoints are taken from the global list of checkpoints which may be read using GetCheckpoints, each task may include a subset of the checkpoints. The subset is specified in the field checkpoints
on the todo object.
This box should display the relevant checkpoints. If the user is checked in on the task then it should be possible to select/deselect each checkpoint. If the user isn't checked in on the task then it should not be possible to select/deselect. When the user checks out from the task, the list of selected checkpoints should be sent Microbizz.
If there are no checkpoints for a task then the box should not be shown.
The box title should be “Checklist”.
Task - Reminders
If the box
field is set to reminders
then the box should display a list of reminders that are relevant for the task.
Reminders are read using GetMyStodos (an “stodo” is a reminder). This will return a list of all pending reminders for the user, each is an stodo object. Notice that reminders may be far into the future - these should probably not be displayed.
To find the stodos that refer to a specific task, look for stodos with modcode
set to 'todo' and objectid
set to the ID of the task.
The fields description
and date
and time
should be displayed. The field assignedbyuserid
specifies the ID of the user who set up the reminder.
To postpone a reminder by a number of minutes, use StodoAccept and specify the number of minutes in postpone
. To complete/accept a reminder, use StodoAccept and don't specify postpone
.
The box title should be “Reminders”.
Task - Description
If the box
field is set to description
then the box should display the description
field from the task. This may be a long text, so it requires special consideration.
The box title should be “Description”.
Task - Procedures
If the box
field is set to procedures
then the box should display the “procedures” for the company that the task belongs to.
Procedures are typically used to inform the user what to do when a certain situation occurs for a given company. The procedures are read using GetProceduresByLastChange which will return a list of procedure objects.
Each procedure object has the fields modcode
and sysref
which determines which object/company it belongs to. The procedures belonging to a company are those where modcode
is 'customers' and sysref
is the ID of a company.
The box should display the title
fields from the relevant procedures, and when the user presses on a title the full text
field should be displayed.
If there are no procedures for the company then the box should not be shown.
The box title should be “Procedures”.
Company - Procedures
This is just like Tasks - Procedures except it displays procedures for the company itself, instead of for the company that the task belongs to.
This should only be displayed if the function “CustomersProcedure” is enabled (see GetMobileAppSettings).
Company - Subcustomers
If the box
field is set to subcustomers
then the box should display a list of subcustomers.
The subcustomers to the company A are those where the field parentcust
holds the ID of company A.
The box title should be “Subcustomers”.
Company - Reminders
If the box
field is set to reminders
then the box should display a list of reminders and calls that are relevant for the customer.
The reminders (stodos) are read, confirmed, postponed and displayed like in the box Task - Reminders (see above), except you should look for stodos where modcode
is set to 'customers' and objectid
is set to the ID of the company.
The calls are read using GetMyPendingCalls, which will return a list of call objects. Look for calls where the field customerid
is set to the ID of the company. Display the fields persontext
and calltime
.
The box title should be “Reminders”.
Person - Companies
If the box
field is set to companies
then the box should display details about the companies that the person belongs to. The companies can be read using the API call GetRelationsByPersonID.
Tools - Service
If the box
field is set to toolservice
then the box should display details about the service period (from the equipment type) as well as the fields lastservice
and nextservice
(from the equipment). It should also display a button named “Start service”.
The equipment type details can be read using GetToolTypes; it returns a list of tooltype objects. The equipment has a field groupid
which specifies the ID of the equipment type for the equipment; see the fields periodtype
and period
.
The “Start service” button should start service on the equipment; see Service for details.
Tools - Take
If the box
field is set to tooltake
then the box should display information about whether the equipment is current taken, and if so, by who. The box should also display a button to take the equipment (if not already taken by the current user) or to set down the equipment (if currently taken by the current user).
The tool object includes a field carrier_userid
which holds the ID of the user who has taken the equipment, or 0 if the equipment is not taken by anyone.
An equipment can be taken by using the API call PickupTool, and it can be set down using the API call SetDownTool.
Details of when the user took the equipment is not currently available in the API; the app should keep track of this itself.
The box should only be available if the function “ToolTake” is set.