<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.isikhnas.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jillhinchliffe</id>
	<title>Wiki Sumber Informasi iSIKHNAS - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.isikhnas.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jillhinchliffe"/>
	<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/w/Special:Contributions/Jillhinchliffe"/>
	<updated>2026-09-17T21:18:39Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.16</generator>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=Mapping&amp;diff=39431</id>
		<title>Mapping</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=Mapping&amp;diff=39431"/>
		<updated>2018-06-22T11:27:01Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: /* Viewing maps */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Mapping=&lt;br /&gt;
The mapping system allows administrators to define new map-based reports rapidly through the interface, and for them to be viewed on-line.&lt;br /&gt;
&lt;br /&gt;
==Defining a new map==&lt;br /&gt;
Maps are defined in the same way as other reports, using the Administration | Reports menu. There are two key differences compared to other reports: requirements for the SQL data definition, and style information (Mapfile code)&lt;br /&gt;
&lt;br /&gt;
===SQL===&lt;br /&gt;
The SQL is similar to all other reports, and should be a single SELECT query. However, there are several particular requirements&lt;br /&gt;
&lt;br /&gt;
====Required fields====&lt;br /&gt;
Every query must return two required fields:&lt;br /&gt;
* '''gid''' - this is a 'geographic ID' and is a unique integer for each spatial unit returned. Often, this can just be the id from the locations table, but if there can be multiple reports per location, you need to choose another unique ID value. It doesn't matter which. If nothing else is available, you can also use the row number window function:&lt;br /&gt;
 select row_number() over () as gid, &lt;br /&gt;
* '''the_geom''': this is the spatial data and must be included in every report. It should always come from the projected version of the locations table spatial data. That is:&lt;br /&gt;
** For polygon data (administrative units) this should be geom_proj (e.g. select geom_proj as the_geom, )&lt;br /&gt;
** For point data (village locations etc) this should be centroid_proj (e.g. select centroid_proj as the_geom, )&lt;br /&gt;
Don't use the standard geom and centroid columns, or the data will not be in the right projection and won't appear on the map.&lt;br /&gt;
&lt;br /&gt;
===Field names===&lt;br /&gt;
Any fields generated in the query will be available to the user with a map query (where they click on a feature, and further information pops up). So that this feature works nicely, you should include all the data that a user might want to see, and name each field with a user-friendly name. For example&lt;br /&gt;
 SELECT&lt;br /&gt;
   sum(total) as &amp;quot;Julah hewan&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Example===&lt;br /&gt;
An example of a simple query to display infrastructure:&lt;br /&gt;
 SELECT&lt;br /&gt;
   i.id as gid,&lt;br /&gt;
   l.centroid_proj as the_geom,&lt;br /&gt;
   i.shortname as &amp;quot;Nama infrastruktur&amp;quot;,&lt;br /&gt;
 from infrastructure i&lt;br /&gt;
 join locations l on i.locationid = l.id&lt;br /&gt;
 where not i.del&lt;br /&gt;
