Menu
Work Request Data Model: Fields, Status and Triage

Work Request Data Model: Fields, Status and Triage

The maintenance work request as a record: header, requester and triage fields, nine statuses, rejection codes, and why the denominator moves your rate.
Work Request Data Model: Fields, Status and Triage

Key takeaways

  • A request is an ask and a work order is a commitment. One request can become zero work orders, one, or a line on a job that already exists.
  • Keep nine states, not two. Rejected, duplicate, merged and withdrawn are data, and a system that deletes them destroys the demand signal it was bought to measure.
  • The requester's urgency, the asset's criticality and the scheduler's final priority are three fields. On the line below they disagreed on 20 of 44 decided requests.
  • One month of 60 requests gives an approval rate of 60.0% or 81.8%, a gap of 21.8 percentage points, from nothing but which rows sit in the denominator.
  • Median time to screen, on the same rows, reads 6.0 hours across 58 screened requests and 10.0 hours across the 44 distinct ones.

A request is an ask, a work order is a commitment

A work request is somebody telling maintenance that something needs attention. Nothing has been promised, nobody has been assigned and no budget has moved.

A work order is the plant committing labour, parts and time to a named asset. It has an owner, a priority, a planned duration and a cost.

One request can become no work order at all, one work order, or a task added to a job that was already scheduled. Two requests can also converge on a single work order.

CaseWhat exists
Guard rattle reported, screener finds it within specRequest, no work order
Two shifts report the same leakTwo requests, one work order
Temporary fix now, full repair at the shutdownOne request, two work orders
Ask already covered by a planned jobRequest, an existing work order

What collapsing the two costs you

Collapse request and work order into one table and the rows that never became work have no key of their own. They get edited into work orders, or they get deleted.

On the month worked through below, 60 requests produced 31 conversions. A single-table system therefore shows 31 rows where 60 people asked for something.

That hides 29 requests, 48.3% of everything raised. The hidden half is the interesting half: the rejections, the duplicates and the asks that were never answered at all.

The reporting consequence is precise, and it is worth stating slowly. Your backlog report becomes a report about your own decisions rather than about the plant, because the only demand it can see is demand you already agreed to.

What this page covers that the others do not

The conceptual difference, argued with examples, belongs to our guide on work order vs work request. How the intake process runs day to day is covered in maintenance work request system.

What this page adds is the record itself: the fields, the nine statuses and their allowed transitions, rejection and duplicate handling, the response time definitions, and the join to the work orders that answer a request.

It does not re-specify the work order. That belongs to our production work order data model and the wider CMMS data model.

The request header, field by field

Twelve fields carry the ask. Everything else on a request is a decision about the ask, and decisions belong in the screening record further down.

FieldTypeWhy
request_ididMandatory. Own key, quotable back to the requester
asset_ididMandatory. The machine or location the ask is about
line_ididOptional. Fills from the asset, kept for reporting
request_typeenumMandatory. Repair, inspection, improve­ment, safety
titletextMandatory. One line, capped at about 80 characters
descriptiontextMandatory. What was seen, heard or measured
requested_urgencyenumMandatory. U1 to U4, the requester's own ask
production_impactenumMandatory. Stopped, slowed, quality risk, none yet
submitted_attime­stampMandatory. Server time, never typed by a person
source_channelenumMandatory. QR scan, mobile app, web, phone relay
request_statusenumMandatory. One of the nine states below
attach­ment_countintOptional. A photo is the cheapest evidence you own

asset_id must point at a row, never at typed text. A request against "the filler" is unusable the moment you own three fillers, and no later clean-up recovers which one was meant.

Where the asset register stops and a location starts is its own design question, covered in our asset hierarchy data model. The short rule for requests: point at the deepest node the requester can actually identify from where they stand.

production_impact is separate from urgency on purpose. Impact is an observation about the line right now, and urgency is an opinion about how soon somebody should come.

The requester

Six fields identify who asked and how to answer them. All of them are cheap, and the first one is the one plants most often get wrong.

