Domain Modeling Technical Deep Dive

Post-meeting, in early April 2016, some additional domain model whiteboarding was done.






Receiving Shipping

To us, "Receiving" doesn't make sense as its own context. Either it is the tail end of the "Fulfilling" context, or else it should be thought of as a broader "Shipping" context.


Inventory Management


  • Get all balances at one facility (by batch?)
  • Record and process a Stock Event
    • issue, receipt, adjustment (delta or absolute), transfer?
  • Get stock card + line details (for one product at one warehouse)
  • (something like) Tell me what happened to the stock that I sent out to facilities last period
  • What items are included in this kit?
  • What products are substitutable for this product?

Different types of facilities?

  • National-level Central Receiving
    • typically receives international shipments
    • may even include tracking shipment through customs
      • This is in VIMS
      • Most important for vaccines (e.g. need to track VVM while going through customs)
      • Don't know if this is in scope for OpenLMIS Product
    • maybe >1 per country
    • tracking inventory at this level is probably not a short-term priority
      • but necessary if we want to support forecasting
      • maybe necessary for vaccine workflow too
  • National/Provincial/State Storage
    • Usually 1 (per country/province/state)
    • Distribute to lower levels (e.g. district)
    • For most countries, batches are tracked at this level
    • Big warehouse with multiple rooms, shelves, maybe multiple cold rooms, etc
    • Sometimes this level will already have its own electronic inventory system
    • Sometimes they will want to use OpenLMIS for inventory management at this level
      • But OpenLMIS doesn't want to track warehouse management (e.g. which room, which shelf)
  • "District" Storage
    • sitting in a major city somewhere
    • probably doesn't have a cold room, but has multiple fridges
    • need to provide to different programs
    • Distribute to SDPs
    • Maybe keeps extra stock on hand to cover shortages in facilities that depend on it
    • Maybe acts as a care-providing facility itself
    • Unlikely to have own electronic inventory system level already 
    • Probably want to use OpenLMIS for inventory management at this level
  • SDP (Service Delivery Point)
    • Smaller
      • just a single room +/- a fridge
      • Unlikely to have internet, regular electricity
      • Unlikely to accurately track batch numbers
      • It's important to know what was sent to this level (including batches), but at the programmatic level you may not care what happens after that
        • vaccine program people care more
        • higher levels wants to avoid stock-outs at SDPs, so they may care about total stock quantities, overall consumption, upcoming expiration, etc.
    • Larger
      • hospital with multiple wards, multiple stock points within the hospital
  • Mobile outreach program
    • Usually goes out from a facility
  • Individual health worker
    • (out of scope to track at this level?)

(Darius's opinion) In the long run, OpenLMIS will need to tie together different facilities some using third-party inventory management systems, and having different levels of required accuracy and precision; our challenge is not to write code to cover every possible case, but to allow the variations to communicate the necessary information within the OpenLMIS workflows.

The real purpose of OpenLMIS is the workflow and process of the demand and supply cycle; inventory management is supportive of this, but is not the end goal of OpenLMIS. (Jake: actually this is more true today, but it won't always be true.)

Interfaces Between Bounded Contexts

Requisition Service

  • Query to Inventory Management system for stock on hand, and beginning balance (as an input to "Requisition Advice")
    • InventoryManagement.getStockDetails(Product, Facility)
    • InventoryManagement.getStockDetailsAtHistoricDate(Product, Facility, Date)
  • Query to Inventory Management system for "what was my facility's past consumption" (e.g. period-normalized consumption based on last period). if no Inventory Management system, this will be manually entered as part of the requisition
    • InventoryManagement.getConsumption(ProductFacility, Period)
    • need similar methods for Adjustments, etc.
  • Query to itself for numbers from last month's requisition
    • RequisitionService.getRequisition(Facility, Period, Program)
  • Query Program Data service to verify if all required data has been captured
    • (no new shared reference data)
  • Query (something) for my facility's budget for this program and period
    • (Facility, Program, Period)
  • Query Product Service(?) for catalog of Requestables and their type for my facility + program + period (with full-supply vs non-full-supply details)
    • Program, Period, Facility => Requestable
  • Query (something) for unit prices of the Requestables
    • Program, Period, Requestable => (Currency)
  • Use Fulfillment Service to create a new Order based on a Requisition
    • Order
      • Requestable, from Facility, to Facility, Program, Period
  • (future) Use Notification Service to notify X that Y event happened


  • Submit an order to external ERP
  • (maybe) Query Requisition Service for full details of the requisition that led to this order
    • Requisition.getRequisition(id) => Requisition
  • Query to Inventory Management system for available stock
    • InventoryManagement.getStockAvailable(ProductFacility) (maybe stock is separated out by Program)
    • (maybe) getProductsThatCouldSatisfy(Requestable) => Product(?) aka Orderable/Stockable
  • Use Inventory Management to reserve some stock (to be picked)
    • InventoryManagement.reserveStock(ProductFacility, Quantity) // maybe a StockEvent
  • Decrement Inventory (after picking)
    • InventoryManagement.processStockEvent(StockEvent, pointer to reservation)
      • StockEvent (Event Type, Facility, Product, Batch/Lot, Quantity)
  • Create Shipments
    • Shipment.newShipment(from Facility, to Facility, Product/Stockable line item details)


  • Get product list
    • ProductService.getProductList(...)
  • Update stock
    • InventoryManagement.processStockEvent(StockEvent)
  • Do we need to update the Requisition Service with a status that a requisition was fulfilled?
  • Or update the Fulfillment Service with an "order received" status?

Inventory Management Service

  • Use Notification service to send alerts
  • (internal) Stock Movement service, same as processStockEvent(StockEvent)

Program Data Service

  • Call out to 3rd party data collection system to get data (e.g. Ona, ODK Aggregate, DHIS2, etc)

Product Service

Notification Service