Skip to content

De Zorggroep health index filter ​

De Zorggroep is where this filter started. Any store with an AFAS integration and show_health_index_organizational_unit_filter now gets the same filter (GetOrganizationalUnitFilterAndOptions). It represents the company hierarchy. When a unit is selected, employees in that unit and any unit below it are included. If a unit has fewer than minimum_health_index_participants people (default 25), the results are masked.

A high-level overview of their hierarchy:

An example of a filter they use internally:

The health index started with store employee questions for these filters. A new type of filter was needed because this data comes from a third-party API and has to be processed before it fits our structure.

Similar to store questions, it consists of:

  • A filter
    • \Domain\StoreEmployeeFilters\Models\StoreEmployeeFilter model
    • store_employee_filters table
    • Belongs to a store
  • Filter options
    • \Domain\StoreEmployeeFilters\Models\StoreEmployeeFilterOption model
    • store_employee_filter_options table
    • Belongs to a filter
    • Has a label, a value to filter on, and optional schemaless properties
  • Selected filter options (the filter options chosen by employees)
    • \Domain\StoreEmployeeFilters\Models\StoreEmployeeSelectedFilterOption model
    • store_employee_selected_filter_options pivot table
    • Belongs to a store employee (one can have many selected options)
    • Belongs to a filter option
    • A pivot table is used because it is easy to sync models. A HasOne or BelongsTo relation does not have a sync method.

Preparing the data ​

SynchronizeAllAfasIntegrationFeatures runs at 04:00 and 16:00 Amsterdam (routes/console.php). Per integration that becomes SynchronizeAfasIntegrationOrganizationalUnitHealthIndexFilter, which runs CreateOrUpdateAfasOrganizationalUnitFilterForStore, RecreateAfasOrganizationalUnitsAsFilterOptions, and LinkStoreEmployeesToAfasOrganizationalUnitsUsingFilterOptions.

Constructing the hierarchy ​

RecreateAfasOrganizationalUnitsAsFilterOptions gets the hierarchy from the AFAS API, transforms it, and stores it as filter options.

Saloon represents the API (AfasApiConnector, GetOrganizationalUnitsAfasApiRequest). Units map to AfasOrganizationalUnitData / AfasNormalizedOrganizationalUnitData. Fixtures live in tests/assets/afas/. Recreate uses per-unit updateOrCreate.

Linking employees to organizational units ​

Each employee is placed in an organizational unit by creating selected filter options that link a filter option to an employee.

Employee number is stored on the store employee when they first log in via SSO.

LinkStoreEmployeesToAfasOrganizationalUnitsUsingFilterOptions loads placement with GetEmployeesAfasApiRequest into AfasEmployeeData. It dumps all employees (a filtered URL is too long) and walks them in chunks of 500. For each employee it finds the store employee by employee_number and attaches selected filter options for that unit and every parent unit. The health index can then filter with a simple selected-option query.