FieldTypeWhy
requested_byidMandatory. Employee record, never a typed name
requester_roleenumMandatory. Operator, super­visor, quality, safety
requester_shiftidMandatory. The shift worked, not the wall clock
on_behalf_ofidOptional. Who actually saw it, for a relayed call
requester_contacttextOptional. Only where contractors raise requests
notify_on_decisionbool­eanMandatory. Defaults to yes, drives the push message

requester_shift matters because it is the only honest way to compare intake across a plant. Without it a raw daily count cannot tell you whether a quiet shift was quiet or simply did not report.

notify_on_decision is not a nicety. A requester who never hears an answer stops raising requests, and intake falls without a single person deciding that it should.

Screening: the triage decision

Screening is a separate record because it is a separate act by a separate person. Ten fields carry it, and every one of them answers a question an auditor will ask.

FieldTypeWhy
screened_byidMandatory. A person, never a queue or a role
screened_attime­stampMandatory. Stops the request-to-screen clock
decisionenumMandatory. Approve, reject, duplicate, merge, close
decision_reasonenumMandatory. Coded from a fixed list, not free text
decision_notetextMandatory on reject and on merge
criticality_at_screenenumMandatory. Copied, so a re-rating cannot rewrite history
work_priorityenumMandatory on approve. P1 to P4, the scheduler's call
duplicate_ofidMandatory when the decision is duplicate
merged_intoidMandatory when the decision is merge
target_response_bytime­stampOptional. Derived from priority, an internal promise

criticality_at_screen is the field nobody specifies and everybody later wishes they had. Asset criticality gets re-rated once or twice a year, and a live join silently rewrites every historical decision the next morning.

decision_reason has to be coded. A free text reason cannot be counted, and the whole point of screening data is to count how often each reason fires.

The link between a request and the work it caused

The join is many to many, so it needs its own table. A foreign key on either side will be wrong within a month of going live.

FieldTypeWhy
link_ididMandatory. Own key, because the join is many to many
request_ididMandatory. Which ask
wo_noidMandatory. Which commit­ment
link_typeenumMandatory. Answers fully, answers partly, follow-up
linked_byidMandatory. The person who raised or attached the job
linked_attime­stampMandatory. Stops the request-to-work clock
coverage_notetextOptional. Why this job answers this ask

linked_by is the field that keeps the record honest about who acted. A person screens, a person approves and a person raises the work order, and the link row is where that person is named.

On the month below, 31 converted requests produced 27 distinct work orders, because four requests were attached to a job that already existed. That is 31 ÷ 27 = 1.15 requests per work order.

The counting trap sits right there. "Work orders from requests" is 27 and "requests answered by work" is 31, and the two are different questions that look like the same one.

The status lifecycle

Nine states, and every one of them is a real outcome somebody has to be able to report on. A two-state model, open and closed, throws away everything worth knowing.

FromAllowed next
Sub­mittedScreened, Dupli­cate, With­drawn
ScreenedApproved, Rejected, Merged, Closed without work, With­drawn
ApprovedCon­verted, With­drawn
Con­vertedTerminal
RejectedTerminal
Dupli­cateTerminal
MergedTerminal
With­drawnTerminal
Closed without workTerminal

Six of the nine are terminal, and that is deliberate. A request that has been answered should not be reopened, because reopening it destroys the response time you already recorded against it.

Who moves it and what must be filled

StateMoved byMust be filled
Sub­mittedRequesterHeader fields, submitted_at
ScreenedScreenerscreened_by, screened_at
ApprovedApproverwork_priority, decision_reason
RejectedApproverrejection_code, rejection_note
Dupli­cateScreenerduplicate_of, screened_at
MergedScreenermerged_into, decision_note
Con­vertedPlannerA link row with wo_no
With­drawnRequesterwithdraw_reason
Closed without workScreenerclosure_code, decision_note

Two rules make this table enforceable rather than decorative. A state cannot be entered until its mandatory fields are present, and a person is named on every transition.

Notice also that Converted is the planner's move and requires a link row. A request never changes itself, and no system should raise work off the back of one without a person confirming it.

Rejection is data, not a deletion

