Building Apps for CommCare Supply
Introduction
Before starting to build your Supply application there are a few concept you must familiarize yourself with:
In this document:
Loading data from a ledger
Why?
- To read data previously saved into a ledger
Here is the calculate expression:
coalesce(instance('ledger')/ledgerdb/ledger[@entity-id=case_id]/section[@section-id='balance']/entry[@id=current()/../@id], 0)
instance('commcaresession')/session/data/case_id
Let’s break this down:
coalesce([big scary ledger reference], 0)
just says use the leger reference, and if you don’t find a value, use 0.
This is in case it is the first time filling in a form that touches that value.
Looking at the ledger reference
instance('ledger')/ledgerdb/ledger[@entity-id=case_id]/section[@section-id='balance']/entry[@id=current()/../@id]
case_id: put here the id of the case where you want to get your ledger from. For example instance('commcaresession')/session/data/case_id = the current case ID.
So instance('ledger')/ledgerdb/ledger[@entity-id=instance('commcaresession')/session/data/case_id]
Says grab the ledger for this case
/section[@section-id='balance']
Says grab the section called “balance” (this corresponds to the “balance ID”). You could use here 'stock', 'consumption' ...
/entry[@id=current()/../@id]
Says grab the entry value with the ID of the current product
This is pretty scary expression. Feel free to ask for help with it, though it shouldn’t vary too much per form.
Setting up organizations for supply chain
Organizations can be used to do case sharing and therefore allow supply-point cases and ledgers to be shared between users.
Furthermore using organization levels will allow the configuration of different use cases such as stock management flow at different facility level or supervisor/field worker.
In the organization level page, after defining the structure of your organizations there are several options you need to set. Here they are:
- Tracks Stock: allow the organization to track stock, i.e. define ledgers.
- Own Cases: allow the organization to own the case data, i.e. all the cases saved by the user will be owned by the organization:
- all users linked to the same location will be able to see the cases of this organization (same location case-sharing)
- all users linked to a parent location, with the parameter "view child data" activated, will be able to see the cases of this organization (parent child case-sharing)
- View Child Data: allow the organization to see the case data of its child organizations
In the example below we have the following structure: departement > zs > commune > arrondissement > as > village_admin > village.
We follow stocks at 2 different levels:
- as linked to a supervisor
- Tracks Stock: will allow to track stock at as level.
- View Child Data: will allow to the supervisors at this level to see the data of all its children in the village level
- village linked to a field worker:
- Tracks Stock: will allow to track stock at village level.
- Owns Cases: the village location will be the owner of the case data, allowing case sharing and parent locations to see the data.
With this setup the supervisor will be able to see his "child" user ledgers.
Supply-point case selection
Why?
Enable supervisor type of users to select any child supply-point to view and edit ledgers, or auto-select user own supply-point.
How?
First, you need to use the Advanced Module type. When creating your module, choose "New Advance Module"
- Your module settings > Case Management tab > Use the case type "supply-point"
- Your module settings > Product List tab > add the ledgers you want to display with the property "ledger:you_section_id"
- In your forms settings page > Case Management:
- Click on "Add Action"
- Select "Load / Update / Close a case"
- In the "Select case type" drop down, select "supply-point"
- In the "Case list" drop down, select your module
- On the bottom of the page click on "Display the Product Stock for this Supply Point after it is selected"
Now when a user go to the module case list, all the supply-point at his level and underneath will be displayed.
The user can therefore select a supply-point and access to a form to edit the ledgers of that supply-point, by using this expression for a case id: instance('commcaresession')/session/data/case_id_case_supply-point
Let's consider this organization hierarchy. The supervisor is connected to the organization supply_cp while 2 field workers are connected to supply_rc and supply_rc1:
When connected to the application the supervisor, the case list will display all the relevant supply points.
Here the supervisor own supply point and the 2 field workers underneath him.
Summing data across all products
This is standard app-builder stuff, and can be done using the sum() function.
Outside the repeat group do a sum of a question inside the repeat group.
For example: sum(/data/products/item/data_product_payment) will sum the values of each product data_product_payment.
PS: the additional hidden word “item” in the path that is inserted due to the model iteration structure.
How to refer to the product in a repeat? The use of current()
Referencing the ID of a product in the repeat can be tricky because it’s not obvious how many “../” expressions should be in the path.
This is a complicated question that involves understanding XML and XPath references, and particularly how they work in our tools.
However, you can use these general guidelines to help.
Question you are referencing | Way to reference |
Display of the repeat group itself | current()/@id |
Normal question directly in repeat | current()/../@id |
Normal question in a group inside repeat | current()/../../@id |
For each additional group inside repeat | add an additional ../ to the path |
The CommCare Supply transaction questions require special references. These are described below. These are all relative the a normal question in the same group, so additional “../” elements must be added to these paths when using the transaction questions inside groups.
Question you are referencing | Way to reference (assuming no groups) |
Product ID in a transfer question directly in repeat | current()/../../../@id |
Product ID in a balance question directly in repeat | current()/../../../@id |
For each additional group above the question | add an additional ../ to the path |