SwimdraftPricingSign inStart free

Goods receipt BPMN example

Goods receipt is the gate between a supplier delivery and your stock records: unload, match against the purchase order, inspect, and post the receipt. Warehouses map it because it sits on the boundary of three functions with different incentives, and because errors here cascade into wrong stock figures and disputed supplier invoices. The classic failure is booking goods in before anyone has checked what actually arrived.

The model is a single pool with Warehouse, Quality, and Finance lanes. Two exclusive gateways guard the flow: one checks the delivery against the purchase order, the other checks physical condition, and both failure branches converge on the same discrepancy path. That convergence is the modelling choice worth noticing: one rejection procedure handles both problems, so the diagram avoids duplicating tasks.

Goods receipt: BPMN 2.0 diagram
Goods receipt process modelled as a BPMN 2.0 diagram

Standard BPMN 2.0 interchange XML: opens in Camunda Modeler, Signavio, Bizagi, and any other compliant tool.

The process at a glance

Starts when
Delivery arrived
Ends with
Delivery rejected · Receipt posted
Lanes
Warehouse · Quality · Finance
Decisions
Delivery matches PO? · Goods undamaged?

How to read this diagram

Everything begins when a delivery arrives at the Warehouse lane. Staff unload the delivery and match it to the purchase order, and the gateway "Delivery matches PO?" makes the first decision. Its No branch, the default, records a discrepancy, sends a notification to the supplier, and finishes at the "Delivery rejected" end event. The Yes branch passes the goods to the Quality lane, where an inspector checks their condition.

At the second gateway, "Goods undamaged?", a No result routes to the same discrepancy task the first gateway uses, so both rejection reasons share one exit. A Yes result returns the goods to the Warehouse for putaway, after which Finance posts the goods receipt note and the process ends at "Receipt posted". The two end events split the outcomes cleanly: stock is either on the shelf and in the ledger, or formally rejected with the supplier informed.

BPMN elements used