&lt;br /&gt;
===Mapfile code===&lt;br /&gt;
The R code box of the Report definition interface is used to include mapfile code, which specifies the appearance of the output. &lt;br /&gt;
&lt;br /&gt;
Most of the mapfile is automatically generated using fixed standards and the SQL previously defined, but you have to specify here how the map should appear.&lt;br /&gt;
&lt;br /&gt;
The contents of the R code box is inserted into the mapfile in a LAYER block. Full documentation of what is permitted can be found in the [http://mapserver.org/mapfile/layer.html Mapserver documentation]&lt;br /&gt;
&lt;br /&gt;
Two sections are required (TYPE and CLASS) and there are some optional sections&lt;br /&gt;
=====TYPE (required)=====&lt;br /&gt;
This can be POINT, LINE or POLYGON, depending on the map to be produced. For example, for a point map:&lt;br /&gt;
 TYPE POINT&lt;br /&gt;
Other types can be used including CHART, CIRCLE, RASTER but these are uncommon advanced features. &lt;br /&gt;
&lt;br /&gt;
=====CLASS (required) =====&lt;br /&gt;
This defines the appearance of the data, as well as the legend. A typical class block for a point map &lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;Kasus&amp;quot;&lt;br /&gt;
      STYLE&lt;br /&gt;
          SYMBOL &amp;quot;reddot&amp;quot;&lt;br /&gt;
      END # STYLE&lt;br /&gt;
  END # CLASS&lt;br /&gt;
&lt;br /&gt;
This will produce a layer with a single symbol (reddot) for all features, and a legend with 'Kasus'.&lt;br /&gt;
&lt;br /&gt;
For a polygon layer, you can define the colour of the outline and the fill:&lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;Pelatihan&amp;quot;&lt;br /&gt;
      STYLE&lt;br /&gt;
        COLOR 255 0 0&lt;br /&gt;
        OUTLINECOLOR 255 0 0&lt;br /&gt;
        SIZE 6&lt;br /&gt;
      END # STYLE&lt;br /&gt;
  END&lt;br /&gt;
&lt;br /&gt;
The style options are very powerful. See the [http://mapserver.org/mapfile/class.html#class Mapserver CLASS documentation] for more information.&lt;br /&gt;
&lt;br /&gt;
Standard SYMBOLs are pre-defined in a symbol file. For more symbols, this file will have to be manually edited.&lt;br /&gt;
&lt;br /&gt;
It is also possible to define multiple levels of shading, by referring to data from the query. For example:&lt;br /&gt;
&lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;Belum gunakan&amp;quot;&lt;br /&gt;
      EXPRESSION ([laporan] = 0)&lt;br /&gt;
      STYLE&lt;br /&gt;
        COLOR 237 248 251&lt;br /&gt;
      END # STYLE&lt;br /&gt;
  END # CLASS&lt;br /&gt;
 &lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;1 - 5 laporan&amp;quot;&lt;br /&gt;
      EXPRESSION ([laporan] &amp;gt; 0  AND [laporan] &amp;lt; 6)&lt;br /&gt;
      STYLE&lt;br /&gt;
        COLOR 178 226 226&lt;br /&gt;
      END # STYLE&lt;br /&gt;
  END # CLASS&lt;br /&gt;
 &lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;6 - 50 laporan&amp;quot;&lt;br /&gt;
      EXPRESSION ([laporan] &amp;gt; 5  AND [laporan] &amp;lt; 50)&lt;br /&gt;
      STYLE&lt;br /&gt;
        COLOR 102 194 164&lt;br /&gt;
      END # STYLE&lt;br /&gt;
  END # CLASS&lt;br /&gt;
 &lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;&amp;gt; 50 laporan&amp;quot;&lt;br /&gt;
      EXPRESSION ([laporan] &amp;gt; 50)&lt;br /&gt;
      STYLE&lt;br /&gt;
        COLOR 35 139 69&lt;br /&gt;
      END # STYLE&lt;br /&gt;
  END # CLASS&lt;br /&gt;
&lt;br /&gt;
In this case, the query must have a field called &amp;quot;laporan&amp;quot; which has an integer (the number of reports submitted).&lt;br /&gt;
&lt;br /&gt;
The COLOR and OUTLINECOLOR lines require a RGB (red green blue) colour code. The [http://colorbrewer2.org/index.html   ColorBrewer] web site is an excellent tool for picking good map colours and finding their RGB code.&lt;br /&gt;
&lt;br /&gt;
=====CLASSITEM (optional) =====&lt;br /&gt;
This specifies that one field in the query will be used to determine the style of different features. For example:&lt;br /&gt;
&lt;br /&gt;
  CLASSITEM &amp;quot;Hasil&amp;quot;&lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;Positif&amp;quot;&lt;br /&gt;
        EXPRESSION &amp;quot;Pos&amp;quot;&lt;br /&gt;
      STYLE&lt;br /&gt;
        SYMBOL &amp;quot;reddot&amp;quot;&lt;br /&gt;
      END&lt;br /&gt;
  END&lt;br /&gt;
 &lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;Negatif&amp;quot;&lt;br /&gt;
      EXPRESSION &amp;quot;Neg&amp;quot;&lt;br /&gt;
      STYLE&lt;br /&gt;
        SYMBOL &amp;quot;bluedot&amp;quot;&lt;br /&gt;
      END&lt;br /&gt;
  END&lt;br /&gt;
&lt;br /&gt;
This means that there must be a field in the query called &amp;quot;Hasil&amp;quot; and it will return values of either &amp;quot;Positif&amp;quot; or &amp;quot;Negatif&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Viewing maps==&lt;br /&gt;
Maps must be viewed using the 'root' interface.&lt;br /&gt;
&lt;br /&gt;
* If there are no special parameters (the normal situation)&lt;br /&gt;
** Set up a menu entry as usual, and set the URL to: root/index/''reportid''. For example&lt;br /&gt;
 /root/index/216&lt;br /&gt;
&lt;br /&gt;
* If there are parameters to produce a pre-configured report (different from the default) you need to remove the first '/' and add the parameters. For example:&lt;br /&gt;
&lt;br /&gt;
 root/index/216&amp;amp;param[diagnosis]=13&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=Mapping&amp;diff=39430</id>
		<title>Mapping</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=Mapping&amp;diff=39430"/>
		<updated>2018-06-22T11:25:22Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: /* Mapfile code */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Mapping=&lt;br /&gt;
The mapping system allows administrators to define new map-based reports rapidly through the interface, and for them to be viewed on-line.&lt;br /&gt;
&lt;br /&gt;
==Defining a new map==&lt;br /&gt;
Maps are defined in the same way as other reports, using the Administration | Reports menu. There are two key differences compared to other reports: requirements for the SQL data definition, and style information (Mapfile code)&lt;br /&gt;
&lt;br /&gt;
===SQL===&lt;br /&gt;
The SQL is similar to all other reports, and should be a single SELECT query. However, there are several particular requirements&lt;br /&gt;
&lt;br /&gt;
====Required fields====&lt;br /&gt;
Every query must return two required fields:&lt;br /&gt;
* '''gid''' - this is a 'geographic ID' and is a unique integer for each spatial unit returned. Often, this can just be the id from the locations table, but if there can be multiple reports per location, you need to choose another unique ID value. It doesn't matter which. If nothing else is available, you can also use the row number window function:&lt;br /&gt;
 select row_number() over () as gid, &lt;br /&gt;
* '''the_geom''': this is the spatial data and must be included in every report. It should always come from the projected version of the locations table spatial data. That is:&lt;br /&gt;
** For polygon data (administrative units) this should be geom_proj (e.g. select geom_proj as the_geom, )&lt;br /&gt;
** For point data (village locations etc) this should be centroid_proj (e.g. select centroid_proj as the_geom, )&lt;br /&gt;
Don't use the standard geom and centroid columns, or the data will not be in the right projection and won't appear on the map.&lt;br /&gt;
&lt;br /&gt;
===Field names===&lt;br /&gt;
Any fields generated in the query will be available to the user with a map query (where they click on a feature, and further information pops up). So that this feature works nicely, you should include all the data that a user might want to see, and name each field with a user-friendly name. For example&lt;br /&gt;
 SELECT&lt;br /&gt;
   sum(total) as &amp;quot;Julah hewan&amp;quot;&lt;br /&gt;
&lt;br /&gt;
===Example===&lt;br /&gt;
An example of a simple query to display infrastructure:&lt;br /&gt;
 SELECT&lt;br /&gt;
   i.id as gid,&lt;br /&gt;
   l.centroid_proj as the_geom,&lt;br /&gt;
   i.shortname as &amp;quot;Nama infrastruktur&amp;quot;,&lt;br /&gt;
 from infrastructure i&lt;br /&gt;
 join locations l on i.locationid = l.id&lt;br /&gt;
 where not i.del&lt;br /&gt;
&lt;br /&gt;
===Mapfile code===&lt;br /&gt;
The R code box of the Report definition interface is used to include mapfile code, which specifies the appearance of the output. &lt;br /&gt;
&lt;br /&gt;
Most of the mapfile is automatically generated using fixed standards and the SQL previously defined, but you have to specify here how the map should appear.&lt;br /&gt;
&lt;br /&gt;
The contents of the R code box is inserted into the mapfile in a LAYER block. Full documentation of what is permitted can be found in the [http://mapserver.org/mapfile/layer.html Mapserver documentation]&lt;br /&gt;
&lt;br /&gt;
Two sections are required (TYPE and CLASS) and there are some optional sections&lt;br /&gt;
=====TYPE (required)=====&lt;br /&gt;
This can be POINT, LINE or POLYGON, depending on the map to be produced. For example, for a point map:&lt;br /&gt;
 TYPE POINT&lt;br /&gt;
Other types can be used including CHART, CIRCLE, RASTER but these are uncommon advanced features. &lt;br /&gt;
&lt;br /&gt;
=====CLASS (required) =====&lt;br /&gt;
This defines the appearance of the data, as well as the legend. A typical class block for a point map &lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;Kasus&amp;quot;&lt;br /&gt;
      STYLE&lt;br /&gt;
          SYMBOL &amp;quot;reddot&amp;quot;&lt;br /&gt;
      END # STYLE&lt;br /&gt;
  END # CLASS&lt;br /&gt;
&lt;br /&gt;
This will produce a layer with a single symbol (reddot) for all features, and a legend with 'Kasus'.&lt;br /&gt;
&lt;br /&gt;
For a polygon layer, you can define the colour of the outline and the fill:&lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;Pelatihan&amp;quot;&lt;br /&gt;
      STYLE&lt;br /&gt;
        COLOR 255 0 0&lt;br /&gt;
        OUTLINECOLOR 255 0 0&lt;br /&gt;
        SIZE 6&lt;br /&gt;
      END # STYLE&lt;br /&gt;
  END&lt;br /&gt;
&lt;br /&gt;
The style options are very powerful. See the [http://mapserver.org/mapfile/class.html#class Mapserver CLASS documentation] for more information.&lt;br /&gt;
&lt;br /&gt;
Standard SYMBOLs are pre-defined in a symbol file. For more symbols, this file will have to be manually edited.&lt;br /&gt;
&lt;br /&gt;
It is also possible to define multiple levels of shading, by referring to data from the query. For example:&lt;br /&gt;
&lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;Belum gunakan&amp;quot;&lt;br /&gt;
      EXPRESSION ([laporan] = 0)&lt;br /&gt;
      STYLE&lt;br /&gt;
        COLOR 237 248 251&lt;br /&gt;
      END # STYLE&lt;br /&gt;
  END # CLASS&lt;br /&gt;
 &lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;1 - 5 laporan&amp;quot;&lt;br /&gt;
      EXPRESSION ([laporan] &amp;gt; 0  AND [laporan] &amp;lt; 6)&lt;br /&gt;
      STYLE&lt;br /&gt;
        COLOR 178 226 226&lt;br /&gt;
      END # STYLE&lt;br /&gt;
  END # CLASS&lt;br /&gt;
 &lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;6 - 50 laporan&amp;quot;&lt;br /&gt;
      EXPRESSION ([laporan] &amp;gt; 5  AND [laporan] &amp;lt; 50)&lt;br /&gt;
      STYLE&lt;br /&gt;
        COLOR 102 194 164&lt;br /&gt;
      END # STYLE&lt;br /&gt;
  END # CLASS&lt;br /&gt;
 &lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;&amp;gt; 50 laporan&amp;quot;&lt;br /&gt;
      EXPRESSION ([laporan] &amp;gt; 50)&lt;br /&gt;
      STYLE&lt;br /&gt;
        COLOR 35 139 69&lt;br /&gt;
      END # STYLE&lt;br /&gt;
  END # CLASS&lt;br /&gt;
&lt;br /&gt;
In this case, the query must have a field called &amp;quot;laporan&amp;quot; which has an integer (the number of reports submitted).&lt;br /&gt;
&lt;br /&gt;
The COLOR and OUTLINECOLOR lines require a RGB (red green blue) colour code. The [http://colorbrewer2.org/index.html   ColorBrewer] web site is an excellent tool for picking good map colours and finding their RGB code.&lt;br /&gt;
&lt;br /&gt;
=====CLASSITEM (optional) =====&lt;br /&gt;
This specifies that one field in the query will be used to determine the style of different features. For example:&lt;br /&gt;
&lt;br /&gt;
  CLASSITEM &amp;quot;Hasil&amp;quot;&lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;Positif&amp;quot;&lt;br /&gt;
        EXPRESSION &amp;quot;Pos&amp;quot;&lt;br /&gt;
      STYLE&lt;br /&gt;
        SYMBOL &amp;quot;reddot&amp;quot;&lt;br /&gt;
      END&lt;br /&gt;
  END&lt;br /&gt;
 &lt;br /&gt;
  CLASS&lt;br /&gt;
      NAME &amp;quot;Negatif&amp;quot;&lt;br /&gt;
      EXPRESSION &amp;quot;Neg&amp;quot;&lt;br /&gt;
      STYLE&lt;br /&gt;
        SYMBOL &amp;quot;bluedot&amp;quot;&lt;br /&gt;
      END&lt;br /&gt;
  END&lt;br /&gt;
&lt;br /&gt;
This means that there must be a field in the query called &amp;quot;Hasil&amp;quot; and it will return values of either &amp;quot;Positif&amp;quot; or &amp;quot;Negatif&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Viewing maps==&lt;br /&gt;
Maps must be viewed using the 'root' interface.&lt;br /&gt;
&lt;br /&gt;
* If there are no special parameters (the normal situation)&lt;br /&gt;
** Set up a menu entry as usual, and set the URL to: root/index/''reportid''. For example&lt;br /&gt;
 /root/index/216&lt;br /&gt;
&lt;br /&gt;
* If there are parameters to produced a pre-configured report (different from the default) you need to use remove the first '/' and add the parameters. For example:&lt;br /&gt;
&lt;br /&gt;
 root/index/216&amp;amp;param[diagnosis]=13&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=Advanced_permissions&amp;diff=39429</id>
		<title>Advanced permissions</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=Advanced_permissions&amp;diff=39429"/>
		<updated>2018-06-22T11:12:19Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: /* Page that already has a Task created for it */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Manage advanced permissions=&lt;br /&gt;
Permissions on the web site are managed in two ways:&lt;br /&gt;
* Menu permissions&lt;br /&gt;
** This controls which menu items a user can see and is set in the Administration | Interface | Menu system. If a user does not have permission to see a menu, it won't appear so they cannot select that feature from the interface.&lt;br /&gt;
* Advanced permissions&lt;br /&gt;
** This controls if a user is actually allowed to access a particular page (whether or not it appears on the menu). If a user does not have page permissions, they will get an error message when they try to access the page. &lt;br /&gt;
&lt;br /&gt;
These permissions are rather more complex. In this example, we will demonstrate giving permission for pages to manage data in program table. If a user gets an access error message, the permissions can be updated as follows:&lt;br /&gt;
&lt;br /&gt;
=====New page with no permission=====&lt;br /&gt;
If this is a new interface, then there will be no Operations or Tasks created yet for the page. You have to create these, before you can assign them to a user. If this is an existing page, then the Task should already exist and you can skip this first part.&lt;br /&gt;
&lt;br /&gt;
# Find out the root name of the page that we want to access. On the site, go to the page and look at the URL. For example, if the url is ''www.isikhnas.com/id/trainingCourse/admin'' then the root name of the page is ''TrainingCourse''. Note that the first letter should be made into a capital but the rest should be unchanged&lt;br /&gt;
# Go to the interface permissions page: Administration | Permission | Interface Permissions.&lt;br /&gt;
# Click on '''Manage Auth Items'''&lt;br /&gt;
# Click on '''Create''' under Auth Items&lt;br /&gt;
# Create a task to group several operations together:&lt;br /&gt;
## Name is ''RootName'''''Administrating''' where ''RootName'' is the root name you found out above&lt;br /&gt;
## Type is '''Task'''&lt;br /&gt;
## Leave the other fields blank&lt;br /&gt;
## Click '''Create'''&lt;br /&gt;
# Now create the different operations for that task (not all may be required, depending on what you want people to be able to do)&lt;br /&gt;
## Click Create again&lt;br /&gt;
## Name is ''RootName'''''Index''', type is Operation, click Create&lt;br /&gt;
## Name is ''RootName'''''Create''', type is Operation, click Create&lt;br /&gt;
## Name is ''RootName'''''Delete''', type is Operation, click Create&lt;br /&gt;
## Name is ''RootName'''''Update''', type is Operation, click Create&lt;br /&gt;
## Name is ''RootName'''''Admin''', type is Operation, click Create&lt;br /&gt;
## Name is ''RootName'''''View''', type is Operation, click Create&lt;br /&gt;
# Now group the four operations under the new task&lt;br /&gt;
## At the top, click '''Assign to users'''&lt;br /&gt;
## Click on the '''Tasks''' tab&lt;br /&gt;
## Select the new task you created (''RootName'''''Administrating''')&lt;br /&gt;
## In the third box (on the right) find the four Operations you created and highlight them&lt;br /&gt;
## Click the '''&amp;lt;&amp;lt;''' button to move them to the middle box (Assigned operations)&lt;br /&gt;
&lt;br /&gt;
=====Page that already has a Task created for it=====&lt;br /&gt;
Once you have created the Task and Operations, or if it was already created:&lt;br /&gt;
&lt;br /&gt;
# Now assign the new permissions for that interface to the right user groups&lt;br /&gt;
## Click on '''Roles''' tab at the top&lt;br /&gt;
## Find the user group on the left that you want to have permission &lt;br /&gt;
## Find the Task in the third box (on the right (''RootName'''''Administrating''')&lt;br /&gt;
## Highlight the Task&lt;br /&gt;
## Click the '''&amp;lt;&amp;lt;''' button to add it to the group's tasks&lt;br /&gt;
# Repeat for any other groups that require permissions&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=Advanced_permissions&amp;diff=39428</id>
		<title>Advanced permissions</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=Advanced_permissions&amp;diff=39428"/>
		<updated>2018-06-22T11:11:21Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: /* New page with no permission */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Manage advanced permissions=&lt;br /&gt;
Permissions on the web site are managed in two ways:&lt;br /&gt;
* Menu permissions&lt;br /&gt;
** This controls which menu items a user can see and is set in the Administration | Interface | Menu system. If a user does not have permission to see a menu, it won't appear so they cannot select that feature from the interface.&lt;br /&gt;
* Advanced permissions&lt;br /&gt;
** This controls if a user is actually allowed to access a particular page (whether or not it appears on the menu). If a user does not have page permissions, they will get an error message when they try to access the page. &lt;br /&gt;
&lt;br /&gt;
These permissions are rather more complex. In this example, we will demonstrate giving permission for pages to manage data in program table. If a user gets an access error message, the permissions can be updated as follows:&lt;br /&gt;
&lt;br /&gt;
=====New page with no permission=====&lt;br /&gt;
If this is a new interface, then there will be no Operations or Tasks created yet for the page. You have to create these, before you can assign them to a user. If this is an existing page, then the Task should already exist and you can skip this first part.&lt;br /&gt;
&lt;br /&gt;
# Find out the root name of the page that we want to access. On the site, go to the page and look at the URL. For example, if the url is ''www.isikhnas.com/id/trainingCourse/admin'' then the root name of the page is ''TrainingCourse''. Note that the first letter should be made into a capital but the rest should be unchanged&lt;br /&gt;
# Go to the interface permissions page: Administration | Permission | Interface Permissions.&lt;br /&gt;
# Click on '''Manage Auth Items'''&lt;br /&gt;
# Click on '''Create''' under Auth Items&lt;br /&gt;
# Create a task to group several operations together:&lt;br /&gt;
## Name is ''RootName'''''Administrating''' where ''RootName'' is the root name you found out above&lt;br /&gt;
## Type is '''Task'''&lt;br /&gt;
## Leave the other fields blank&lt;br /&gt;
## Click '''Create'''&lt;br /&gt;
# Now create the different operations for that task (not all may be required, depending on what you want people to be able to do)&lt;br /&gt;
## Click Create again&lt;br /&gt;
## Name is ''RootName'''''Index''', type is Operation, click Create&lt;br /&gt;
## Name is ''RootName'''''Create''', type is Operation, click Create&lt;br /&gt;
## Name is ''RootName'''''Delete''', type is Operation, click Create&lt;br /&gt;
## Name is ''RootName'''''Update''', type is Operation, click Create&lt;br /&gt;
## Name is ''RootName'''''Admin''', type is Operation, click Create&lt;br /&gt;
## Name is ''RootName'''''View''', type is Operation, click Create&lt;br /&gt;
# Now group the four operations under the new task&lt;br /&gt;
## At the top, click '''Assign to users'''&lt;br /&gt;
## Click on the '''Tasks''' tab&lt;br /&gt;
## Select the new task you created (''RootName'''''Administrating''')&lt;br /&gt;
## In the third box (on the right) find the four Operations you created and highlight them&lt;br /&gt;
## Click the '''&amp;lt;&amp;lt;''' button to move them to the middle box (Assigned operations)&lt;br /&gt;
&lt;br /&gt;
=====Page that already has a Task created for it=====&lt;br /&gt;
Once you have created the Task and Operations, or if it was already crated:&lt;br /&gt;
&lt;br /&gt;
# Now assign the new permissions for that interface to the right user groups&lt;br /&gt;
## Click on '''Roles''' tab at the top&lt;br /&gt;
## Find the user group on the left that you want to have permission &lt;br /&gt;
## Find the Task in the third box (on the right (''RootName'''''Administrating''')&lt;br /&gt;
## Highlight the Task&lt;br /&gt;
## Click the '''&amp;lt;&amp;lt;''' button to add it to the group's tasks&lt;br /&gt;
# Repeat for any other groups that require permissions&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=SMS_Handler:_Step_by_step_example&amp;diff=39427</id>
		<title>SMS Handler: Step by step example</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=SMS_Handler:_Step_by_step_example&amp;diff=39427"/>
		<updated>2018-06-22T10:58:37Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: /* 6) Build the message handler */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages/&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
==1) Plan the message== &amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
* What data are you trying to collect?&lt;br /&gt;
* Why?&lt;br /&gt;
* Who are the stakeholders?&lt;br /&gt;
** Who will provide the data? &lt;br /&gt;
*** What information do they have? &lt;br /&gt;
*** Can they generate the data reliably?&lt;br /&gt;
*** What is the cost of generating and reporting the data?&lt;br /&gt;
*** What benefits will they get?&lt;br /&gt;
** Who will use the data?&lt;br /&gt;
*** What do they need?&lt;br /&gt;
*** How long will they need the data to be collected? One off or ongoing?&lt;br /&gt;
* Exactly what data items should be collected&lt;br /&gt;
&lt;br /&gt;
==2) Design the database table== &amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
* Will the data be stored in existing tables or do we need new tables?&lt;br /&gt;
* What should the table design be&lt;br /&gt;
* Create the tables if necessary &lt;br /&gt;
** This currently requires Admin access to the database. Check with Priyono. &lt;br /&gt;
&lt;br /&gt;
==3) Design the SMS message== &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
* What will the start code be?&lt;br /&gt;
* What fields will be collected?&lt;br /&gt;
* What is the type of each field?&lt;br /&gt;
* Are there any optional fields?&lt;br /&gt;
* Are there any repeating groups?&lt;br /&gt;
&lt;br /&gt;
==4) Set up the SMS message metadata== &amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
* Go to Edit SMS message, under SMS metadata in the Administration menu&lt;br /&gt;
* Create a new SMS message record&lt;br /&gt;
** For the reply (and any possible alert messages) put in a temporary placeholder SQL (e.g. &amp;quot;select 'Thank you'&amp;quot;)&lt;br /&gt;
* Go to Edit SMS Fields&lt;br /&gt;
* Add and configure each of the fields&lt;br /&gt;
&lt;br /&gt;
==5) Set up the translation strings ==&lt;br /&gt;
* Go to Admin | Interface |translation table &lt;br /&gt;
* Add new strings for each of the error messages&lt;br /&gt;
* Add new strings for the reply and alert messages (if required)&lt;br /&gt;
&lt;br /&gt;
==6) Build the message handler ==&lt;br /&gt;
* Go to Admin | SMS metadata | Create SMS handler&lt;br /&gt;
* Select the new message from the list and click submit&lt;br /&gt;
* Check any errors carefully. They are usually to do with invalid lookup SQL for specific fields. Proceed if there are no errors, otherwise correct the problems and retry&lt;br /&gt;
&lt;br /&gt;
==7) Test the message ==&lt;br /&gt;
* Using IM test the message&lt;br /&gt;
* First send just the message start code to check that the format message is correct&lt;br /&gt;
* Then send some correct data&lt;br /&gt;
* Then send some incorrect data testing each of the validation steps&lt;br /&gt;
&lt;br /&gt;
==8) Finish the reply and alert messages ==&lt;br /&gt;
* Now there is some test data, it is easier to compose the SQL for the reply message.&lt;br /&gt;
* Build the SQL in PgAdmin first to make sure that it works&lt;br /&gt;
* The copy it into the SMS message definition. &lt;br /&gt;
** Replace any hard coded user ID values with the predefined variable '''sms_userid'''&lt;br /&gt;
** Replace any hard coded message ID values with '''sms_msgid'''&lt;br /&gt;
* Save, re-create the handler, and test again&lt;br /&gt;
&lt;br /&gt;
==9) Set up any required custom business rules ==&lt;br /&gt;
See the section on Business Rules.&lt;br /&gt;
&lt;br /&gt;
==10) Create output reports==&lt;br /&gt;
Create new reports to display, summarise and analyse the data that is now able to be captured. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=SMS_handler_setup&amp;diff=39426</id>
		<title>SMS handler setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=SMS_handler_setup&amp;diff=39426"/>
		<updated>2018-06-22T10:52:38Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages/&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