A rejected request is one of the most valuable rows in the whole model. It is a record of demand that the plant consciously chose not to meet.

Deleting it, or letting the requester's screen simply stop showing it, destroys that evidence. Six fields make a rejection auditable.

FieldTypeWhy
rejection_codeenumMandatory. From the short fixed list below
rejection_notetextMandatory. One line the requester will actually read
rejected_byidMandatory. A person, never a depart­ment
rejected_attime­stampMandatory. Server time, stops the decision clock
notified_attime­stampMandatory. Proof the answer reached the requester
appeal_ofidOptional. Points back when the ask is re-raised

notified_at is the field that changes behaviour on the floor. It is the difference between a decision and a decision somebody heard about.

Six rejection codes are enough for almost any plant. More than about eight and screeners start picking the first plausible one in the list.

CodeMeaning
RJ1Not a fault, equip­ment working as designed
RJ2Already covered by a planned job
RJ3Outside mainte­nance scope, routed else­where
RJ4Asset retired or out of service
RJ5Not enough infor­mation, requester did not respond
RJ6Risk accepted and recorded for review

RJ6 is the one that must exist and the one vendors rarely offer. Some requests are turned down knowingly, with the risk accepted by a named person, and that is a completely different fact from "not a fault".

Watch RJ2 as well. Requests rejected because a planned job already covers them tell you the preventive maintenance schedule is not visible to the people on the machines.

Duplicates and merges change what you are counting

A duplicate_of pointer says this row describes the same problem as that row. It does not say this row should never have existed.

The pointer creates two legitimate counts: raw requests, and distinct problems.

On the month below, 60 requests were raised. Nine were duplicates and three were merged into other requests, so distinct demand is 48.

The raw count is therefore 25.0% higher than the distinct count, since 60 ÷ 48 = 1.25. Neither number is wrong and quoting either one without its definition is.

Why merging is the dangerous one

Marking a duplicate keeps the row and adds a pointer. Merging, as most systems implement it, moves the content of one request into another and leaves one row where there were two.

That silently destroys the demand signal. The second requester vanishes, the second submitted_at vanishes, and the response time for that person is never measured because their request no longer exists.

If you merge, record the merge. Keep the source row in state Merged with merged_into populated, its own submitted_at, its own requester and its own screened_at.

Response time is not repair time

Requests generate their own clocks, and those clocks measure the maintenance department's responsiveness rather than the length of a repair. Three intervals matter, and they are not interchangeable.

IntervalFormula
Request to screenscreened_at minus submitted_at
Request to approvalapproved_at minus submitted_at
Request to work startwo actual_start minus submitted_at
Request to answernotified_at minus submitted_at

Each interval needs its denominator printed beside it, because the four run over different row sets.

IntervalDenomi­nator
Request to screenRequests with a screened_at
Request to approvalRequests that reached Approved
Request to work startLink rows whose work order has actually started
Request to answerRequests with a notified_at

Two of these a plant can measure honestly from request fields alone. Request to screen and request to approval use only submitted_at, screened_at and approved_at, all of which live on the request.

Request to answer is measurable too, and it is the one requesters care about, but only if notified_at is written when the message is actually sent.

Request to work start is different. It reaches into the work order table for an actual start time, and it is only as good as the discipline around starting jobs in the system rather than at the machine.

None of these is repair time. Repair time starts when a technician picks up the tools and ends when the asset works again, which our guide to mean time to repair defines properly.

The confusion is expensive because the two move independently. A plant can cut request to screen from two days to two hours and not change MTTR by a minute, and that is a real and reportable improvement.

Urgency, criticality and priority are three fields

Almost every system ships with one field called priority, and almost every plant fills it with three different meanings. The result is a column where nobody can tell who made the call.

FieldWho sets it
requested_urgencyThe requester, at the machine
criticality_at_screenThe asset register, copied at screening
work_priorityThe screener or planner, as the final call

Urgency is an opinion, and it is allowed to be one. The operator is telling you how much this is hurting them right now, and that is information you want even when it is wrong.

Criticality is a property of the asset, reviewed annually. It knows nothing about this morning.