ElementCountIn this diagram
Start event1Delivery arrived
End event2Delivery rejected, Receipt posted
Task4Unload delivery, Match delivery to PO, Record discrepancy, Put away stock
User task1Inspect goods condition
Service task1Post goods receipt note
Send task1Notify supplier
Exclusive gateway2Delivery matches PO?, Goods undamaged?
View the BPMN 2.0 XML for this diagram
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="swimdraft" exporterVersion="1.0">
  <bpmn2:collaboration id="Collaboration_1">
    <bpmn2:participant id="pool_gr" name="Goods receipt" processRef="Process_pool_gr" />
  </bpmn2:collaboration>
  <bpmn2:process id="Process_pool_gr" isExecutable="false">
    <bpmn2:laneSet id="LaneSet_pool_gr">
      <bpmn2:lane id="lane_gr_wh" name="Warehouse">
        <bpmn2:flowNodeRef>start_gr</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>t_gr_unload</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>t_gr_match</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>g_gr_match</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>t_gr_discrep</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>t_gr_notify</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>end_gr_rej</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>t_gr_putaway</bpmn2:flowNodeRef>
      </bpmn2:lane>
      <bpmn2:lane id="lane_gr_qa" name="Quality">
        <bpmn2:flowNodeRef>t_gr_inspect</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>g_gr_cond</bpmn2:flowNodeRef>
      </bpmn2:lane>
      <bpmn2:lane id="lane_gr_fin" name="Finance">
        <bpmn2:flowNodeRef>t_gr_grn</bpmn2:flowNodeRef>
        <bpmn2:flowNodeRef>end_gr_ok</bpmn2:flowNodeRef>
      </bpmn2:lane>
    </bpmn2:laneSet>
    <bpmn2:startEvent id="start_gr" name="Delivery arrived">
      <bpmn2:outgoing>fgr1</bpmn2:outgoing>
    </bpmn2:startEvent>
    <bpmn2:task id="t_gr_unload" name="Unload delivery">
      <bpmn2:incoming>fgr1</bpmn2:incoming>
      <bpmn2:outgoing>fgr2</bpmn2:outgoing>
    </bpmn2:task>
    <bpmn2:task id="t_gr_match" name="Match delivery to PO">
      <bpmn2:incoming>fgr2</bpmn2:incoming>
      <bpmn2:outgoing>fgr3</bpmn2:outgoing>
    </bpmn2:task>
    <bpmn2:exclusiveGateway id="g_gr_match" name="Delivery matches PO?" default="fgr5">
      <bpmn2:incoming>fgr3</bpmn2:incoming>
      <bpmn2:outgoing>fgr4</bpmn2:outgoing>
      <bpmn2:outgoing>fgr5</bpmn2:outgoing>
    </bpmn2:exclusiveGateway>
    <bpmn2:userTask id="t_gr_inspect" name="Inspect goods condition">
      <bpmn2:incoming>fgr4</bpmn2:incoming>
      <bpmn2:outgoing>fgr6</bpmn2:outgoing>
    </bpmn2:userTask>
    <bpmn2:exclusiveGateway id="g_gr_cond" name="Goods undamaged?" default="fgr8">
      <bpmn2:incoming>fgr6</bpmn2:incoming>
      <bpmn2:outgoing>fgr7</bpmn2:outgoing>
      <bpmn2:outgoing>fgr8</bpmn2:outgoing>
    </bpmn2:exclusiveGateway>
    <bpmn2:task id="t_gr_discrep" name="Record discrepancy">
      <bpmn2:incoming>fgr5</bpmn2:incoming>
      <bpmn2:incoming>fgr8</bpmn2:incoming>
      <bpmn2:outgoing>fgr9</bpmn2:outgoing>
    </bpmn2:task>
    <bpmn2:sendTask id="t_gr_notify" name="Notify supplier">
      <bpmn2:incoming>fgr9</bpmn2:incoming>
      <bpmn2:outgoing>fgr10</bpmn2:outgoing>
    </bpmn2:sendTask>
    <bpmn2:endEvent id="end_gr_rej" name="Delivery rejected">
      <bpmn2:incoming>fgr10</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:task id="t_gr_putaway" name="Put away stock">
      <bpmn2:incoming>fgr7</bpmn2:incoming>
      <bpmn2:outgoing>fgr11</bpmn2:outgoing>
    </bpmn2:task>
    <bpmn2:serviceTask id="t_gr_grn" name="Post goods receipt note">
      <bpmn2:incoming>fgr11</bpmn2:incoming>
      <bpmn2:outgoing>fgr12</bpmn2:outgoing>
    </bpmn2:serviceTask>
    <bpmn2:endEvent id="end_gr_ok" name="Receipt posted">
      <bpmn2:incoming>fgr12</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:sequenceFlow id="fgr1" sourceRef="start_gr" targetRef="t_gr_unload" />
    <bpmn2:sequenceFlow id="fgr2" sourceRef="t_gr_unload" targetRef="t_gr_match" />
    <bpmn2:sequenceFlow id="fgr3" sourceRef="t_gr_match" targetRef="g_gr_match" />
    <bpmn2:sequenceFlow id="fgr4" name="Yes" sourceRef="g_gr_match" targetRef="t_gr_inspect">
      <bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">Yes</bpmn2:conditionExpression>
    </bpmn2:sequenceFlow>
    <bpmn2:sequenceFlow id="fgr5" name="No" sourceRef="g_gr_match" targetRef="t_gr_discrep" />
    <bpmn2:sequenceFlow id="fgr6" sourceRef="t_gr_inspect" targetRef="g_gr_cond" />
    <bpmn2:sequenceFlow id="fgr7" name="Yes" sourceRef="g_gr_cond" targetRef="t_gr_putaway">
      <bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">Yes</bpmn2:conditionExpression>
    </bpmn2:sequenceFlow>
    <bpmn2:sequenceFlow id="fgr8" name="No" sourceRef="g_gr_cond" targetRef="t_gr_discrep" />
    <bpmn2:sequenceFlow id="fgr9" sourceRef="t_gr_discrep" targetRef="t_gr_notify" />
    <bpmn2:sequenceFlow id="fgr10" sourceRef="t_gr_notify" targetRef="end_gr_rej" />
    <bpmn2:sequenceFlow id="fgr11" sourceRef="t_gr_putaway" targetRef="t_gr_grn" />
    <bpmn2:sequenceFlow id="fgr12" sourceRef="t_gr_grn" targetRef="end_gr_ok" />
  </bpmn2:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Collaboration_1">
      <bpmndi:BPMNShape id="pool_gr_di" bpmnElement="pool_gr" isHorizontal="true">
        <dc:Bounds x="20" y="20" width="1420" height="500" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="lane_gr_wh_di" bpmnElement="lane_gr_wh" isHorizontal="true">
        <dc:Bounds x="50" y="20" width="1390" height="240" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="lane_gr_qa_di" bpmnElement="lane_gr_qa" isHorizontal="true">
        <dc:Bounds x="50" y="260" width="1390" height="130" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="lane_gr_fin_di" bpmnElement="lane_gr_fin" isHorizontal="true">
        <dc:Bounds x="50" y="390" width="1390" height="130" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="start_gr_di" bpmnElement="start_gr">
        <dc:Bounds x="112" y="59" width="36" height="36" />
        <bpmndi:BPMNLabel><dc:Bounds x="91" y="101" width="79" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="t_gr_unload_di" bpmnElement="t_gr_unload">
        <dc:Bounds x="230" y="37" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="t_gr_match_di" bpmnElement="t_gr_match">
        <dc:Bounds x="380" y="37" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="g_gr_match_di" bpmnElement="g_gr_match">
        <dc:Bounds x="555" y="52" width="50" height="50" />
        <bpmndi:BPMNLabel><dc:Bounds x="524" y="32" width="112" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="t_gr_inspect_di" bpmnElement="t_gr_inspect">
        <dc:Bounds x="680" y="277" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="g_gr_cond_di" bpmnElement="g_gr_cond">
        <dc:Bounds x="855" y="292" width="50" height="50" />
        <bpmndi:BPMNLabel><dc:Bounds x="829" y="272" width="102" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="t_gr_discrep_di" bpmnElement="t_gr_discrep">
        <dc:Bounds x="980" y="37" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="t_gr_notify_di" bpmnElement="t_gr_notify">
        <dc:Bounds x="1130" y="37" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="end_gr_rej_di" bpmnElement="end_gr_rej">
        <dc:Bounds x="1312" y="59" width="36" height="36" />
        <bpmndi:BPMNLabel><dc:Bounds x="1288" y="101" width="84" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="t_gr_putaway_di" bpmnElement="t_gr_putaway">
        <dc:Bounds x="980" y="147" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="t_gr_grn_di" bpmnElement="t_gr_grn">
        <dc:Bounds x="1130" y="407" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="end_gr_ok_di" bpmnElement="end_gr_ok">
        <dc:Bounds x="1312" y="429" width="36" height="36" />
        <bpmndi:BPMNLabel><dc:Bounds x="1292" y="471" width="76" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="fgr1_di" bpmnElement="fgr1">
        <di:waypoint x="148" y="77" />
        <di:waypoint x="230" y="77" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fgr2_di" bpmnElement="fgr2">
        <di:waypoint x="330" y="77" />
        <di:waypoint x="380" y="77" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fgr3_di" bpmnElement="fgr3">
        <di:waypoint x="480" y="77" />
        <di:waypoint x="555" y="77" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fgr4_di" bpmnElement="fgr4">
        <di:waypoint x="605" y="77" />
        <di:waypoint x="660" y="77" />
        <di:waypoint x="660" y="317" />
        <di:waypoint x="680" y="317" />
        <bpmndi:BPMNLabel><dc:Bounds x="611" y="57" width="21" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fgr5_di" bpmnElement="fgr5">
        <di:waypoint x="605" y="77" />
        <di:waypoint x="980" y="77" />
        <bpmndi:BPMNLabel><dc:Bounds x="611" y="83" width="17" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fgr6_di" bpmnElement="fgr6">
        <di:waypoint x="780" y="317" />
        <di:waypoint x="855" y="317" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fgr7_di" bpmnElement="fgr7">
        <di:waypoint x="905" y="317" />
        <di:waypoint x="960" y="317" />
        <di:waypoint x="960" y="187" />
        <di:waypoint x="980" y="187" />
        <bpmndi:BPMNLabel><dc:Bounds x="911" y="297" width="21" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fgr8_di" bpmnElement="fgr8">
        <di:waypoint x="905" y="317" />
        <di:waypoint x="960" y="317" />
        <di:waypoint x="960" y="77" />
        <di:waypoint x="980" y="77" />
        <bpmndi:BPMNLabel><dc:Bounds x="911" y="323" width="17" height="14" /></bpmndi:BPMNLabel>
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fgr9_di" bpmnElement="fgr9">
        <di:waypoint x="1080" y="77" />
        <di:waypoint x="1130" y="77" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fgr10_di" bpmnElement="fgr10">
        <di:waypoint x="1230" y="77" />
        <di:waypoint x="1312" y="77" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fgr11_di" bpmnElement="fgr11">
        <di:waypoint x="1080" y="187" />
        <di:waypoint x="1110" y="187" />
        <di:waypoint x="1110" y="447" />
        <di:waypoint x="1130" y="447" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="fgr12_di" bpmnElement="fgr12">
        <di:waypoint x="1230" y="447" />
        <di:waypoint x="1312" y="447" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn2:definitions>

Frequently asked questions

Is it valid for two gateways to route to the same rejection task?

Yes. BPMN allows any number of sequence flows to target one activity, and the merge is implicit: each arriving token simply runs the task. Reusing the discrepancy path keeps the model compact and guarantees both failure modes follow the identical procedure, which is usually exactly what the warehouse intends in practice.

Why is the condition check a user task rather than a plain task?

A user task signals work performed by a named person through some system, here an inspector recording results against acceptance criteria. A plain task is deliberately vague about who or what performs it. Marking inspection as a user task tells readers, and any future workflow engine, that a human decision sits at this point.

Where would a timer belong if the supplier never responds?

Attach the wait after "Notify supplier": add an intermediate timer catch event on a path that escalates to procurement if no credit note arrives within, say, ten working days. Swimdraft validates that the event has both incoming and outgoing flows, one of the 19 BPMN 2.0.2 rules it checks with clause citations.

Related BPMN examples

Generate your own version of this diagram

Describe how the process works in your organisation: plain English, meeting notes, a transcript, or a spreadsheet. Swimdraft turns it into a spec-validated BPMN 2.0 diagram you can edit in the browser and export as .bpmn, SVG, or PNG.

Start free

No credit card required