Products' program collection

Hi everyone,

Because of our business needs, we have made some modifications to the program design of openLMIS, but this has caused some conflicts after the openLMIS upgrade. Our team hopes to find a reasonable way to solve our current dilemma.

Business requirement

  • R&R report:
  1. Multiple Programs(PULL process, based on the requisition), requisition supports emergency reports
  2. malaria program (usage report), but its’ product will be requested by Multiple Programs.
  3. ARV && Rapid Test (PUSH process, based on usage report)
  4. Usage report does not support emergency reports, but authorize and approve processes are similar to requisition
  • stock management:
  1. Physical inventory needs to inventory all products.
  2. Stock management needs to manage all products.
  3. stock overview can be classified according to All products program, Multiple Programs, ARV Program, Rapid Test Program, and Malaria Program.
  4. User permissions are also used by category program for stock management and requisition.
  5. malaria’s virtual program is Multiple programs, but it belongs to a type shown in the stock overview and usage report

Current design:
In order to classify the statistics of the real program on the stock management page, R&R page, we add the concepts of all Product and virtual programs. all product can be understood as grandpa, he contains all virtual programs. The virtual program can be understood as the parents, it contains the real program. Virtual program and all product programs will be shown in the stock overview page and usage report page.But we have a special program : malaria program is a real program which virtual program is multiple programs, but it belongs to a type shown in the stock overview and usage report .
In order to meet the above requirements, the following related fields were added to the program table in DB:

  1. parentId: each real program belongs to a virtual program, which is easy to summarize according to the report and stock management program types in Mozambique.
  2. isSupportEmergency : emergency is allowed by specific program
  3. isVirtual: only the virtual program is displayed in the program list of stock management && requisition.
  4. isReport: admin can configure template only if isReport is true , Except the virtual program can be fulfilled , malaria can also be fulfilled in the usage report which belongs to the real program.

This table is the binding relationship between the stock management and program categories in our design.

database table Program Category
physical_inventories ALL Products porgram
physical_inventory_line_items virtual program
stock_cards virtual program
stock_events ALL Products porgram
valid_destination_assignments virtual program
valid_reason_assignments virtual program
valid_source_assignments virtual program

New Design:
In order to upgrade smoothly, our team gets the advice of the expert team: We will build a new customization layer on the code. Designed a new design:

  1. To make our structure clearer, we will remove the all product program. But in order to meet our needs for stock management of all products at the same time, we will wrap a new layer on top of the existing code. If it is all products, we will group products according to the virtual program and then call the original interface.

  2. For our newly added field isReport in the program table .isReport is determines which program will be displayed in the R & R report category. We will remove it. But the Malaria program is a special real program which needs to appear in the stock manage category and requisition report type and its medicine needs to be requested in the requisition of the multi-program. We will upgrade the malaria program to a virtual program that will have one malaria real program and all virtual programs will be displayed in categories so that we don’t have to add the isreport field. In order to requests the Malaria program in multi-program, we can add extra data to the requisition template, and add the associated program in it.

  3. Our newly added field isvirtual in the program table, we still need to add this field. In our system, we will use the virtual program, which will not cause great changes to our original system. We will use the virtual program as an openLmis real program collection, and the real program is just a sign of the virtual program. To meet Mozambique’s business requirements: first: a product can belong to multiple real programs and can only belong to one virtual program. second: the stock card will be bound to the virtual program.

Please everyone help us confirm our new design is reasonable. Or you have better suggestions, hope you can contact us.

Hey @jingzhao,

Thanks for bringing this to the attention of the community. Welcome!

So, I see that you are modifying the Program model by creating this idea of a “virtual program”. We need to be careful when making changes to our domain models because they have far-reaching effects throughout the system. Can you explain further the reasoning behind creating the concept of a virtual/parent program? Is it to simplify configuration of the system for administrators? Is it to improve the UI experience when doing tasks in the requisition and stock management workflows?

The reason I ask is because I am wondering if the design of a virtual program is necessary to satisfying the business requirements. Can these requirements be satisfied instead by additional logic to consolidate program-related data, or through customizing the UI to filter and consolidate programs?