Priority is the decision, made by someone who can see both the urgency and the criticality plus the schedule, the parts and everybody else's requests.

A worked case where all three disagree

Three requests from the same week on line LINE‑03, with urgency, criticality and the final priority side by side.

RequestUrgency, criti­calityPri­or­ity
REQ‑2026‑0412 guard inter­lock on the label­lerU1 and C3P1
REQ‑2026‑0418 oil weep on the ex­truder gear­boxU4 and C1P2
REQ‑2026‑0423 noisy bearing, standby pallet­iserU1 and C4P4

REQ‑2026‑0412 is a safety interlock on a machine rated C3. Criticality does not govern here, and the screener raised it to P1 despite the asset being unremarkable.

REQ‑2026‑0418 came in as a low urgency note from a planner walking the line. The asset is C1, a weep becomes a leak, and the screener raised it to P2 against the requester's own opinion.

REQ‑2026‑0423 is the uncomfortable one. The operator wanted it now, the palletiser is a standby unit, and the screener lowered it to P4 and had to write a reason the operator would read.

Now collapse the three fields into one. REQ‑2026‑0423 arrives as P1 and stays P1, or the screener overwrites it to P4 and the operator's U1 is gone forever.

Across the 44 decided requests in the month below, urgency and final priority matched on 24. The screener lowered 14 and raised 6, so 20 of 44, or 45.5%, were changed.

Worked example: one month of requests on one line

Line LINE‑03, one calendar month, 60 requests raised by operators and supervisors. Every figure below comes from these rows.

1. The month, reconciled

OutcomeRequests
Con­verted to a work order31
Approved, no work order yet5
Rejected6
Dupli­cate of another request9
Merged into another request3
With­drawn by the requester2
Closed without work2
Still awaiting screening2
Total raised60

Check the arithmetic before anything else: 31 + 5 + 6 + 9 + 3 + 2 + 2 + 2 = 60. A month that does not reconcile to the raw count has rows in a state nobody has agreed on.

Requests that reached Approved are 31 + 5 = 36. Requests that were screened at all are 60 minus the 2 still waiting, so 58.

The 31 conversions produced 27 work orders, four of them attached to jobs already on the schedule. Distinct demand, after removing 9 duplicates and 3 merges, is 48.

2. Approval rate, computed two defensible ways

Both methods use the same 60 rows and the same definition of "approved". Only the denominator moves.

MethodResult
A. 36 ÷ 60 raised60.0%
B. 36 ÷ 44 decided81.8%

Method B divides by the requests that received a genuine screening decision on distinct demand: 31 + 5 + 6 + 2 = 44. It excludes the 9 duplicates, the 3 merges and the 2 withdrawals, none of which is a decision about a distinct problem, and the 2 still waiting.

Method A gives 36 ÷ 60 = 60.0%. Method B gives 36 ÷ 44 = 81.8%.

The gap is 21.8 percentage points, from a denominator that moved by 16 requests. Nothing about the plant changed between the two calculations.

Both are defensible, and a vendor quoting an approval rate is quoting one of them without telling you which. Ask, and write the answer into your reporting standard on the day you go live.

3. Median time to screen, on the same rows

Every screened request carries screened_at minus submitted_at in elapsed hours. Here is the whole distribution, once for all 58 screened requests and once for the 44 distinct decided ones.

HoursAll 58Distinct 44
191
274
364
454
655
844
1244
2055
3055
4844
7244
Total5844

With 58 values the median is the average of the 29th and 30th. The cumulative counts run 9, 16, 22, 27, 32, so both of those values sit in the 6 hour bin and the median is 6.0 hours.

With 44 values the median is the average of the 22nd and 23rd. The cumulative counts run 1, 5, 9, 13, 18, 22, 26, which puts the 22nd at 8 hours and the 23rd at 12 hours.

That gives (8 + 12) ÷ 2 = 10.0 hours. Same field, same month, same clock: 6.0 hours or 10.0 hours.

The gap is 4.0 hours, a median 66.7% higher on a row set 14 requests smaller. Again, nothing on the line changed.

4. Why the definition moved the number