= Overview = &amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
An SMS handler is a function that controls the process of receiving and parsing data from an incoming SMS, checking the data, inserting it into a table and providing any response messages required. The creation of an SMS handler function is automated and can be achieved by providing metadata through the web interface. The process involves:&lt;br /&gt;
* Setting up the general message information (format, premissions, purpose, data table, error message etc)&lt;br /&gt;
* Setting up the details for each of the fields&lt;br /&gt;
* Populating reference tables&lt;br /&gt;
* Creating the data table&lt;br /&gt;
* Creating message strings for outgoing messages&lt;br /&gt;
These steps are described in detail below.&lt;br /&gt;
&lt;br /&gt;
= Message attributes = &amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
The interface to edit message attributes is available through the Admin | Create SMS Handler | Edit SMS Message menu options. The fields are:&lt;br /&gt;
== Start code ==&lt;br /&gt;
Every message has a start code. This must contain only letters (no numbers, symbols, spaces or punctuation), and should be written in capital letters. It must be at least one letter, but can be longer. It is best to keep it as short as possible, while still allowing it to be easily understood and unique. Two or three letters is normal.&lt;br /&gt;
== Name ==&lt;br /&gt;
The name for the message is a short name describing the purpose of the message or the type of data being collected. It should be written in Indonesian and English.&lt;br /&gt;
== Permission ==&lt;br /&gt;
This controls who is allowed to send this type of message. The drop down list shows all defined group permissions, normally named in the form 'can_dosomething'. If there is an existing permission that is already suitable for this type of report, that can be used, but normally it will be necessary to define a new permission. Once defined, and associated with the SMS message, different user groups can be give this permission or not, depending on their responsibilities.&lt;br /&gt;
=== Defining a new permission ===&lt;br /&gt;
In the menu, go to Admin | Permissions | Edit Permissions. &lt;br /&gt;
==== Name ====&lt;br /&gt;
Enter a new name for the permission in the form 'can_xxx'. For a permission for a particular SMS message, the normal name for the permission is 'can_send_''message_type'''. For example, for an OB message, the corresponding permission would be 'can_send_ob'.&lt;br /&gt;
==== Enable by default ====&lt;br /&gt;
This sets all groups to have this permission by default. Normally this should be set to 'no' so that groups have to be explicitly give this permission, unless it is sure that almost all users should be able to use this permission.&lt;br /&gt;
==== User permission ====&lt;br /&gt;
Set this to 'no' as we are creating a group permission. &lt;br /&gt;
&lt;br /&gt;
Save the permission and return to Edit SMS Message, selecting the permission that you have created.&lt;br /&gt;
== Purpose and Help Text == &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
These are currently not used but will be used in documentation and the interface in future. &lt;br /&gt;
== Table name ==&lt;br /&gt;
This is the name of an existing database table into which the received data will be inserted. Type the name of the table.&lt;br /&gt;
&lt;br /&gt;
Only the first table name is required. The second and third are used in special cases where data is distributed amongst several tables&lt;br /&gt;
&lt;br /&gt;
== Error message ==&lt;br /&gt;
This is a key to a string which will be used as the error message if the general format of the message is incorrect. Normally it is in the form ''message_type''_error. For example, for an OB message, the name would be OB_error.&lt;br /&gt;
== Reply SQL ==&lt;br /&gt;
This is an SQL 'select' query that controls what message is returned to the sender. It must always be defined.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
The SQL should return a single varchar value which is the text of the message that will be returned to the sender. At its very simplest, it could be something like: &lt;br /&gt;
 select 'Thank you. Your message has been received'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
However, all reply messages should confirm the contents of the submitted message, converted from the coded version into clear text. The reply SQL is therefore normally more complex, and queries the newly inserted data (filtering by the message id), joins it to references tables, and composes the result. It also normally uses language-specific strings from the translation table to present the message in the correct form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
Pre-defined variables that can be included in the SQL (and almost always are) are:&lt;br /&gt;
* sms_userid: the user ID of the person sending the message. This is used to get the right language.&lt;br /&gt;
* sms_msgid: the message ID for the current message. This is used to get the submitted data.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
Helpful functions that may be included in reply SQL include:&lt;br /&gt;
* get_string(key varchar, userid integer): returns a defined string (indexed by the key) in the user's preferred language&lt;br /&gt;
* get_user_lang(userid integer): return the language code for the user. This is useful if directly accessing data from a translated array field.&lt;br /&gt;
* add_checkdigit(code integer): when returning a numeric code (case ID, program ID etc), a check digit is used to ensure that there are no typographical errors. This function adds a check digit to the raw code. All ID codes should have a check digit added, as if they are used in a message without the check digit, it will be interpreted as an error by the system.  &lt;br /&gt;
* format(format_string varchar, input_string varchar,...): This is a standard PostgreSQL function to format a string with a list of replaceable variables. The string should contain one or more %s placeholders, which are replaced with the value of the variables specified.&lt;br /&gt;
* string_agg(string varchar, separator varchar): another standard SQL function that aggregates string from multiple rows (when using a 'group by' clause) into a single concatenated value, with each row's string separated by the separator. This is useful when the message might insert data into multiple rows, and the reply needs to summarise the data from these rows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
An example of a reply SQL for the OB message:&lt;br /&gt;
 select format(get_string('OB_reply',sms_userid), dinfo, s.species[1], l.name)&lt;br /&gt;
 from ( &lt;br /&gt;
 select t.caseid, string_agg(format('%s (%s %s)', d.name, dose, units), ', ') as dinfo &lt;br /&gt;
 from treatments t&lt;br /&gt;
 join drugs d on d.id = drug&lt;br /&gt;
 where t.msgid = sms_msgid group by t.caseid) as dd&lt;br /&gt;
 left join cadre_reports c on c.id = dd.caseid&lt;br /&gt;
 left join locations l on l.id = c.locationid&lt;br /&gt;
 left join species s on s.id = c. speciesid&lt;br /&gt;
&lt;br /&gt;
== Alert SQL == &amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
The Alert SQL is used to send immediate SMS messages to users other than the original sender, alerting them of the contents of the original SQL or of other information. If no alert message is required, this field should be left blank.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
This is a 'select' statement returning one or more records with two fields: the phone number (varchar, from the users.phone field), and the message content (varchar).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
The same variables and functions described above are available for use in this message. An example of the Alert SQL for the Q message is:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
select u2.phone, &lt;br /&gt;
   format(get_string('Q_alert',2), u.firstname||coalesce(' '||u.surname,''), &lt;br /&gt;
   local_phone(u.phone), to_char(report_date,'HH:MM:SS'), question)&lt;br /&gt;
 from questions q&lt;br /&gt;
 join users u on u.id = q.userid&lt;br /&gt;
 join users u2 on (not u2.del) and (u2.phone is not null) and (u2.groupid &amp;lt; 2)&lt;br /&gt;
 join locations l on l.id = u2.location&lt;br /&gt;
 join locations l2 on l2.id = u.location&lt;br /&gt;
 where q.msgid = sms_msgid&lt;br /&gt;
&lt;br /&gt;
== Protected == &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
Mark 'yes' to protect this message from being overwritten by the message creation process. Any message function that has had custom modifications made to its code should be marked as protected to avoid being overwritten by the automatic message generator function.&lt;br /&gt;
&lt;br /&gt;
= Field attributes = &amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
Once the message attributes are defined, the fields for the message need to be defined. This is done from the menu: Admin | Create SMS Handler | Edit SMS Fields&lt;br /&gt;
&lt;br /&gt;
== Message == &amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
Select the existing message defined in the previous step&lt;br /&gt;
&lt;br /&gt;
== Natorder == &amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
Natural order. Type an integer to define the order of fields in the SMS. Each field must have a different sequential value.&lt;br /&gt;
&lt;br /&gt;
== Name == &amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
Enter a name in English and Indonesian. This appears in documentation and is used internally. It may contains spaces. It should briefly describe what the content of the field is.&lt;br /&gt;
&lt;br /&gt;
== Data type == &amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
The following data types are defined:&lt;br /&gt;
&lt;br /&gt;
===== Numeric code ===== &amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
This is a number containing a check digit. Its main use is case ID, but it is used in a number of other situations where users need to send and receive numeric codes.&lt;br /&gt;
&lt;br /&gt;
===== Lookup code ===== &amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
This is an alpha (letters only) code (one or more letters), which is used to look up a value from a reference table. This is the most common way to refer to reference table values.&lt;br /&gt;
&lt;br /&gt;
===== Integer ===== &amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
This is a simple integer, used for counts in the data submitted (number of animals slaughtered, vaccinated, sick etc.)&lt;br /&gt;
&lt;br /&gt;
===== Location ===== &amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
This is a location code, which can be a full version (8 digits in the new system, 10 in the old), or short (just the last digits below the users area of responsibility).&lt;br /&gt;
&lt;br /&gt;
===== Boolean ===== &amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
A single letter text code that can take two values, defaulting to Y (Ya, yes), and T (tidak, no). SQL can be used to define other alternatives. &lt;br /&gt;
&lt;br /&gt;
===== Text ===== &amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
Free text with any characters. This normally has to be the last field in a message as it is difficult to parse.&lt;br /&gt;
&lt;br /&gt;
===== Float ===== &amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
A number that may contain a decimal point, for example, drug doses or coordinates.&lt;br /&gt;
&lt;br /&gt;
===== Integer code ===== &amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
An integer used to lookup a value from a reference table. This is not commonly used (alpha codes are used instead).&lt;br /&gt;
&lt;br /&gt;
===== Text array ===== &amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
A field containing one or more lookup codes (alpha codes referencing values in a table). These values are parsed and inserted into a single array field in the data table. In this way, multiple values can be handled as a single field type. This is used for signs and differential diagnoses, for example. Care is required to ensure that parsing is unambiguous (last field, or surrounded by numeric fields).&lt;br /&gt;
&lt;br /&gt;
===== Date ===== &lt;br /&gt;
A field which allows the user to submit a date. Dates are submitted in one of the following formats:&lt;br /&gt;
* dd/mm/yyyy&lt;br /&gt;
* dd/mm/yy (assumes 21st century)&lt;br /&gt;
* mm/yyyy (assumes 15th of the month)&lt;br /&gt;
* mm/yy (assumes 15th of the month, 21st century)&lt;br /&gt;
* dd.mm.yyyy and other variations above&lt;br /&gt;
* dd-mm-yyyy and other variations above&lt;br /&gt;
Dates are stored in date fields in the database.&lt;br /&gt;
&lt;br /&gt;
== Optional == &amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
This indicates if the field is optional or not.&lt;br /&gt;
&lt;br /&gt;
== Group sequence == &amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
SMS messages can contain repeating groups of fields. For example a POP population message can contain multiple pairs of ([species] [number]...). &lt;br /&gt;
When a field is not part of a repeating group, it should have a group sequence of 0. If it is part of a group, then each element of the group should be numbered sequentially. Only one repeating group is permitted in a message.&lt;br /&gt;
&lt;br /&gt;
== Lookup SQL == &amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
This is a select statement with a different purpose depending on the field type. When not required, it can be left blank. When used, it should contain a single %s value which is replaced with the value of the field. Return types vary with the field type.&lt;br /&gt;
&lt;br /&gt;
===== Lookup code ===== &amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
The SQL returns the id from the reference table of the value submitted. The SQL is required in this case. For example:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!--T:32--&amp;gt;&lt;br /&gt;
select id from drugs where upper(code) = upper(trim(%s))&lt;br /&gt;
&lt;br /&gt;
===== Integer or Date ===== &amp;lt;!--T:33--&amp;gt;&lt;br /&gt;
The SQL is required. If provided it is used for range checking. It should return a single boolean value. For example:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!--T:34--&amp;gt;&lt;br /&gt;
select %s between 0 and 1000&lt;br /&gt;
&lt;br /&gt;
===== Text array ===== &amp;lt;!--T:35--&amp;gt;&lt;br /&gt;
The SQL is required. It returns an array of ID values for the codes in the input array. The requirements are rather special:&lt;br /&gt;
* two %s parameters&lt;br /&gt;
** First one: select %s from&lt;br /&gt;
** Second one: (select unnest(regexp_matches(%s,'([a-z]+)', 'igx')) as code) as dat&lt;br /&gt;
* join to main table: left outer join diseases s on upper(dat.code) = upper(s.code)&lt;br /&gt;
** table '''must''' be aliased 's'&lt;br /&gt;
* other join clauses and filters&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:36--&amp;gt;&lt;br /&gt;
For example:&lt;br /&gt;
 &lt;br /&gt;
 select %s from&lt;br /&gt;
  (select unnest(regexp_matches(%s,'([a-z]+)', 'igx')) as code) as dat&lt;br /&gt;
 left outer join diseases s on upper(dat.code) = upper(s.code)&lt;br /&gt;
 AND NOT del&lt;br /&gt;
 AND (valid_from IS NULL OR valid_from &amp;lt;= CURRENT_DATE)&lt;br /&gt;
 AND (valid_to IS NULL OR valid_to &amp;gt;= CURRENT_DATE)&lt;br /&gt;
&lt;br /&gt;
===== Boolean ===== &amp;lt;!--T:37--&amp;gt;&lt;br /&gt;
The SQL is optional. If present, it returns a boolean value for the submitted code. For example:&lt;br /&gt;
 select case upper(trim(%s)) &lt;br /&gt;
  when 'K' then true&lt;br /&gt;
  when 'Y' then true&lt;br /&gt;
  when 'T' then false &lt;br /&gt;
  when 'N' then false&lt;br /&gt;
 else null end&lt;br /&gt;
&lt;br /&gt;
== Field name == &amp;lt;!--T:38--&amp;gt;&lt;br /&gt;
The field in the database table into which the data received will be inserted.&lt;br /&gt;
&lt;br /&gt;
== Error message ==  &amp;lt;!--T:39--&amp;gt;&lt;br /&gt;
A key reference to an string in the translation table that will be used as the error message for this field. The key should contain one replaceable parameter (%s) which is replaced with the (invalid) value submitted.&lt;br /&gt;
&lt;br /&gt;
= Reference tables = &amp;lt;!--T:40--&amp;gt;&lt;br /&gt;
Reference tables are in the reference schema. Structure varies but most have at least the following fields:&lt;br /&gt;
* id: unique record id&lt;br /&gt;
* code: an alpha code&lt;br /&gt;
* hier_code: a dot separated hierarchical code in the form 1.1.1. This is used to arrange data at different levels of detail, allowing more flexible analysis&lt;br /&gt;
* name: varchar[] - a text array field with the name in Indonesian at index 1, and English at index 2&lt;br /&gt;
* valid_from and valid_to: dates indicating the period of validity of the item. Valid_to may be null indicating ongoing validity.&lt;br /&gt;
* modified_by: user id of the last user to modify the value&lt;br /&gt;
* modified_on: timestamp of the last modification&lt;br /&gt;
* del: boolean flag for deleted&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:41--&amp;gt;&lt;br /&gt;
In addition, there may be classifications referring to other tables (eg species) or flags (eg zoonosis, OIE etc for diseases)&lt;br /&gt;
&lt;br /&gt;
= Data tables = &amp;lt;!--T:42--&amp;gt;&lt;br /&gt;
Data tables are stored in the 'data' schema. Their structure depends on the data required, but they must have have the following fields which are automatically updated:&lt;br /&gt;
* id: unique record id&lt;br /&gt;
* userid: integer referencing the user ID of the submitting user (from the 'users' table);&lt;br /&gt;
* report_date: timestamp of data submission&lt;br /&gt;
* msgid bigint: the unique id of the incoming SMS message&lt;br /&gt;
* created_on and modified_on: dates&lt;br /&gt;
* created_by and modified_by: user IDs&lt;br /&gt;
* del: deleted flag&lt;br /&gt;
&lt;br /&gt;
= Message strings = &amp;lt;!--T:43--&amp;gt;&lt;br /&gt;
Translated message strings are stored against a key in the translation table, and can be edited using the menu Admin | Message codes and translations | SMS messsage text. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:44--&amp;gt;&lt;br /&gt;
The key or string code is used to access the message. By convention, this code starts with the message start code, followed by an underscore and then an abbreviation of the purpose. For example a message with an error due to an invalid drug code when sending a treatment (OB) message might be OB_invdrug.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:45--&amp;gt;&lt;br /&gt;
The strings are stored in Indonesian and English (and this can be expanded to other languages if required). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:46--&amp;gt;&lt;br /&gt;
Most messages have data inserted into them, so are used with the SQL '''format()''' function. For this to work, they need to have place holders for the data to insert, in the form %s. For example:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!--T:47--&amp;gt;&lt;br /&gt;
Laporan tindak lanjut dari %s (ID kasus %s) %s. %s&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:48--&amp;gt;&lt;br /&gt;
would have the following data substituted into it: village name, case ID, the numbers of animals and whether the outbreak is resolved or ongoing.&lt;br /&gt;
&lt;br /&gt;
= Building the message function = &amp;lt;!--T:49--&amp;gt;&lt;br /&gt;
Once the metadata, tables and strings for an SMS handler function have been set up, the function needs to be generated before it can be used. Use the menu Admin | Create SMS handler | Create handler function, and select the function to generate. Once generated, the function will be saved in the SMS schema, and be immediately available for use.&lt;br /&gt;
&lt;br /&gt;
= Testing the message function = &amp;lt;!--T:50--&amp;gt;&lt;br /&gt;
To test a new function, use the Instant Messaging system. This allows a message to be composed and submitted to the system as if it were being sent by SMS. The message is inserted into the inbox, normal processing follows, and any response messages are inserted into the outbox and returned to the sender via IM. Note that any data submitted is inserted into the database so be sure to delete any test data afterwards if using the live server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=SMS_handler_setup&amp;diff=39425</id>
		<title>SMS handler setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=SMS_handler_setup&amp;diff=39425"/>
		<updated>2018-06-22T10:39:51Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: /* Reply SQL */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages/&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
