DEV Community

Isaac Mwendwa Muthui
Isaac Mwendwa Muthui

Posted on Originally published at factoraerp.com

Competence Is a Join, Not a Spreadsheet: Modelling Training Matrices, Certificate Expiry and Task Authorisation in a Food ERP

By Isaac Muthui, CEO, Tamalaki Business Network Ltd. Originally published at factoraerp.com.

Most HR systems store training as a list of events: a course name, a date and a list of attendees. That is fine for payroll and leave. It breaks the moment a production supervisor asks the question that actually matters in a food factory at 6 am: is the person I have just put on the pasteuriser authorised to run that CCP, and is their medical certificate still valid?

Answering that is not a lookup. It is a join across roles, tasks, required training, assessments, certificates with expiry dates and the shift roster. This post walks through how we think about modelling food safety training and task authorisation in an ERP for food and agro manufacturers in East Africa. The operational checklist behind it is in the original article.

What the domain rules say

The requirements read like a spec:

  • Codex CXC 1-1969 (section 10): everyone in contact with food needs "competence appropriate to the operations they are to perform"; "periodic assessments of the effectiveness of training and instruction programmes should be made"; "records should be kept of training activities". For HACCP (19.13), working instructions should define "the tasks of the operating personnel in charge of each CCP", and "re-training may be needed as part of corrective actions for some deviations". Source
  • EAS 39:2001 (5.3): all staff, including management, get "induction and on going training in hygiene", delivered by competent personnel, and "training records shall be kept". Source
  • Kenya Food Hygiene Regulations (reg 15): staff who identify sanitation failures must be "properly trained"; medical examination before employment and at intervals of not more than twelve months, with certificates kept at the plant. Source
  • Kenya OSHA 2007 (s.99): training on recruitment, transfer or change of job, new equipment or materials and new technology, "repeated periodically". Source
  • 21 CFR 117.4 (US benchmark): training applies to everyone "including temporary and seasonal personnel", and training records "must be established and maintained". Source

Translated: training requirements hang off roles and tasks, not people; completion is not the same as competence; some certificates expire; certain events (job change, new equipment, a deviation) create new training obligations; and casual workers are in scope from day one.

The core entities

Role              (id, name)
Task              (id, name, is_ccp, ccp_id, required_certificate)
RoleTask          (role_id, task_id)
TrainingItem      (id, name, procedure_id, procedure_version,
                   refresh_interval_days, required_before_unsupervised)
TaskTraining      (task_id, training_item_id)
Person            (id, kind, role_id)          -- kind: employee | casual | contractor
TrainingSession   (id, training_item_id, trainer_id, held_on, procedure_version)
Assessment        (id, person_id, training_item_id, session_id,
                   method, assessor_id, assessed_on, result)   -- observed | oral | practical
Certificate       (id, person_id, type, issued_on, expires_on, document_ref)
TrainingTrigger   (id, person_id, training_item_id, reason, source_ref, due_on)
RosterSlot        (id, shift_id, task_id, person_id)
Enter fullscreen mode Exit fullscreen mode

A few design choices matter more than the table list.

1. Requirements attach to tasks, not to people

A person needs training because of what they do. Model Task -> TaskTraining -> TrainingItem and derive each person's requirements from their role and rostered tasks. When someone moves from packing to the filler, their requirements change automatically, which is exactly the OSHA "change of job" trigger.

2. Attendance and competence are different rows

A TrainingSession records that something was taught. An Assessment records that a specific person was observed doing the task and passed. Authorisation comes only from a passing assessment, never from attendance alone. This is the whole point of the article in one constraint.

3. Pin the procedure version

Store the procedure version on both the session and the assessment. When a CCP work instruction is revised, every assessment against the old version becomes "needs refresh". Without this, a factory can show that everyone was trained, just not on the procedure currently in force.

4. Authorisation is a derived view

-- People currently authorised for a task (simplified)
SELECT p.id
FROM person p
WHERE NOT EXISTS (
  SELECT 1 FROM task_training tt
  JOIN training_item ti ON ti.id = tt.training_item_id
  WHERE tt.task_id = :task
    AND NOT EXISTS (
      SELECT 1 FROM assessment a
      WHERE a.person_id = p.id
        AND a.training_item_id = ti.id
        AND a.result = 'pass'
        AND a.procedure_version = ti.procedure_version
        AND (ti.refresh_interval_days IS NULL
             OR a.assessed_on >= current_date - ti.refresh_interval_days)))
AND NOT EXISTS (
  SELECT 1 FROM task t
  WHERE t.id = :task AND t.required_certificate IS NOT NULL
    AND NOT EXISTS (
      SELECT 1 FROM certificate c
      WHERE c.person_id = p.id AND c.type = t.required_certificate
        AND c.expires_on >= current_date));
Enter fullscreen mode Exit fullscreen mode

Never store an "authorised" flag that someone has to remember to untick. Derive it.

5. Warn at rostering time, block where it matters

Check authorisation when a person is assigned to a roster slot or production task. For most tasks a visible warning is enough. For CCP tasks, a plant may choose to block the assignment outright. In FactoraERP, production task types can name a certificate the person should hold, and the system shows a warning when someone without a valid certificate is assigned; employee and casual worker documents (including medical and food handler certificates) carry expiry dates.

6. Events create training obligations

New equipment, a revised procedure, a job change or a non-conformance whose root cause was a skill gap should insert a TrainingTrigger row with a due date. That turns "operator retrained" from a phrase in a corrective action into a tracked obligation that is closed by an assessment.

7. Casuals are first-class people

Seasonal and casual workers are often kept in a separate spreadsheet, which is exactly where gaps hide. Model them as Person with kind = casual so the same authorisation view applies on their first day.

What this buys you

  • Before each shift: rostered people not authorised for their task.
  • Certificates expiring in the next 30 days.
  • Assessments made against superseded procedure versions.
  • Open training triggers past their due date, by source (deviation, change, refresher).
  • Deviations by person and task, joined to their training status at the time.

None of this is exotic. It is a dozen tables and one derived view. The hard part is deciding that training is about tasks and competence, not courses and attendance.

FactoraERP is an ERP for food and agro manufacturers in East Africa, built by Tamalaki Business Network Ltd. Full checklist: Food Safety Training Checklist.

Top comments (0)