However we decide to develop a design that will satisfy the business requirements, I recommend we go through a process that works with the community. I feel like there are three courses of action we can take here:

  1. For this work, create a new microservice and have it talk to other services it needs to (such as reference data, requisition, stock management) through their (predictably changing) APIs. This can be potentially the quickest path, as it does not require coordination with the Core team to implement extension interfaces and wait for a patch release. There are some guidelines in the docs (, and a template is provided at I know some developers (@mkwiatkowski @Aleksandra_Soltys) have already recently created a new microservice, requisition batching, for the SELV v3 upgrade, so hopefully they can be resource on how to do this.
  2. For this work, if the amount to extend seems small enough not to warrant creating a new microservice, you can identify where you would need extension points and ask the Core team/Tech Committee to implement extension interfaces. Additionally, if this new logic requires storing some data for state, you can extend some models using an extraData property, which would be structured json data, on a model. Note, this would require coordination and waiting for those interfaces to be implemented (and released in a patch before production rollout). There is an example repository ( that shows how that could potentially look.
  3. If you feel this work is globally applicable and would like to make changes to code in the Core software that would be merged back into the codebase as a pull request, it is possible, but you would need to get buy-in from the Product Committee for the new features, and from the community/Tech Committee on the design of it. This requires coordination as well, to create a path forward for these changes to eventually become part of the Core software. As for the proposed design, I do not think that the concept of a virtual program, with its proposed properties here, would be a design that is accepted, as it muddies the concept of programs, potentially creating issues in the future.

One thing we are trying to avoid is forking the OpenLMIS codebase and making changes to microservices directly without involvement in the community. This is because when it comes time to upgrade the system, and gain the benefits of future releases, conflicts arise, as you have already encountered. This can be avoided by pursuing one of the options I have mentioned above.

I know the current topic is this design of programs, but I recommend that you think about the above options for any design/development you are doing for OpenLMIS. The community welcomes your questions and proposals for discussion, so please keep posting them.


Hi @Chongsun_Ahn, Thank you for taking the time and effort on this topic.

The concept of “virtual program” is necessary for our current business design. For our current data, a product can belong to multiple real programs and can only belong to one virtual program. If there is no concept of “virtual program”, we directly associate the stock card with the program. I can give an example:

  • product 1 belongs to A program.
  • product 1 also belongs to the B program.
  • Both A program and B program belong to the multi-aggregation class.

According to Mozambique’s needs, the user operates on product 1 on the stock manage page. We don’t know which program is operated. On the stock overview page, it is classified according to the multi-category. The user wants to see only one product 1 in the multi-category.

Based on the advice that you provide, “create a new microservice and have it talk to other services” is a good idea, we can put the virtual program relationship and business logic to the new service, this can make our upgrade more smoothly.:grinning:

Hey @jingzhao, thanks for the response.

Is the main reason for the virtual program, being able to manage all stock, not just stock associated with a specific program? Are there other business requirements that are met with this virtual program design? I will do a bit of research to determine if there is another way to manage all stock of a product without having to set up programs this way.


Hey @Chongsun_Ahn, thanks again for your support.
Yes, The relationship between product and virtual program and the relationship between product and real program are the major reasons for our current design.

If we can manage our stock management without setting up a virtual program, it will be very helpful for simplifying our design.

After we solve the main reasons, we can further discuss the following business requirement :

  1. For admin users, users directly configure the virtual program, which can greatly simplify the user’s configuration.
  2. The requisition needs associating with the virtual programs and manage virtual programs’ products.

Hi @jingzhao, building on @Chongsun_Ahn’s guidance and questions. I’d also ask how these concepts of “virtual program” or “multiple program” relate back to basic supply chain operations:

  • Program background: A program reflects how most supply chains operate in-country where the program has people, processes, and re-supply periods for managing the supplies in that program. A classic example of a difference between programs is how a family planning program is managed as opposed to a vaccine program. To oversimplify the family planning program might have longer re-supply times, less need for cold chain equipment, and different funders, than the vaccines program that is going to be highly reliant on an effective cold-chain and quicker re-supplies to help ensure populations are at herd-immunity.
  • Tracking stock, and by extension the requisition of more stock, per-program is important in supporting the above. A “virtual program” to me makes it confusing. We do expect for a product to be in two Programs, however we also expect then that you’ll count the Product by Program when you count. If I don’t count by program how will I know how much that Program will need to resupply via that Program? If I don’t know what I used and for what, then how can I forecast what the Program will need to forecast?

The last thing I’ll note is that in the technical gap report for SIGLUS we gave no option to create virtual Programs. Rather we stressed the importance above - that in-order to forecast what you need or understand what you use in a Program, you must do stock management and resupply at the Program level (no virtual or multi). There could be an exception to that, and that’s if Mozambique wanted to do Program management differently at the lowest levels of the system than at the intermediate and higher levels, however I haven’t seen that stated by anyone yet.

I’d really like to hear more about the business/process/supply chain need here. The clearer that we can state this in supply chain terms, rather than software terms, the clearer our guidance will be.