= Overview = &amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
An SMS handler is a function that controls the process of receiving and parsing data from an incoming SMS, checking the data, inserting it into a table and providing any response messages required. The creation of an SMS handler function is automated and can be achieved by providing metadata through the web interface. The process involves:&lt;br /&gt;
* Setting up the general message information (format, premissions, purpose, data table, error message etc)&lt;br /&gt;
* Setting up the details for each of the fields&lt;br /&gt;
* Populating reference tables&lt;br /&gt;
* Creating the data table&lt;br /&gt;
* Creating message strings for outgoing messages&lt;br /&gt;
These steps are described in detail below.&lt;br /&gt;
&lt;br /&gt;
= Message attributes = &amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
The interface to edit message attributes is available through the Admin | Create SMS Handler | Edit SMS Message menu options. The fields are:&lt;br /&gt;
== Start code ==&lt;br /&gt;
Every message has a start code. This must contain only letters (no numbers, symbols, spaces or punctuation), and should be written in capital letters. It must be at least one letter, but can be longer. It is best to keep it as short as possible, while still allowing it to be easily understood and unique. Two or three letters is normal.&lt;br /&gt;
== Name ==&lt;br /&gt;
The name for the message is a short name describing the purpose of the message or the type of data being collected. It should be written in Indonesian and English.&lt;br /&gt;
== Permission ==&lt;br /&gt;
This controls who is allowed to send this type of message. The drop down list shows all defined group permissions, normally named in the form 'can_dosomething'. If there is an existing permission that is already suitable for this type of report, that can be used, but normally it will be necessary to define a new permission. Once defined, and associated with the SMS message, different user groups can be give this permission or not, depending on their responsibilities.&lt;br /&gt;
=== Defining a new permission ===&lt;br /&gt;
In the menu, go to Admin | Permissions | Edit Permissions. &lt;br /&gt;
==== Name ====&lt;br /&gt;
Enter a new name for the permission in the form 'can_xxx'. For a permission for a particular SMS message, the normal name for the permission is 'can_send_''message_type'''. For example, for an OB message, the corresponding permission would be 'can_send_ob'.&lt;br /&gt;
==== Enable by default ====&lt;br /&gt;
This sets all groups to have this permission by default. Normally this should be set to 'no' so that groups have to be explicitly give this permission, unless it is sure that almost all users should be able to use this permission.&lt;br /&gt;
==== User permission ====&lt;br /&gt;
Set this to 'no' as we are creating a group permission. &lt;br /&gt;
&lt;br /&gt;
Save the permission and return to Edit SMS Message, selecting the permission that you have created.&lt;br /&gt;
== Purpose and Help Text == &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
These are currently not used but will be used in documentation and the interface in future. &lt;br /&gt;
== Table name ==&lt;br /&gt;
This is the name of an existing database table into which the received data will be inserted. Type the name of the table.&lt;br /&gt;
&lt;br /&gt;
Only the first table name is required. The second and third are used in special cases where data is distributed amongst several tables&lt;br /&gt;
&lt;br /&gt;
== Error message ==&lt;br /&gt;
This is a key to a string which will be used as the error message if the general format of the message is incorrect. Normally it is in the form ''message_type''_error. For example, for an OB message, the name would be OB_error.&lt;br /&gt;
== Reply SQL ==&lt;br /&gt;
This is an SQL 'select' query that controls what message is returned to the sender. It must always be defined.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
The SQL should return a single varchar value which is the text of the message that will be returned to the sender. At its very simplest, it could be something like: &lt;br /&gt;
 select 'Thank you. Your message has been received'&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
However, all reply messages should confirm the contents of the submitted message, converted from the coded version into clear text. The reply SQL is therefore normally more complex, and queries the newly inserted data (filtering by the message id), joins it to references tables, and composes the result. It also normally uses language-specific strings from the translation table to present the message in the correct form. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
Pre-defined variables that can be included in the SQL (and almost always are) are:&lt;br /&gt;
* sms_userid: the user ID of the person sending the message. This is used to get the right language.&lt;br /&gt;
* sms_msgid: the message ID for the current message. This is used to get the submitted data.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
Helpful functions that may be included in reply SQL include:&lt;br /&gt;
* get_string(key varchar, userid integer): returns a defined string (indexed by the key) in the user's preferred language&lt;br /&gt;
* get_user_lang(userid integer): return the language code for the user. This is useful if directly accessing data from a translated array field.&lt;br /&gt;
* add_checkdigit(code integer): when returning a numeric code (case ID, program ID etc), a check digit is used to ensure that there are no typographical errors. This function adds a check digit to the raw code. All ID codes should have a check digit added, as if they are used in a message without the check digit, it will be interpreted as an error by the system.  &lt;br /&gt;
* format(format_string varchar, input_string varchar,...): This is a standard PostgreSQL function to format a string with a list of replaceable variables. The string should contain one or more %s placeholders, which are replaced with the value of the variables specified.&lt;br /&gt;
* string_agg(string varchar, separator varchar): another standard SQL function that aggregates string from multiple rows (when using a 'group by' clause) into a single concatenated value, with each row's string separated by the separator. This is useful when the message might insert data into multiple rows, and the reply needs to summarise the data from these rows.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
An example of a reply SQL for the OB message:&lt;br /&gt;
 select format(get_string('OB_reply',sms_userid), dinfo, s.species[1], l.name)&lt;br /&gt;
 from ( &lt;br /&gt;
 select t.caseid, string_agg(format('%s (%s %s)', d.name, dose, units), ', ') as dinfo &lt;br /&gt;
 from treatments t&lt;br /&gt;
 join drugs d on d.id = drug&lt;br /&gt;
 where t.msgid = sms_msgid group by t.caseid) as dd&lt;br /&gt;
 left join cadre_reports c on c.id = dd.caseid&lt;br /&gt;
 left join locations l on l.id = c.locationid&lt;br /&gt;
 left join species s on s.id = c. speciesid&lt;br /&gt;
&lt;br /&gt;
== Alert SQL == &amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
The Alert SQL is used to send immediate SMS messages to users other than the original sender, alerting them of the contents of the original SQL or of other information. If no alert message is required, this field should be left blank.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
This is a 'select' statement returning one or more records with two fields: the phone number (varchar, from the users.phone field), and the message content (varchar).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
The same variables and functions described above are available for use in this message. An example of the Alert SQL for the Q message is:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
select u2.phone, &lt;br /&gt;
   format(get_string('Q_alert',2), u.firstname||coalesce(' '||u.surname,''), &lt;br /&gt;
   local_phone(u.phone), to_char(report_date,'HH:MM:SS'), question)&lt;br /&gt;
 from questions q&lt;br /&gt;
 join users u on u.id = q.userid&lt;br /&gt;
 join users u2 on (not u2.del) and (u2.phone is not null) and (u2.groupid &amp;lt; 2)&lt;br /&gt;
 join locations l on l.id = u2.location&lt;br /&gt;
 join locations l2 on l2.id = u.location&lt;br /&gt;
 where q.msgid = sms_msgid&lt;br /&gt;
&lt;br /&gt;
== Protected == &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
Mark 'yes' to protect this message from being overwritten by the message creation process. Any message function that has had custom modifications made to its code should be marked as protected to avoid being overwritten by the automatic message generator function.&lt;br /&gt;
&lt;br /&gt;
= Field attributes = &amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
Once the message attributes are defined, the fields for the message need to be defined. This is done from the menu: Admin | Create SMS Handler | Edit SMS Fields&lt;br /&gt;
&lt;br /&gt;
== Message == &amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
Select the existing message defined in the previous step&lt;br /&gt;
&lt;br /&gt;
== Natorder == &amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
Natural order. Type an integer to define the order of fields in the SMS. Each field must have a different sequential value.&lt;br /&gt;
&lt;br /&gt;
== Name == &amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
Enter a name in English and Indonesian. This appears in documentation and is used internally. It may contains spaces. It should briefly describe what the content of the field is.&lt;br /&gt;
&lt;br /&gt;
== Data type == &amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
The following data types are defined:&lt;br /&gt;
&lt;br /&gt;
===== Numeric code ===== &amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
This is a number containing a check digit. Its main use is case ID, but it is used in a number of other situations where users need to send and receive numeric codes.&lt;br /&gt;
&lt;br /&gt;
===== Lookup code ===== &amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
This is a alpha (letters only) code (one or more letters), which is used to look up a value from a reference table. This is the most common way to refer to reference table values.&lt;br /&gt;
&lt;br /&gt;
===== Integer ===== &amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
This is a simple integer, used for counts in the data submitted (number of animals slaughtered, vaccinated, sick etc.)&lt;br /&gt;
&lt;br /&gt;
===== Location ===== &amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
This is a location code, which can be a full version (8 digits in the new system, 10 in the old), or short (just the last digits below the users area of responsibility).&lt;br /&gt;
&lt;br /&gt;
===== Boolean ===== &amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
A single letter text code that can take two values, defaulting to Y (Ya, yes), and T (tidak, no). SQL can be used to define other alternatives. &lt;br /&gt;
&lt;br /&gt;
===== Text ===== &amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
Free text with any characters. This normally has to be the last field in a message as it is difficult to parse.&lt;br /&gt;
&lt;br /&gt;
===== Float ===== &amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
A number that may contain a decimal point, for example, drug doses or coordinates.&lt;br /&gt;
&lt;br /&gt;
===== Integer code ===== &amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
An integer used to lookup a value from a reference table. This is not commonly used (alpha codes are used instead).&lt;br /&gt;
&lt;br /&gt;
===== Text array ===== &amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
A field containing one or more lookup codes (alpha codes referencing values in a table). These values are parsed and inserted into a single array field in the data table. In this way, multiple values can be handled as a single field type. This is used for signs and differential diagnoses, for example. Care is required to ensure that parsing is unambiguous (last field, or surrounded by numeric fields).&lt;br /&gt;
&lt;br /&gt;
===== Date ===== &lt;br /&gt;
A field which allows the user to submit a date. Dates are submitted in one of the following formats:&lt;br /&gt;
* dd/mm/yyyy&lt;br /&gt;
* dd/mm/yy (assumes 21st century)&lt;br /&gt;
* mm/yyyy (assumes 15th of the month)&lt;br /&gt;
* mm/yy (assumes 15th of the month, 21st century)&lt;br /&gt;
* dd.mm.yyyy and other variations above&lt;br /&gt;
* dd-mm-yyyy and other variations above&lt;br /&gt;
Dates are stored in date fields in the database.&lt;br /&gt;
&lt;br /&gt;
== Optional == &amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
This indicates if the field is optional or not.&lt;br /&gt;
&lt;br /&gt;
== Group sequence == &amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
SMS messages can contain repeating groups of fields. For example a POP population message can contain multiple pairs of ([species] [number]...). &lt;br /&gt;
When a field is not part of a repeating group, it should have a group sequence of 0. If it is part of a group, then each element of the group should be numbered sequentially. Only one repeating group is permitted in a message.&lt;br /&gt;
&lt;br /&gt;
== Lookup SQL == &amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
This is a select statement with a different purpose depending on the field type. When not required, it can be left blank. When used, it should contain a single %s value which is replaced with the value of the field. Return types vary with the field type.&lt;br /&gt;
&lt;br /&gt;
===== Lookup code ===== &amp;lt;!--T:31--&amp;gt;&lt;br /&gt;
The SQL returns the id from the reference table of the value submitted. The SQL is required in this case. For example:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!--T:32--&amp;gt;&lt;br /&gt;
select id from drugs where upper(code) = upper(trim(%s))&lt;br /&gt;
&lt;br /&gt;
===== Integer or Date ===== &amp;lt;!--T:33--&amp;gt;&lt;br /&gt;
The SQL is required. If provided it is used for range checking. It should return a single boolean value. For example:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!--T:34--&amp;gt;&lt;br /&gt;
select %s between 0 and 1000&lt;br /&gt;
&lt;br /&gt;
===== Text array ===== &amp;lt;!--T:35--&amp;gt;&lt;br /&gt;
The SQL is required. It returns an array of ID values for the codes in the input array. The requirements are rather special:&lt;br /&gt;
* two %s parameters&lt;br /&gt;
** First one: select %s from&lt;br /&gt;
** Second one: (select unnest(regexp_matches(%s,'([a-z]+)', 'igx')) as code) as dat&lt;br /&gt;
* join to main table: left outer join diseases s on upper(dat.code) = upper(s.code)&lt;br /&gt;
** table '''must''' be aliased 's'&lt;br /&gt;
* other join clauses and filters&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:36--&amp;gt;&lt;br /&gt;
For example:&lt;br /&gt;
 &lt;br /&gt;
 select %s from&lt;br /&gt;
  (select unnest(regexp_matches(%s,'([a-z]+)', 'igx')) as code) as dat&lt;br /&gt;
 left outer join diseases s on upper(dat.code) = upper(s.code)&lt;br /&gt;
 AND NOT del&lt;br /&gt;
 AND (valid_from IS NULL OR valid_from &amp;lt;= CURRENT_DATE)&lt;br /&gt;
 AND (valid_to IS NULL OR valid_to &amp;gt;= CURRENT_DATE)&lt;br /&gt;
&lt;br /&gt;
===== Boolean ===== &amp;lt;!--T:37--&amp;gt;&lt;br /&gt;
The SQL is optional. If present, it returns a boolean value for the submitted code. For example:&lt;br /&gt;
 select case upper(trim(%s)) &lt;br /&gt;
  when 'K' then true&lt;br /&gt;
  when 'Y' then true&lt;br /&gt;
  when 'T' then false &lt;br /&gt;
  when 'N' then false&lt;br /&gt;
 else null end&lt;br /&gt;