The 14 excluded rows were not a random sample. Duplicates and withdrawals are screened fastest, because recognising an ask you have already seen takes seconds.

Eight of the nine fastest requests in the month were duplicates or withdrawals. Remove them and the fast end of the distribution collapses, so the median walks up the tail.

This is the whole lesson of the example. A request metric is a statement about a row set, and the row set is a choice somebody made, usually without writing it down.

The defence is a single line in the report header naming the population. "Median request to screen, 58 screened requests, duplicates and withdrawals included" is reproducible and "median response time 6 hours" is not.

The same discipline applies to backlog age, which is another median over a row set that changes shape as you clear it. Our guide to maintenance backlog management works through that side of it.

Five questions to ask a vendor about request data

  1. Is a request a separate record with its own key? Ask them to show a rejected request from six months ago, with the rejection reason and the name of the person who rejected it, without opening a work order.
  2. Can two requests point at one work order, and one request at two? Ask them to do both in front of you, then show which requests a given work order answers.
  3. What happens to the second request when you merge? Ask how many people reported the problem and when each of them was told, after the merge has been done.
  4. Are urgency and priority two fields? Ask what the requester chose and what the screener finally set, on a request where those two differ.
  5. What exactly does your response time report divide by? Ask whether duplicates, withdrawals and unscreened requests are in the denominator, and ask to see that stated on the report itself.

Question five is the one that separates the tools. Any system will show you an average response time, and very few will print the population that produced it, which is the difference worth testing when you compare equipment maintenance software.

How Fabrico helps

Fabrico is an OEE platform with a full CMMS built in, so requests, work orders and machine data sit in one system.

Requests move through a status workflow with approval workflows, and there is a dedicated emergency and reactive flow that records reaction time for the urgent ones.

Your team raises them from the iOS, Android or web app, with QR scanners on machines and parts so the right asset is attached without typing, and fast or detailed task creation depending on who is filling it in.

Push, in-app and email notifications with smart rules carry the decision back to the person who asked, and the audit log keeps who did what.

The analytics cover task distribution, per-employee productivity, MTTR and MTBF, with Excel export, a REST API and SAP and other ERP connectors when the numbers have to leave the system.

What Fabrico does not do: it does not plan or schedule production, it does not order parts on its own, and it has no predictive maintenance product.

A work order is always created and confirmed by your team. A person screens the request, a person approves it and a person raises the job.

Everything else on this page, including the nine states, the rejection codes and the link table, is a specification to test a vendor against rather than a feature list.

Want to see how your requests would flow from the machine to a decision? Book a 30 minute demo with a Fabrico consultant, no commitment, or contact us with your questions.

Frequently asked questions

What is the difference between a work request and a work order?

A work request records that somebody asked for attention, with no labour, parts or time committed. A work order is the plant agreeing to do the work, with an owner, a priority and a cost.

What fields does a work request need?

The header needs request_id, asset_id, request_type, title, description, requested_urgency, production_impact, submitted_at, source_channel and request_status. The requester needs requested_by, requester_role and requester_shift, and screening adds screened_by, screened_at, decision and decision_reason.

Should a rejected request be deleted?

No, it is evidence of demand the plant chose not to meet. Keep it with a rejection code, a note, the name of the approver and a timestamp proving the requester was told.

How many statuses should a work request have?

Nine: submitted, screened, approved, rejected, duplicate, merged, converted, withdrawn and closed without work. Six of them are terminal, and each one has a named person who may move it and a set of fields that must be filled first.

Is request response time the same as MTTR?

No. Response time measures how fast the department reacted to an ask, while MTTR measures how long the repair itself took once it started.

Последно от блога

Начертайте вашата пътна карта за надеждност
Изчислете потенциалната възвръщаемост: запазете час за демонстрация
Начертайте вашата пътна карта за надеждност
Като натиснете бутона Приемам, вие давате съгласието си за използването на `бисквитки`, докато ползвате до този уебсайт. За да научите повече за това как `бисквитките` се използват и управляват, моля, вижте нашата Политика за поверителност и Декларация за Бисквитките