&lt;br /&gt;
== Field name == &amp;lt;!--T:38--&amp;gt;&lt;br /&gt;
The field in the database table into which the data received will be inserted.&lt;br /&gt;
&lt;br /&gt;
== Error message ==  &amp;lt;!--T:39--&amp;gt;&lt;br /&gt;
A key reference to an string in the translation table that will be used as the error message for this field. The key should contain one replaceable parameter (%s) which is replaced with the (invalid) value submitted.&lt;br /&gt;
&lt;br /&gt;
= Reference tables = &amp;lt;!--T:40--&amp;gt;&lt;br /&gt;
Reference tables are in the reference schema. Structure varies but most have at least the following fields:&lt;br /&gt;
* id: unique record id&lt;br /&gt;
* code: an alpha code&lt;br /&gt;
* hier_code: a dot separated hierarchical code in the form 1.1.1. This is used to arrange data at different levels of detail, allowing more flexible analysis&lt;br /&gt;
* name: varchar[] - a text array field with the name in Indonesian at index 1, and English at index 2&lt;br /&gt;
* valid_from and valid_to: dates indicating the period of validity of the item. Valid_to may be null indicating ongoing validity.&lt;br /&gt;
* modified_by: user id of the last user to modify the value&lt;br /&gt;
* modified_on: timestamp of the last modification&lt;br /&gt;
* del: boolean flag for deleted&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:41--&amp;gt;&lt;br /&gt;
In addition, there may be classifications referring to other tables (eg species) or flags (eg zoonosis, OIE etc for diseases)&lt;br /&gt;
&lt;br /&gt;
= Data tables = &amp;lt;!--T:42--&amp;gt;&lt;br /&gt;
Data tables are stored in the 'data' schema. Their structure depends on the data required, but they must have have the following fields which are automatically updated:&lt;br /&gt;
* id: unique record id&lt;br /&gt;
* userid: integer referencing the user ID of the submitting user (from the 'users' table);&lt;br /&gt;
* report_date: timestamp of data submission&lt;br /&gt;
* msgid bigint: the unique id of the incoming SMS message&lt;br /&gt;
* created_on and modified_on: dates&lt;br /&gt;
* created_by and modified_by: user IDs&lt;br /&gt;
* del: deleted flag&lt;br /&gt;
&lt;br /&gt;
= Message strings = &amp;lt;!--T:43--&amp;gt;&lt;br /&gt;
Translated message strings are stored against a key in the translation table, and can be edited using the menu Admin | Message codes and translations | SMS messsage text. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:44--&amp;gt;&lt;br /&gt;
The key or string code is used to access the message. By convention, this code starts with the message start code, followed by an underscore and then an abbreviation of the purpose. For example a message with an error due to an invalid drug code when sending a treatment (OB) message might be OB_invdrug.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:45--&amp;gt;&lt;br /&gt;
The strings are stored in Indonesian and English (and this can be expanded to other languages if required). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:46--&amp;gt;&lt;br /&gt;
Most messages have data inserted into them, so are used with the SQL '''format()''' function. For this to work, they need to have place holders for the data to insert, in the form %s. For example:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;!--T:47--&amp;gt;&lt;br /&gt;
Laporan tindak lanjut dari %s (ID kasus %s) %s. %s&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:48--&amp;gt;&lt;br /&gt;
would have the following data substituted into it: village name, case ID, the numbers of animals and whether the outbreak is resolved or ongoing.&lt;br /&gt;
&lt;br /&gt;
= Building the message function = &amp;lt;!--T:49--&amp;gt;&lt;br /&gt;
Once the metadata, tables and strings for an SMS handler function have been set up, the function needs to be generated before it can be used. Use the menu Admin | Create SMS handler | Create handler function, and select the function to generate. Once generated, the function will be saved in the SMS schema, and be immediately available for use.&lt;br /&gt;
&lt;br /&gt;
= Testing the message function = &amp;lt;!--T:50--&amp;gt;&lt;br /&gt;
To test a new function, use the Instant Messaging system. This allows a message to be composed and submitted to the system as if it were being sent by SMS. The message is inserted into the inbox, normal processing follows, and any response messages are inserted into the outbox and returned to the sender via IM. Note that any data submitted is inserted into the database so be sure to delete any test data afterwards if using the live server&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=New_table_creation&amp;diff=39424</id>
		<title>New table creation</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=New_table_creation&amp;diff=39424"/>
		<updated>2018-06-22T10:28:23Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: /* Reference fields */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=New table creation=&lt;br /&gt;
==Technical guide==&lt;br /&gt;
New tables are created manually by administrators or iSIKHNAS technical champions using either direct server shell access and psql, or PGAdmin on a remote computer. &lt;br /&gt;
&lt;br /&gt;
In either case you will need access passwords and appropriate permissions for table creation. This example uses PGAdmin.&lt;br /&gt;
&lt;br /&gt;
# Compose your table creation statement using a text editor, based on the standard fields and naming conventions shown below.&lt;br /&gt;
# Open PGAdmin and log on to the correct iSIKHNAS database. Possible databases are:&lt;br /&gt;
## Crashtest - this is the first one you should use. It is the development server and is reconfigured every night (so all changes are lost). Use this to make sure your table creation script is working&lt;br /&gt;
## Training (Sidecar) - the training server is reconfigured every week. Use this for longer term testing, once you think you've got it right&lt;br /&gt;
## Live - Once you are sure of the table structure, create it on the live system. it will then be automatically copied to Crashtest (every night) or Sidecar (every Monday).&lt;br /&gt;
# Paste your table creation SQL script into an SQL window and run the script&lt;br /&gt;
# Set table permissions '''Important'''&lt;br /&gt;
## Ensure that isikhnascore and smsd have appropriate permissions on the table, usually including SELECT, UPDATE and INSERT, for any user that needs to access the table:&lt;br /&gt;
&lt;br /&gt;
 GRANT SELECT, UPDATE, INSERT ON TABLE ''tablename'' TO isikhnascore;&lt;br /&gt;
 GRANT SELECT, UPDATE, INSERT ON TABLE ''tablename'' TO smsd;&lt;br /&gt;
 GRANT SELECT ON TABLE ''tablename'' TO champion;&lt;br /&gt;
 GRANT SELECT ON TABLE ''tablename'' TO mailer;&lt;br /&gt;
&lt;br /&gt;
# Set sequence permissions '''Very important'''&lt;br /&gt;
## Ensure that the sequence has all privileges set for any user that may INSERT records into the data table (mainly isikhnascore and smsd). This is really easy to forget and causes permission errors.&lt;br /&gt;
&lt;br /&gt;
 GRANT ALL ON TABLE ''tablename''_id_seq TO isikhnascore;&lt;br /&gt;
 GRANT ALL ON TABLE ''tablename''_id_seq TO smsd;&lt;br /&gt;
&lt;br /&gt;
# Test the table&lt;br /&gt;
&lt;br /&gt;
==Standard fields==&lt;br /&gt;
Every table in the database has a number of standard fields, which are used for consistency and for data auditing purposes. You may only omit or alter these standard fields if you have a very very good reason. &lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE ages (&lt;br /&gt;
   -- record identifier (primary key)&lt;br /&gt;
   id serial primary key,&lt;br /&gt;
   ...data fields here...&lt;br /&gt;
   -- if the table is used to store data submitted by SMS&lt;br /&gt;
   msgid bigint not null,&lt;br /&gt;
   -- standard system audit fields&lt;br /&gt;
   createdby integer NOT NULL REFERENCES users,&lt;br /&gt;
   createdon timestamp NOT NULL DEFAULT now(),&lt;br /&gt;
   modifiedby integer REFERENCES users,&lt;br /&gt;
   modifiedon timestamp without time zone,&lt;br /&gt;
   del boolean NOT NULL DEFAULT false&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
The required standard fields are:&lt;br /&gt;
* id - the unique record id and primary key.&lt;br /&gt;
* createdby - the id of the user creating the record. This must be explicitly included in any INSERT statements&lt;br /&gt;
* createdon - time stamp for creation - automatically inserted&lt;br /&gt;
* modifiedby - user id for UPDATE - must be explicitly included&lt;br /&gt;
* modifiedon - timestamp for UPDATE - use '''now()'''&lt;br /&gt;
* del - the 'deleted' flag. iSIKHNAS never uses DELETE statements, but instead simply flags records as deleted, so they can be referenced for historical purposes or undeleted if required.&lt;br /&gt;
&lt;br /&gt;
If the table is used to store data submitted by SMS or IM, it should also include the '''msgid''' field, which stores the message ID used to link incoming and outgoing SMS data.&lt;br /&gt;
&lt;br /&gt;
==Table and field naming standards==&lt;br /&gt;
&lt;br /&gt;
===Schemas===&lt;br /&gt;
There are a number of schemas in the database for different purposes. Most tables should be created in the following schemas:&lt;br /&gt;
* data - all routine data tables (i.e. tables containing data submitted by users)&lt;br /&gt;
* reference - look up tables&lt;br /&gt;
* lab - data tables for the lab system &lt;br /&gt;
&lt;br /&gt;
The other schemas are for specialised purposes&lt;br /&gt;
* backoffice - web and database administrative tables&lt;br /&gt;
* metadata - data defining table, field, spreadsheet, structures etc&lt;br /&gt;
* sms - SMS system management &lt;br /&gt;
* reports - output report definitions&lt;br /&gt;
* public - not used, except for functions from imported libraries&lt;br /&gt;
&lt;br /&gt;
===Table names===&lt;br /&gt;
Tables may be named in English or Indonesian. Core tables developed by the original team have been named in English, but later tables developed by champions can be named in Indonesian.&lt;br /&gt;
&lt;br /&gt;
Tables are named in all lowercase. Multiple words are combined without spaces or underscores. (This rule has been applied inconsistently by some developers less familiar with the standards but should be adhered to for future table creation)&lt;br /&gt;
&lt;br /&gt;
The name of the table represents the elements contained in each record, expressed as a plural (in English). Link tables use the combined names of the two tables they are linking.&lt;br /&gt;
&lt;br /&gt;
Table names should be unique in the entire database (even though tables with the same name are permitted in different schemas).&lt;br /&gt;
&lt;br /&gt;
===Fields===&lt;br /&gt;
Fields are named all lowercase with no spaces, with the name reflecting concisely the content. &lt;br /&gt;
&lt;br /&gt;
===Reference fields===&lt;br /&gt;
Reference fields are named based on the target table followed by 'id' with no space or underscore. So to reference the id field of the users table, the reference field would be userid.&lt;br /&gt;
&lt;br /&gt;
All reference fields are of type integer except in unusual circumstances where a very large number of records are expected, when a bigint is used.&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
See the automated list of [[database tables]] for examples. Note the displayed format is not exactly the same as the recommended table definition format in all cases (e.g., the use of 'serial' and references).&lt;br /&gt;
&lt;br /&gt;
====Reference table====&lt;br /&gt;
The ageunits table is an example of a simple reference table:&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE ageunits (&lt;br /&gt;
   id serial PRIMARY KEY,&lt;br /&gt;
   '''code character varying NOT NULL,'''&lt;br /&gt;
   '''name character varying[] NOT NULL,'''&lt;br /&gt;
   createdby integer NOT NULL REFERENCES users,&lt;br /&gt;
   createdon timestamp NOT NULL DEFAULT now(),&lt;br /&gt;
   modifiedby integer REFERENCES users,&lt;br /&gt;
   modifiedon timestamp without time zone,&lt;br /&gt;
   del boolean NOT NULL DEFAULT false&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
Standard names for reference table fields include:&lt;br /&gt;
* name - an array of type character varying. This is used to display the Indonesian name [1] and English name [2]&lt;br /&gt;
* code - character varying. A short abbreviation such as may be used in SMS messages.&lt;br /&gt;
* hiercode - character varying. Numbers in the form 3.4.2.3 representing a hierarchical coding system. As an example&lt;br /&gt;
&lt;br /&gt;
{{#apGetSQL:&lt;br /&gt;
select hiercode, code, &lt;br /&gt;
format('%s%s',&lt;br /&gt;
  repeat('&amp;amp;nbsp;',(array_length(regexp_split_to_array(hiercode,'\.'),1)-1)*2),name[2])&lt;br /&gt;
from specimentypes order by regexp_split_to_array(hiercode,'\.')|Hiercode,Code, Spesimen}}&lt;br /&gt;
&lt;br /&gt;
====Data tables====&lt;br /&gt;
An example of a data table (animals in laboratory submissions) is shown below:&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE animals (&lt;br /&gt;
   id serial PRIMARY KEY,&lt;br /&gt;
   '''labsubmissionid integer REFERENCES labsubmissions,'''&lt;br /&gt;
   '''animalident character varying NOT NULL,'''&lt;br /&gt;
   '''ownerid integer REFERENCES owners,'''&lt;br /&gt;
   '''animalid bigint REFERENCES hewan,'''&lt;br /&gt;
   '''speciesid integer NOT NULL REFERENCES species,'''&lt;br /&gt;
   '''sexid integer REFERENCES sex,'''&lt;br /&gt;
   '''age double precision,'''&lt;br /&gt;
   '''ageunitsid integer REFERENCES ageunits,'''&lt;br /&gt;
   '''msgid bigint,'''&lt;br /&gt;
   createdby integer NOT NULL DEFAULT 1 REFERENCES users,&lt;br /&gt;
   createdon timestamp without time zone NOT NULL DEFAULT now(),&lt;br /&gt;
   modifiedby integer REFERENCES users,&lt;br /&gt;
   modifiedon timestamp without time zone,&lt;br /&gt;
   del boolean NOT NULL DEFAULT false&lt;br /&gt;
 );&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=New_table_creation&amp;diff=39423</id>
		<title>New table creation</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=New_table_creation&amp;diff=39423"/>
		<updated>2018-06-22T10:24:38Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: /* Table names */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=New table creation=&lt;br /&gt;
==Technical guide==&lt;br /&gt;
New tables are created manually by administrators or iSIKHNAS technical champions using either direct server shell access and psql, or PGAdmin on a remote computer. &lt;br /&gt;
&lt;br /&gt;
In either case you will need access passwords and appropriate permissions for table creation. This example uses PGAdmin.&lt;br /&gt;
&lt;br /&gt;
# Compose your table creation statement using a text editor, based on the standard fields and naming conventions shown below.&lt;br /&gt;
# Open PGAdmin and log on to the correct iSIKHNAS database. Possible databases are:&lt;br /&gt;
## Crashtest - this is the first one you should use. It is the development server and is reconfigured every night (so all changes are lost). Use this to make sure your table creation script is working&lt;br /&gt;
## Training (Sidecar) - the training server is reconfigured every week. Use this for longer term testing, once you think you've got it right&lt;br /&gt;
## Live - Once you are sure of the table structure, create it on the live system. it will then be automatically copied to Crashtest (every night) or Sidecar (every Monday).&lt;br /&gt;
# Paste your table creation SQL script into an SQL window and run the script&lt;br /&gt;
# Set table permissions '''Important'''&lt;br /&gt;
## Ensure that isikhnascore and smsd have appropriate permissions on the table, usually including SELECT, UPDATE and INSERT, for any user that needs to access the table:&lt;br /&gt;
&lt;br /&gt;
 GRANT SELECT, UPDATE, INSERT ON TABLE ''tablename'' TO isikhnascore;&lt;br /&gt;
 GRANT SELECT, UPDATE, INSERT ON TABLE ''tablename'' TO smsd;&lt;br /&gt;
 GRANT SELECT ON TABLE ''tablename'' TO champion;&lt;br /&gt;
 GRANT SELECT ON TABLE ''tablename'' TO mailer;&lt;br /&gt;
&lt;br /&gt;
# Set sequence permissions '''Very important'''&lt;br /&gt;
## Ensure that the sequence has all privileges set for any user that may INSERT records into the data table (mainly isikhnascore and smsd). This is really easy to forget and causes permission errors.&lt;br /&gt;
&lt;br /&gt;
 GRANT ALL ON TABLE ''tablename''_id_seq TO isikhnascore;&lt;br /&gt;
 GRANT ALL ON TABLE ''tablename''_id_seq TO smsd;&lt;br /&gt;
&lt;br /&gt;
# Test the table&lt;br /&gt;
&lt;br /&gt;
==Standard fields==&lt;br /&gt;
Every table in the database has a number of standard fields, which are used for consistency and for data auditing purposes. You may only omit or alter these standard fields if you have a very very good reason. &lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE ages (&lt;br /&gt;
   -- record identifier (primary key)&lt;br /&gt;
   id serial primary key,&lt;br /&gt;
   ...data fields here...&lt;br /&gt;
   -- if the table is used to store data submitted by SMS&lt;br /&gt;
   msgid bigint not null,&lt;br /&gt;
   -- standard system audit fields&lt;br /&gt;
   createdby integer NOT NULL REFERENCES users,&lt;br /&gt;
   createdon timestamp NOT NULL DEFAULT now(),&lt;br /&gt;
   modifiedby integer REFERENCES users,&lt;br /&gt;
   modifiedon timestamp without time zone,&lt;br /&gt;
   del boolean NOT NULL DEFAULT false&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
The required standard fields are:&lt;br /&gt;
* id - the unique record id and primary key.&lt;br /&gt;
* createdby - the id of the user creating the record. This must be explicitly included in any INSERT statements&lt;br /&gt;
* createdon - time stamp for creation - automatically inserted&lt;br /&gt;
* modifiedby - user id for UPDATE - must be explicitly included&lt;br /&gt;
* modifiedon - timestamp for UPDATE - use '''now()'''&lt;br /&gt;
* del - the 'deleted' flag. iSIKHNAS never uses DELETE statements, but instead simply flags records as deleted, so they can be referenced for historical purposes or undeleted if required.&lt;br /&gt;
&lt;br /&gt;
If the table is used to store data submitted by SMS or IM, it should also include the '''msgid''' field, which stores the message ID used to link incoming and outgoing SMS data.&lt;br /&gt;
&lt;br /&gt;
==Table and field naming standards==&lt;br /&gt;
&lt;br /&gt;
===Schemas===&lt;br /&gt;
There are a number of schemas in the database for different purposes. Most tables should be created in the following schemas:&lt;br /&gt;
* data - all routine data tables (i.e. tables containing data submitted by users)&lt;br /&gt;
* reference - look up tables&lt;br /&gt;
* lab - data tables for the lab system &lt;br /&gt;
&lt;br /&gt;
The other schemas are for specialised purposes&lt;br /&gt;
* backoffice - web and database administrative tables&lt;br /&gt;
* metadata - data defining table, field, spreadsheet, structures etc&lt;br /&gt;
* sms - SMS system management &lt;br /&gt;
* reports - output report definitions&lt;br /&gt;
* public - not used, except for functions from imported libraries&lt;br /&gt;
&lt;br /&gt;
===Table names===&lt;br /&gt;
Tables may be named in English or Indonesian. Core tables developed by the original team have been named in English, but later tables developed by champions can be named in Indonesian.&lt;br /&gt;
&lt;br /&gt;
Tables are named in all lowercase. Multiple words are combined without spaces or underscores. (This rule has been applied inconsistently by some developers less familiar with the standards but should be adhered to for future table creation)&lt;br /&gt;
&lt;br /&gt;
The name of the table represents the elements contained in each record, expressed as a plural (in English). Link tables use the combined names of the two tables they are linking.&lt;br /&gt;
&lt;br /&gt;
Table names should be unique in the entire database (even though tables with the same name are permitted in different schemas).&lt;br /&gt;
&lt;br /&gt;
===Fields===&lt;br /&gt;
Fields are named all lowercase with no spaces, with the name reflecting concisely the content. &lt;br /&gt;
&lt;br /&gt;
===Reference fields===&lt;br /&gt;
Reference fields are named based on the target table followed by 'id' with no space or underscore. So to reference the id field of the user table, the reference field would be userid.&lt;br /&gt;
&lt;br /&gt;
All reference fields are of type integer except in unusual circumstances where a very large number of records are expected, when a bigint is used.&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
See the automated list of [[database tables]] for examples. Note the displayed format is not exactly the same as the recommended table definition format in all cases (e.g., the use of 'serial' and references).&lt;br /&gt;
&lt;br /&gt;
====Reference table====&lt;br /&gt;
The ageunits table is an example of a simple reference table:&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE ageunits (&lt;br /&gt;
   id serial PRIMARY KEY,&lt;br /&gt;
   '''code character varying NOT NULL,'''&lt;br /&gt;
   '''name character varying[] NOT NULL,'''&lt;br /&gt;
   createdby integer NOT NULL REFERENCES users,&lt;br /&gt;
   createdon timestamp NOT NULL DEFAULT now(),&lt;br /&gt;
   modifiedby integer REFERENCES users,&lt;br /&gt;
   modifiedon timestamp without time zone,&lt;br /&gt;
   del boolean NOT NULL DEFAULT false&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
Standard names for reference table fields include:&lt;br /&gt;
* name - an array of type character varying. This is used to display the Indonesian name [1] and English name [2]&lt;br /&gt;
* code - character varying. A short abbreviation such as may be used in SMS messages.&lt;br /&gt;
* hiercode - character varying. Numbers in the form 3.4.2.3 representing a hierarchical coding system. As an example&lt;br /&gt;
&lt;br /&gt;
{{#apGetSQL:&lt;br /&gt;
select hiercode, code, &lt;br /&gt;
format('%s%s',&lt;br /&gt;
  repeat('&amp;amp;nbsp;',(array_length(regexp_split_to_array(hiercode,'\.'),1)-1)*2),name[2])&lt;br /&gt;
from specimentypes order by regexp_split_to_array(hiercode,'\.')|Hiercode,Code, Spesimen}}&lt;br /&gt;
&lt;br /&gt;
====Data tables====&lt;br /&gt;
An example of a data table (animals in laboratory submissions) is shown below:&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE animals (&lt;br /&gt;
   id serial PRIMARY KEY,&lt;br /&gt;
   '''labsubmissionid integer REFERENCES labsubmissions,'''&lt;br /&gt;
   '''animalident character varying NOT NULL,'''&lt;br /&gt;
   '''ownerid integer REFERENCES owners,'''&lt;br /&gt;
   '''animalid bigint REFERENCES hewan,'''&lt;br /&gt;
   '''speciesid integer NOT NULL REFERENCES species,'''&lt;br /&gt;
   '''sexid integer REFERENCES sex,'''&lt;br /&gt;
   '''age double precision,'''&lt;br /&gt;
   '''ageunitsid integer REFERENCES ageunits,'''&lt;br /&gt;
   '''msgid bigint,'''&lt;br /&gt;
   createdby integer NOT NULL DEFAULT 1 REFERENCES users,&lt;br /&gt;
   createdon timestamp without time zone NOT NULL DEFAULT now(),&lt;br /&gt;
   modifiedby integer REFERENCES users,&lt;br /&gt;
   modifiedon timestamp without time zone,&lt;br /&gt;
   del boolean NOT NULL DEFAULT false&lt;br /&gt;
 );&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=New_table_creation&amp;diff=39422</id>
		<title>New table creation</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=New_table_creation&amp;diff=39422"/>
		<updated>2018-06-22T10:21:32Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: /* Table names */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=New table creation=&lt;br /&gt;
==Technical guide==&lt;br /&gt;
New tables are created manually by administrators or iSIKHNAS technical champions using either direct server shell access and psql, or PGAdmin on a remote computer. &lt;br /&gt;
&lt;br /&gt;
In either case you will need access passwords and appropriate permissions for table creation. This example uses PGAdmin.&lt;br /&gt;
&lt;br /&gt;
# Compose your table creation statement using a text editor, based on the standard fields and naming conventions shown below.&lt;br /&gt;
# Open PGAdmin and log on to the correct iSIKHNAS database. Possible databases are:&lt;br /&gt;
## Crashtest - this is the first one you should use. It is the development server and is reconfigured every night (so all changes are lost). Use this to make sure your table creation script is working&lt;br /&gt;
## Training (Sidecar) - the training server is reconfigured every week. Use this for longer term testing, once you think you've got it right&lt;br /&gt;
## Live - Once you are sure of the table structure, create it on the live system. it will then be automatically copied to Crashtest (every night) or Sidecar (every Monday).&lt;br /&gt;
# Paste your table creation SQL script into an SQL window and run the script&lt;br /&gt;
# Set table permissions '''Important'''&lt;br /&gt;
## Ensure that isikhnascore and smsd have appropriate permissions on the table, usually including SELECT, UPDATE and INSERT, for any user that needs to access the table:&lt;br /&gt;
&lt;br /&gt;
 GRANT SELECT, UPDATE, INSERT ON TABLE ''tablename'' TO isikhnascore;&lt;br /&gt;
 GRANT SELECT, UPDATE, INSERT ON TABLE ''tablename'' TO smsd;&lt;br /&gt;
 GRANT SELECT ON TABLE ''tablename'' TO champion;&lt;br /&gt;
 GRANT SELECT ON TABLE ''tablename'' TO mailer;&lt;br /&gt;
&lt;br /&gt;
# Set sequence permissions '''Very important'''&lt;br /&gt;
## Ensure that the sequence has all privileges set for any user that may INSERT records into the data table (mainly isikhnascore and smsd). This is really easy to forget and causes permission errors.&lt;br /&gt;
&lt;br /&gt;
 GRANT ALL ON TABLE ''tablename''_id_seq TO isikhnascore;&lt;br /&gt;
 GRANT ALL ON TABLE ''tablename''_id_seq TO smsd;&lt;br /&gt;
&lt;br /&gt;
# Test the table&lt;br /&gt;
&lt;br /&gt;
==Standard fields==&lt;br /&gt;
Every table in the database has a number of standard fields, which are used for consistency and for data auditing purposes. You may only omit or alter these standard fields if you have a very very good reason. &lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE ages (&lt;br /&gt;
   -- record identifier (primary key)&lt;br /&gt;
   id serial primary key,&lt;br /&gt;
   ...data fields here...&lt;br /&gt;
   -- if the table is used to store data submitted by SMS&lt;br /&gt;
   msgid bigint not null,&lt;br /&gt;
   -- standard system audit fields&lt;br /&gt;
   createdby integer NOT NULL REFERENCES users,&lt;br /&gt;
   createdon timestamp NOT NULL DEFAULT now(),&lt;br /&gt;
   modifiedby integer REFERENCES users,&lt;br /&gt;
   modifiedon timestamp without time zone,&lt;br /&gt;
   del boolean NOT NULL DEFAULT false&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
The required standard fields are:&lt;br /&gt;
* id - the unique record id and primary key.&lt;br /&gt;
* createdby - the id of the user creating the record. This must be explicitly included in any INSERT statements&lt;br /&gt;
* createdon - time stamp for creation - automatically inserted&lt;br /&gt;
* modifiedby - user id for UPDATE - must be explicitly included&lt;br /&gt;
* modifiedon - timestamp for UPDATE - use '''now()'''&lt;br /&gt;
* del - the 'deleted' flag. iSIKHNAS never uses DELETE statements, but instead simply flags records as deleted, so they can be referenced for historical purposes or undeleted if required.&lt;br /&gt;
&lt;br /&gt;
If the table is used to store data submitted by SMS or IM, it should also include the '''msgid''' field, which stores the message ID used to link incoming and outgoing SMS data.&lt;br /&gt;
&lt;br /&gt;
==Table and field naming standards==&lt;br /&gt;
&lt;br /&gt;
===Schemas===&lt;br /&gt;
There are a number of schemas in the database for different purposes. Most tables should be created in the following schemas:&lt;br /&gt;
* data - all routine data tables (i.e. tables containing data submitted by users)&lt;br /&gt;
* reference - look up tables&lt;br /&gt;
* lab - data tables for the lab system &lt;br /&gt;
&lt;br /&gt;
The other schemas are for specialised purposes&lt;br /&gt;
* backoffice - web and database administrative tables&lt;br /&gt;
* metadata - data defining table, field, spreadsheet, structures etc&lt;br /&gt;
* sms - SMS system management &lt;br /&gt;
* reports - output report definitions&lt;br /&gt;
* public - not used, except for functions from imported libraries&lt;br /&gt;
&lt;br /&gt;
===Table names===&lt;br /&gt;
Tables may be named in English or Indonesian. Core tables developed by the original team have been named in English, but later tables developed by champions can be named in Indonesian.&lt;br /&gt;
&lt;br /&gt;
Tables are named in all lowercase. Multiple words are combined without spaces or underscores. (This rule has been applied inconsistently by some developers less familiar with the standards but should be adhered to for future table creation)&lt;br /&gt;
&lt;br /&gt;
The name of the table represents the elements contained in each record, expressed as a plural (in English). Link tables use the combined names of the two tables they are linking.&lt;br /&gt;
&lt;br /&gt;
Table names should be unique in the entire database (even though tables with the same name are permitted in different schema).&lt;br /&gt;
&lt;br /&gt;
===Fields===&lt;br /&gt;
Fields are named all lowercase with no spaces, with the name reflecting concisely the content. &lt;br /&gt;
&lt;br /&gt;
===Reference fields===&lt;br /&gt;
Reference fields are named based on the target table followed by 'id' with no space or underscore. So to reference the id field of the user table, the reference field would be userid.&lt;br /&gt;
&lt;br /&gt;
All reference fields are of type integer except in unusual circumstances where a very large number of records are expected, when a bigint is used.&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
See the automated list of [[database tables]] for examples. Note the displayed format is not exactly the same as the recommended table definition format in all cases (e.g., the use of 'serial' and references).&lt;br /&gt;
&lt;br /&gt;
====Reference table====&lt;br /&gt;
The ageunits table is an example of a simple reference table:&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE ageunits (&lt;br /&gt;
   id serial PRIMARY KEY,&lt;br /&gt;
   '''code character varying NOT NULL,'''&lt;br /&gt;
   '''name character varying[] NOT NULL,'''&lt;br /&gt;
   createdby integer NOT NULL REFERENCES users,&lt;br /&gt;
   createdon timestamp NOT NULL DEFAULT now(),&lt;br /&gt;
   modifiedby integer REFERENCES users,&lt;br /&gt;
   modifiedon timestamp without time zone,&lt;br /&gt;
   del boolean NOT NULL DEFAULT false&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
Standard names for reference table fields include:&lt;br /&gt;
* name - an array of type character varying. This is used to display the Indonesian name [1] and English name [2]&lt;br /&gt;
* code - character varying. A short abbreviation such as may be used in SMS messages.&lt;br /&gt;
* hiercode - character varying. Numbers in the form 3.4.2.3 representing a hierarchical coding system. As an example&lt;br /&gt;
&lt;br /&gt;
{{#apGetSQL:&lt;br /&gt;
select hiercode, code, &lt;br /&gt;
format('%s%s',&lt;br /&gt;
  repeat('&amp;amp;nbsp;',(array_length(regexp_split_to_array(hiercode,'\.'),1)-1)*2),name[2])&lt;br /&gt;
from specimentypes order by regexp_split_to_array(hiercode,'\.')|Hiercode,Code, Spesimen}}&lt;br /&gt;
&lt;br /&gt;
====Data tables====&lt;br /&gt;
An example of a data table (animals in laboratory submissions) is shown below:&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE animals (&lt;br /&gt;
   id serial PRIMARY KEY,&lt;br /&gt;
   '''labsubmissionid integer REFERENCES labsubmissions,'''&lt;br /&gt;
   '''animalident character varying NOT NULL,'''&lt;br /&gt;
   '''ownerid integer REFERENCES owners,'''&lt;br /&gt;
   '''animalid bigint REFERENCES hewan,'''&lt;br /&gt;
   '''speciesid integer NOT NULL REFERENCES species,'''&lt;br /&gt;
   '''sexid integer REFERENCES sex,'''&lt;br /&gt;
   '''age double precision,'''&lt;br /&gt;
   '''ageunitsid integer REFERENCES ageunits,'''&lt;br /&gt;
   '''msgid bigint,'''&lt;br /&gt;
   createdby integer NOT NULL DEFAULT 1 REFERENCES users,&lt;br /&gt;
   createdon timestamp without time zone NOT NULL DEFAULT now(),&lt;br /&gt;
   modifiedby integer REFERENCES users,&lt;br /&gt;
   modifiedon timestamp without time zone,&lt;br /&gt;
   del boolean NOT NULL DEFAULT false&lt;br /&gt;
 );&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=New_table_creation&amp;diff=39421</id>
		<title>New table creation</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=New_table_creation&amp;diff=39421"/>
		<updated>2018-06-22T10:20:01Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: /* Schemas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=New table creation=&lt;br /&gt;
==Technical guide==&lt;br /&gt;
New tables are created manually by administrators or iSIKHNAS technical champions using either direct server shell access and psql, or PGAdmin on a remote computer. &lt;br /&gt;
&lt;br /&gt;
In either case you will need access passwords and appropriate permissions for table creation. This example uses PGAdmin.&lt;br /&gt;
&lt;br /&gt;
# Compose your table creation statement using a text editor, based on the standard fields and naming conventions shown below.&lt;br /&gt;
# Open PGAdmin and log on to the correct iSIKHNAS database. Possible databases are:&lt;br /&gt;
## Crashtest - this is the first one you should use. It is the development server and is reconfigured every night (so all changes are lost). Use this to make sure your table creation script is working&lt;br /&gt;
## Training (Sidecar) - the training server is reconfigured every week. Use this for longer term testing, once you think you've got it right&lt;br /&gt;
## Live - Once you are sure of the table structure, create it on the live system. it will then be automatically copied to Crashtest (every night) or Sidecar (every Monday).&lt;br /&gt;
# Paste your table creation SQL script into an SQL window and run the script&lt;br /&gt;
# Set table permissions '''Important'''&lt;br /&gt;
## Ensure that isikhnascore and smsd have appropriate permissions on the table, usually including SELECT, UPDATE and INSERT, for any user that needs to access the table:&lt;br /&gt;
&lt;br /&gt;
 GRANT SELECT, UPDATE, INSERT ON TABLE ''tablename'' TO isikhnascore;&lt;br /&gt;
 GRANT SELECT, UPDATE, INSERT ON TABLE ''tablename'' TO smsd;&lt;br /&gt;
 GRANT SELECT ON TABLE ''tablename'' TO champion;&lt;br /&gt;
 GRANT SELECT ON TABLE ''tablename'' TO mailer;&lt;br /&gt;
&lt;br /&gt;
# Set sequence permissions '''Very important'''&lt;br /&gt;
## Ensure that the sequence has all privileges set for any user that may INSERT records into the data table (mainly isikhnascore and smsd). This is really easy to forget and causes permission errors.&lt;br /&gt;
&lt;br /&gt;
 GRANT ALL ON TABLE ''tablename''_id_seq TO isikhnascore;&lt;br /&gt;
 GRANT ALL ON TABLE ''tablename''_id_seq TO smsd;&lt;br /&gt;
&lt;br /&gt;
# Test the table&lt;br /&gt;
&lt;br /&gt;
==Standard fields==&lt;br /&gt;
Every table in the database has a number of standard fields, which are used for consistency and for data auditing purposes. You may only omit or alter these standard fields if you have a very very good reason. &lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE ages (&lt;br /&gt;
   -- record identifier (primary key)&lt;br /&gt;
   id serial primary key,&lt;br /&gt;
   ...data fields here...&lt;br /&gt;
   -- if the table is used to store data submitted by SMS&lt;br /&gt;
   msgid bigint not null,&lt;br /&gt;
   -- standard system audit fields&lt;br /&gt;
   createdby integer NOT NULL REFERENCES users,&lt;br /&gt;
   createdon timestamp NOT NULL DEFAULT now(),&lt;br /&gt;
   modifiedby integer REFERENCES users,&lt;br /&gt;
   modifiedon timestamp without time zone,&lt;br /&gt;
   del boolean NOT NULL DEFAULT false&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
The required standard fields are:&lt;br /&gt;
* id - the unique record id and primary key.&lt;br /&gt;
* createdby - the id of the user creating the record. This must be explicitly included in any INSERT statements&lt;br /&gt;
* createdon - time stamp for creation - automatically inserted&lt;br /&gt;
* modifiedby - user id for UPDATE - must be explicitly included&lt;br /&gt;
* modifiedon - timestamp for UPDATE - use '''now()'''&lt;br /&gt;
* del - the 'deleted' flag. iSIKHNAS never uses DELETE statements, but instead simply flags records as deleted, so they can be referenced for historical purposes or undeleted if required.&lt;br /&gt;
&lt;br /&gt;
If the table is used to store data submitted by SMS or IM, it should also include the '''msgid''' field, which stores the message ID used to link incoming and outgoing SMS data.&lt;br /&gt;
&lt;br /&gt;
==Table and field naming standards==&lt;br /&gt;
&lt;br /&gt;
===Schemas===&lt;br /&gt;
There are a number of schemas in the database for different purposes. Most tables should be created in the following schemas:&lt;br /&gt;
* data - all routine data tables (i.e. tables containing data submitted by users)&lt;br /&gt;
* reference - look up tables&lt;br /&gt;
* lab - data tables for the lab system &lt;br /&gt;
&lt;br /&gt;
The other schemas are for specialised purposes&lt;br /&gt;
* backoffice - web and database administrative tables&lt;br /&gt;
* metadata - data defining table, field, spreadsheet, structures etc&lt;br /&gt;
* sms - SMS system management &lt;br /&gt;
* reports - output report definitions&lt;br /&gt;
* public - not used, except for functions from imported libraries&lt;br /&gt;
&lt;br /&gt;
===Table names===&lt;br /&gt;
Tables may be named in English or Indonesian. Core tables developed by the original team have been named in English, but later tables developed by champions can be named in Indonesian.&lt;br /&gt;
&lt;br /&gt;
Tables are named in all lowercase. Multiple words are combined without spaces or underscores. (This rule has been applied inconsistently by some developers less familiar with the standards but should be adhered to for future table creation)&lt;br /&gt;
&lt;br /&gt;
The name of the table represents the elements contained in each record, expressed as a plural (in English). Link tables are use the combined names of the two tables they are linking.&lt;br /&gt;
&lt;br /&gt;
Table names should be unique in the entire database (even though tables with the same name are permitted in different schema.&lt;br /&gt;
&lt;br /&gt;
===Fields===&lt;br /&gt;
Fields are named all lowercase with no spaces, with the name reflecting concisely the content. &lt;br /&gt;
&lt;br /&gt;
===Reference fields===&lt;br /&gt;
Reference fields are named based on the target table followed by 'id' with no space or underscore. So to reference the id field of the user table, the reference field would be userid.&lt;br /&gt;
&lt;br /&gt;
All reference fields are of type integer except in unusual circumstances where a very large number of records are expected, when a bigint is used.&lt;br /&gt;
&lt;br /&gt;
==Examples==&lt;br /&gt;
See the automated list of [[database tables]] for examples. Note the displayed format is not exactly the same as the recommended table definition format in all cases (e.g., the use of 'serial' and references).&lt;br /&gt;
&lt;br /&gt;
====Reference table====&lt;br /&gt;
The ageunits table is an example of a simple reference table:&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE ageunits (&lt;br /&gt;
   id serial PRIMARY KEY,&lt;br /&gt;
   '''code character varying NOT NULL,'''&lt;br /&gt;
   '''name character varying[] NOT NULL,'''&lt;br /&gt;
   createdby integer NOT NULL REFERENCES users,&lt;br /&gt;
   createdon timestamp NOT NULL DEFAULT now(),&lt;br /&gt;
   modifiedby integer REFERENCES users,&lt;br /&gt;
   modifiedon timestamp without time zone,&lt;br /&gt;
   del boolean NOT NULL DEFAULT false&lt;br /&gt;
 );&lt;br /&gt;
&lt;br /&gt;
Standard names for reference table fields include:&lt;br /&gt;
* name - an array of type character varying. This is used to display the Indonesian name [1] and English name [2]&lt;br /&gt;
* code - character varying. A short abbreviation such as may be used in SMS messages.&lt;br /&gt;
* hiercode - character varying. Numbers in the form 3.4.2.3 representing a hierarchical coding system. As an example&lt;br /&gt;
&lt;br /&gt;
{{#apGetSQL:&lt;br /&gt;
select hiercode, code, &lt;br /&gt;
format('%s%s',&lt;br /&gt;
  repeat('&amp;amp;nbsp;',(array_length(regexp_split_to_array(hiercode,'\.'),1)-1)*2),name[2])&lt;br /&gt;
from specimentypes order by regexp_split_to_array(hiercode,'\.')|Hiercode,Code, Spesimen}}&lt;br /&gt;
&lt;br /&gt;
====Data tables====&lt;br /&gt;
An example of a data table (animals in laboratory submissions) is shown below:&lt;br /&gt;
&lt;br /&gt;
 CREATE TABLE animals (&lt;br /&gt;
   id serial PRIMARY KEY,&lt;br /&gt;
   '''labsubmissionid integer REFERENCES labsubmissions,'''&lt;br /&gt;
   '''animalident character varying NOT NULL,'''&lt;br /&gt;
   '''ownerid integer REFERENCES owners,'''&lt;br /&gt;
   '''animalid bigint REFERENCES hewan,'''&lt;br /&gt;
   '''speciesid integer NOT NULL REFERENCES species,'''&lt;br /&gt;
   '''sexid integer REFERENCES sex,'''&lt;br /&gt;
   '''age double precision,'''&lt;br /&gt;
   '''ageunitsid integer REFERENCES ageunits,'''&lt;br /&gt;
   '''msgid bigint,'''&lt;br /&gt;
   createdby integer NOT NULL DEFAULT 1 REFERENCES users,&lt;br /&gt;
   createdon timestamp without time zone NOT NULL DEFAULT now(),&lt;br /&gt;
   modifiedby integer REFERENCES users,&lt;br /&gt;
   modifiedon timestamp without time zone,&lt;br /&gt;
   del boolean NOT NULL DEFAULT false&lt;br /&gt;
 );&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=IT:Servers&amp;diff=39420</id>
		<title>IT:Servers</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=IT:Servers&amp;diff=39420"/>
		<updated>2018-06-22T09:56:48Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages/&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
=Servers= &amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
The VPC is divided into two zones, which are hosted in different physical locations. Further, there are two subnets. The public subnet contains servers that (through the NAT) are able to be accessed from outside the VPC (web and messaging servers). The private subnet contains servers that can only be accessed from within the VPC (database, processing and reporting servers). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
All iSIKHNAS servers are listed here. They are identified by their location (zone 1 or zone 2, indicating the two physical locations), subnet (private or public), their [http://aws.amazon.com/ec2/instance-types  instance type] (indicating memory and CPU capacity) and whether they are autoscaling (elastic) or not. Load balancers are used to distribute requests to autoscaling servers.&lt;br /&gt;
&lt;br /&gt;
==Network Address Translation (NAT) server== &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
This is the only point of access to the VPC. It is a single instance (non-elastic) and is located in Zone 1, public subnet. Its sole role is to manage security and direct incoming traffic to the correct server in the VPC. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
Type: m1.small&lt;br /&gt;
&lt;br /&gt;
==Messaging server== &amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
This is in the public subnet of zone 1 and is a single instance. It is responsible for sending and receiving e-mail, managing the SMS system and managing Instant messaging. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
Type:m3.medium&lt;br /&gt;
&lt;br /&gt;
=====E-mail processing===== &amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
In addition to an email server, it uses email aliases to direct incoming email to the email parsing script (Python). This checks that the sender is authorised, and saves any Excel attachments to an S3 bucket (com.isikhnas.queuefiles). It then puts a message on the emailinput queue for processing by the processing server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
Outgoing email is managed by a Python daemon, listening on the emailoutput queue, and getting attachments from the com.isikhnas.emailattachments bucket.&lt;br /&gt;
&lt;br /&gt;
=====SMS processing=====  &amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
SMS messages are managed by SMSTools3. Incoming messages are parsed and submitted to the master database, which is then checked for any response messages.&lt;br /&gt;
&lt;br /&gt;
=====Instant messaging===== &amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
IM is managed by a Python daemon which listens for incoming messages, submits them to the database, and checks for outgoing responses in the same way as the SMS sytem. &lt;br /&gt;
In addition, if an incoming message contains a link to an image, the image is saved to an S3 bucket (static.isikhnas.com/images), and the message is recoded as an IMAGE message to store the file name and attach it to a case record.&lt;br /&gt;
&lt;br /&gt;
==Processing server== &amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
This is an elastic instance located in the private subnet. The main instance is located in Zone 1, but elastic instances are created so as to balance the numbers between zones 1 and 2. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
This server processes incoming email Excel attachments, parsing their contents and inserting them into the database. It gets request from the emailinput queue, and gets attachments from the com.isikhnas.queuefiles bucket. Once processed, it puts request to send email responses on the emailoutput queue, and any attachments for the email in the com.isikhnas.emailattachments bucket. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
This server has a Python daemon listening for messages on the emailinput queue.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
Type: m3.medium&lt;br /&gt;
&lt;br /&gt;
==Reporting server== &amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
This is an elastic instance located in the private subnet. The main instance is located in Zone 1, but elastic instances are created so as to balance the numbers between zones 1 and 2. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
This server generates output reports, including regular e-mail reports (daily, weekly, monthly), and ad hoc reports based on templates (for example client reports after laboratory submissions).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
Regular reports are generated by a Python script triggered by a cron job. Ad hoc reports are produced by a daemon listing on the reportrequest queue. Completed reports are stored in the reports.isikhnas.com S3 bucket and email request placed on the outgoing email queue.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
Type: m3.medium&lt;br /&gt;
&lt;br /&gt;
==Web servers== &amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
These are elastic instance located in the public submit. The main instance is located in Zone 1, but elastic instances are created so as to balance the numbers between zones 1 and 2.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
These servers provide the iSIKHNAS web site.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
Type: m3.medium&lt;br /&gt;
&lt;br /&gt;
==Database servers== &amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
=====Master database server=====&lt;br /&gt;
There is a single instance of the master database server located in the private subnet of zone 1. This handles all database requests that require writing of data, and is accessible only from within the VPC. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:23--&amp;gt;&lt;br /&gt;
Type: m3.medium&lt;br /&gt;
&lt;br /&gt;
=====Slave (read-replicate) database servers===== &amp;lt;!--T:24--&amp;gt;&lt;br /&gt;
This is an elastic group of servers in the private subnet, balanced bewteen zones 1 and 2. These servers play a triple role:&lt;br /&gt;
* real time backup&lt;br /&gt;
* automated promotion to master in case of failure&lt;br /&gt;
* read-access&lt;br /&gt;
** any reporting or analysis process that requires only read access to the database is directed to one of the read-replicas. This minimises load on the master database to maximise performance. This is necessary as some of the output reports require extensive and complex database processing, which would otherwise slow down the master database for other requests.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:25--&amp;gt;&lt;br /&gt;
Type: m3.large&lt;br /&gt;
&lt;br /&gt;
==Training server== &amp;lt;!--T:26--&amp;gt;&lt;br /&gt;
The training server (Sidecar) is completely independent from the VPC, and contains a duplicate database, web site and SMS messaging system. The database is automatically updated from the live database every Monday morning, and updates to the user and infrastructure tables (only) on the live server are instantly copied to Sidecar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:27--&amp;gt;&lt;br /&gt;
Email and Instant messaging requests for the training server are handled by the messaging server, which direct the requests to the Sidecar database. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:28--&amp;gt;&lt;br /&gt;
Type: m3.medium&lt;br /&gt;
&lt;br /&gt;
==Wiki server== &amp;lt;!--T:29--&amp;gt;&lt;br /&gt;
This is a self-contained documentation server located in the VPC public subnet in zone 1. It runs MediaWiki and a MySQL database. To increase performance during CPU intensive processes (particularly when exporting content to ODT or PDF format), there is a separate Wiki rendering server dedicated to that role.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:30--&amp;gt;&lt;br /&gt;
Type: m3.medium and T2.small (renderer)&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=Overview&amp;diff=39419</id>
		<title>Overview</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=Overview&amp;diff=39419"/>
		<updated>2018-06-22T09:49:52Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages/&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=iSIKHNAS Server Infrastructure= &amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
iSIKHNAS is hosted in a Virtual Private Cloud (VPC) on Amazon Web Services (AWS) cloud servers. The VPC consists of a number of different components (servers, queues, storage) that expand and contract according to need.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
[[File:cloudoverview.png|800px|centre]]&lt;br /&gt;
&lt;br /&gt;
==Security== &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
=====Access security=====&lt;br /&gt;
The Virtual Private Cloud allows computers within the cloud to communicate between themselves rapidly and easily, while blocking all access from outside the VPC. Access is controlled by a single, highly secure NAT server. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
All communications with iSIKHNAS are encrypted using secure industry standard Transport Layer Security (TLS) encryption, preventing interception of any data exchanged between the user and the VPC. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
Administrative access through the NAT server is controlled using digital certificates.&lt;br /&gt;
&lt;br /&gt;
=====Data security and redundancy===== &amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
The iSIKHNAS database runs on a single master database, with multiple slave databases providing real-time replication. Some of the slaves are always in a different physical location to the master. In case of failure of the master, one of the slaves is automatically promoted to be the master, resulting in down-time of only a few seconds. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
In addition to database replication, the full system is automatically backed up every 12 hours and stored in replicated off-site storage. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
The VPC is spread across two security zones, representing different physical locations, with servers and queues replicated in each zone. This means that should there be a catastrophic failure of an entire data centre, the system will continue to run uninterrupted.&lt;br /&gt;
&lt;br /&gt;
==[[IT:Servers|Servers]]== &amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
The VPC consists of a number of different servers dedicated to different tasks:&lt;br /&gt;
* NAT (for controlling access to the VPC)&lt;br /&gt;
* Database (master and read-replica slave servers)&lt;br /&gt;
* Web servers (for hosting the web site)&lt;br /&gt;
* Messaging server (for managing SMS, IM and email)&lt;br /&gt;
* Processing (for processing incoming requests on email)&lt;br /&gt;
* Reporting (for analysing data and generating outputs)&lt;br /&gt;
* Wiki (for managing this Wiki server)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
While some of these servers are single fixed instances, others are Elastic Cloud Computing (EC2) instances. This means that, as demand increases, the server is automatically replicated to increase capacity. As demand decreases, servers no longer in use are shut down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
All servers use the Ubuntu operating system, with open source and custom built software configured to optimise the performance of their particular tasks.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
[[IT:Servers|More details...]]&lt;br /&gt;
&lt;br /&gt;
==[[IT:Storage|Storage]]== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
AWS S3 storage buckets are used to provide rapid access to unlimited storage for both temporary and static data. The content of each bucket is automatically replicated and stored in three different physical locations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
[[IT:Storage|More details...]]&lt;br /&gt;
&lt;br /&gt;
==[[IT:Queues|Queues]]== &amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
The AWS Simple Queue System (SQS) is used to manage the exchange of tasks between the different servers in the VPC. For example, an incoming email is analysed by the messaging server, and then put in the processing queue. The processing server then gets the request from the queue and processes it. Once finished, if there is a response email to send, a request is put on the outgoing email queue, and if there is a report to be generated, a request is put on the reporting queue, to be picked up by the next available report server. &lt;br /&gt;
This approach, known as 'loose coupling', allows complex and processor-intensive tasks to be shared between a cluster of different servers, increasing speed and redundancy.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
[[IT:Queues|More details...]]&lt;br /&gt;
&lt;br /&gt;
==Daemons== &amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
In order to respond to various system events, a number of daemons have been created. These are small programs that are running full time in the background, waiting for a job. When an event occurs (such as a new IM message, or a message is available on a queue that the daemon serves), the daemon processes that message, and continues to wait. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
iSIKHNAS daemons are written in Python, and controlled with the Linux '''upstart''' tool, which manages starting, stopping, and automatically re-starting the daemon in case of failure. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
Daemons include:&lt;br /&gt;
* Processor for incoming email&lt;br /&gt;
* Report processor&lt;br /&gt;
* Instant messaging system&lt;br /&gt;
* E-mail sender&lt;br /&gt;
&lt;br /&gt;
==Technologies== &amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
iSIKHNAS uses a range of AWS technologies to maximise robustness, performance, security and flexibility. These include:&lt;br /&gt;
* EC2 (Elastic cloud computing for cost-effective response to demand)&lt;br /&gt;
* Route 53 (scalable domain name system)&lt;br /&gt;
* VPC (Virtual private cloud, for security)&lt;br /&gt;
* S3 (Scalable storage)&lt;br /&gt;
* IAM (secure access control)&lt;br /&gt;
* SES (e-mail sending service)&lt;br /&gt;
* SQS (messaging queue service)&lt;br /&gt;
* CloudFront (cached content delivery for increased speed and efficiency)&lt;br /&gt;
&lt;br /&gt;
==Software== &amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
iSIKHNAS uses a range of open source and custom-built software, on Ubuntu servers.&lt;br /&gt;
The main tools used are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
* Apache2 web server&lt;br /&gt;
* PostgreSQL database server, with the PostGIS extension&lt;br /&gt;
* Python programming language&lt;br /&gt;
* PHP and the Yii framework for web page delivery&lt;br /&gt;
* MediaWiki for the Wiki&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=Overview&amp;diff=39418</id>
		<title>Overview</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=Overview&amp;diff=39418"/>
		<updated>2018-06-22T09:47:21Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages/&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=iSIKHNAS Server Infrastructure= &amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
iSIKHNAS is hosted in a Virtual Private Cloud (VPC) on Amazon Web Services (AWS) cloud servers. The VPC consists of a number of different components (servers, queues, storage) that expand and contract according to need.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:2--&amp;gt;&lt;br /&gt;
[[File:cloudoverview.png|800px|centre]]&lt;br /&gt;
&lt;br /&gt;
==Security== &amp;lt;!--T:3--&amp;gt;&lt;br /&gt;
=====Access security=====&lt;br /&gt;
The Virtual Private Cloud allows computers within the cloud to communicate between themselves rapidly and easily, while blocking all access from outside the VPC. Access is controlled by a single, highly secure NAT server. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:4--&amp;gt;&lt;br /&gt;
All communications with iSIKHNAS are encrypted using secure industry standard Transport Layer Security (TLS) encryption, preventing interception of any data exchanged between the user and the VPC. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:5--&amp;gt;&lt;br /&gt;
Administrative access through the NAT server is controlled using digital certificates.&lt;br /&gt;
&lt;br /&gt;
=====Data security and redundancy===== &amp;lt;!--T:6--&amp;gt;&lt;br /&gt;
The iSIKHNAS database runs on a single master database, with multiple slave databases providing real-time replication. Some of the slaves are always in a different physical location to the master. In case of failure of the master, one of the slaves is automatically promoted to be the master, resulting in down-time of only a few seconds. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:7--&amp;gt;&lt;br /&gt;
In addition to database replication, the full system is automatically backed up every 12 hours and stored in replicated off-site storage. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:8--&amp;gt;&lt;br /&gt;
The VPC is spread across two security zones, representing different physical locations, with servers and queues replicated in each zone. This means that should there be a catastrophic failure of an entire data centre, the system will continue to run uninterrupted.&lt;br /&gt;
&lt;br /&gt;
==[[IT:Servers|Servers]]== &amp;lt;!--T:9--&amp;gt;&lt;br /&gt;
The VPC consists of a number of different servers dedicated to different tasks:&lt;br /&gt;
* NAT (for controlling access to the VPC)&lt;br /&gt;
* Database (master and read-replica slave servers)&lt;br /&gt;
* Web servers (for hosting the web site)&lt;br /&gt;
* Messaging server (for managing SMS, IM and email)&lt;br /&gt;
* Processing (for processing incoming requests on email)&lt;br /&gt;
* Reporting (for analysing data and generating outputs)&lt;br /&gt;
* Wiki (for managing this Wiki server)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:10--&amp;gt;&lt;br /&gt;
While some of these servers are single fixed instances, others are Elastic Cloud Computing (EC2) instances. This means that, as demand increases, the server is automatically replicated to increase capacity. As demand decreases, servers no longer in use are shut down.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:11--&amp;gt;&lt;br /&gt;
All servers use the Ubuntu operating system, with open source and custom built software configured to optimise the performance of their particular tasks.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:12--&amp;gt;&lt;br /&gt;
[[IT:Servers|More details...]]&lt;br /&gt;
&lt;br /&gt;
==[[IT:Storage|Storage]]== &amp;lt;!--T:13--&amp;gt;&lt;br /&gt;
AWS S3 storage buckets are used to provide rapid access to unlimited storage for both temporary and static data. The content of each bucket is automatically replicated and stored in three different physical locations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:14--&amp;gt;&lt;br /&gt;
[[IT:Storage|More details...]]&lt;br /&gt;
&lt;br /&gt;
==[[IT:Queues|Queues]]== &amp;lt;!--T:15--&amp;gt;&lt;br /&gt;
The AWS Simple Queue System (SQS) is used to manage the exchange of tasks between the different servers in the VPC. For example, an incoming email is analysed by the messaging server, and then put in the processing queue. The processing server then gets the request from the queue and processes it. Once finished, if there is a response email to send, a request is put on the outgoing email queue, and if there is a report to be generated, a request is put on the reporting queue, to be picked up by the next available report server. &lt;br /&gt;
This approach, known as 'loose coupling', allows complex and processor-intensive tasks to be shared between a cluster of different servers, increasing speed and redundancy.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:16--&amp;gt;&lt;br /&gt;
[[IT:Queues|More details...]]&lt;br /&gt;
&lt;br /&gt;
==Daemons== &amp;lt;!--T:17--&amp;gt;&lt;br /&gt;
In order to respond to various system events, a number of daemons have been created. These are small programs that are running full time in the background, waiting for a job. When an event occurs (such as a new IM message, or a message is available on a queue that the daemon serves), the daemon processes that message, and continues to wait. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:18--&amp;gt;&lt;br /&gt;
iSIKHNAS daemons are written in Python, and controlled with the Linux '''upstart''' tool, which manages starting, stopping, and automatically re-starting the daemon in case of failure. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:19--&amp;gt;&lt;br /&gt;
Daemons include:&lt;br /&gt;
* Processor for incoming email&lt;br /&gt;
* Report processor&lt;br /&gt;
* Instant messaging system&lt;br /&gt;
* E-mail sender&lt;br /&gt;
&lt;br /&gt;
==Technologies== &amp;lt;!--T:20--&amp;gt;&lt;br /&gt;
iSIKHNAS uses a range of AWS technologies to maximise robustness, performance, security and flexibility. These include:&lt;br /&gt;
* EC2 (Elastic cloud computing for cost-effective response to demand)&lt;br /&gt;
* Route 53 (scalable domain name system)&lt;br /&gt;
* VPC (Virtual private cloud, for security)&lt;br /&gt;
* S3 (Scalable storage)&lt;br /&gt;
* IAM (secure access control)&lt;br /&gt;
* SES (e-mail sending service)&lt;br /&gt;
* SQS (messaging queue service)&lt;br /&gt;
* CloudFront (cached content delivery for increased speed and efficiency)&lt;br /&gt;
&lt;br /&gt;
==Software== &amp;lt;!--T:21--&amp;gt;&lt;br /&gt;
iSIKHNAS uses a range of open source and custom-built software, on Ubuntu servers.&lt;br /&gt;
The main tools used are:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--T:22--&amp;gt;&lt;br /&gt;
* Apache2 web server&lt;br /&gt;
* PostgreSQL database server, with the PostGIS extension&lt;br /&gt;
* Python programming language&lt;br /&gt;
* PHP and the Yii framework for web page deliver&lt;br /&gt;
* MediaWiki for the Wiki&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.isikhnas.com/index.php?title=Overview_of_data_managed&amp;diff=39417</id>
		<title>Overview of data managed</title>
		<link rel="alternate" type="text/html" href="https://wiki.isikhnas.com/index.php?title=Overview_of_data_managed&amp;diff=39417"/>
		<updated>2018-06-22T09:25:05Z</updated>

		<summary type="html">&lt;p&gt;Jillhinchliffe: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;languages/&amp;gt;&lt;br /&gt;
&amp;lt;translate&amp;gt;&lt;br /&gt;
==Overview of data managed== &amp;lt;!--T:1--&amp;gt;&lt;br /&gt;
* [[Data overview: Field disease reporting|Field disease reporting]]&lt;br /&gt;
* [[Data overview: Laboratory data|Laboratory data]]&lt;br /&gt;
* [[Data overview: Slaughter statistics|Slaughter statistics]]&lt;br /&gt;
* [[Data overview: Livestock movement|Livestock movement]]&lt;br /&gt;
* [[Data overview: Population data|Population data]]&lt;br /&gt;
* [[Data overview: Vaccination programs|Vaccination programs]]&lt;br /&gt;
* [[Data overview: Active surveillance|Active surveillance]]&lt;br /&gt;
* [[Data overview: Animal identification|Animal identification]]&lt;br /&gt;
* [[Data overview: Breeding management|Breeding management]]&lt;br /&gt;
* Proposed future functionality&lt;br /&gt;
** Feed and feed supplies&lt;br /&gt;
** Meat inspections&lt;br /&gt;
** Antimicrobial Resistance monitoring&lt;br /&gt;
** Milk recording&lt;br /&gt;
** Drug registration management&lt;br /&gt;
&amp;lt;/translate&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jillhinchliffe</name></author>
		
	</entry>
</feed>