Skip to content

API Contract for Workflow Status Transitions

This document defines the API contract for workflow status transitions in the PRS system. It serves as a reference for both frontend and backend developers to ensure consistent implementation of workflow rules.

Requisition Workflow

Submit Requisition

Endpoint: PUT /v1/requisitions/submit

Purpose: Submit a draft requisition for approval

Request Body:

JSON
{
  "id": 123,
  "isDraft": "false",
  "type": "ofm",
  "companyId": 1,
  "departmentId": 2,
  "projectId": 3,
  "purpose": "Office supplies",
  "notes": "Urgent request",
  "deliveryAddress": "Main Office",
  "category": "company",
  "attachments": [
    {
      "name": "document.pdf",
      "file": "[Binary Data]"
    }
  ]
}

Response:

JSON
{
  "message": "Requisition submitted successfully",
  "requisition": {
    "id": 123,
    "status": "submitted",
    "rsNumber": "RS-01A0001",
    "type": "ofm",
    "companyId": 1,
    "departmentId": 2,
    "projectId": 3,
    "purpose": "Office supplies",
    "notes": "Urgent request",
    "deliveryAddress": "Main Office",
    "category": "company",
    "createdAt": "2023-06-01T00:00:00.000Z",
    "updatedAt": "2023-06-01T00:00:00.000Z"
  }
}

Required State: draft

Resulting State: submitted

Required Permissions: submit_requisition

Frontend Component: SubmitRequisitionButton

React Query Invalidation: ['requisition'], ['requisitions']

Error Handling: - 400: Invalid request body - 403: Insufficient permissions - 404: Requisition not found - 409: Invalid status transition

Approve Requisition

Endpoint: PUT /v1/requisitions/{id}/approve

Purpose: Approve a submitted requisition

Request Body:

JSON
1
2
3
4
5
6
7
{
  "comments": [
    {
      "comment": "Approved as requested"
    }
  ]
}

Response:

JSON
1
2
3
4
5
6
7
8
9
{
  "message": "Requisition approved successfully",
  "requisition": {
    "id": 123,
    "status": "approved",
    "rsNumber": "RS-01A0001",
    "updatedAt": "2023-06-01T00:00:00.000Z"
  }
}

Required State: submitted

Resulting State: approved (if all approvers approve)

Required Permissions: approve_requisition

Frontend Component: ApproveRequisitionButton

React Query Invalidation: ['requisition'], ['requisitions'], ['notes']

Error Handling: - 400: Invalid request body - 403: Insufficient permissions or not a pending approver - 404: Requisition not found - 409: Invalid status transition

Canvass Workflow

Submit Canvass

Endpoint: POST /v1/canvass/

Purpose: Submit a canvass for approval

Request Body:

JSON
{
  "requisitionId": 123,
  "isDraft": "false",
  "addItems": [
    {
      "id": 1,
      "requisitionItemId": 101,
      "suppliers": [
        {
          "supplierId": 201,
          "term": "NET 30",
          "quantity": 10,
          "unitPrice": 100,
          "discountValue": 0,
          "discountType": "fixed",
          "isSelected": true,
          "notes": "Best quality"
        }
      ]
    }
  ],
  "updateItems": [],
  "deleteItems": [],
  "notes": "Canvass completed"
}

Response:

JSON
{
  "message": "Canvass submitted successfully",
  "canvass": {
    "id": 456,
    "requisitionId": 123,
    "status": "for_approval",
    "csNumber": "CS-01A0001",
    "createdAt": "2023-06-01T00:00:00.000Z",
    "updatedAt": "2023-06-01T00:00:00.000Z"
  }
}

Required State: N/A (new canvass) or draft (existing canvass)

Resulting State: for_approval (complete canvass) or partially_canvassed (partial canvass)

Required Permissions: submit_canvass

Frontend Component: SubmitCanvassButton

React Query Invalidation: Multiple canvass and requisition queries

Error Handling: - 400: Invalid request body or missing suppliers - 403: Insufficient permissions or not assigned to requisition - 404: Requisition not found - 409: Invalid status transition

Approve Canvass

Endpoint: POST /v1/canvass/{id}/approve

Purpose: Approve a canvass and generate purchase orders

Request Body:

JSON
1
2
3
4
5
6
7
8
{
  "suppliers": [
    {
      "itemId": 1,
      "supplierId": 201
    }
  ]
}

Response:

JSON
1
2
3
{
  "message": "Canvass successfully approved"
}

Required State: for_approval

Resulting State: approved

Required Permissions: approve_canvass

Frontend Component: ApproveCanvassButton

React Query Invalidation: Multiple canvass and requisition queries

Error Handling: - 400: Invalid request body or missing suppliers - 403: Insufficient permissions or not a pending approver - 404: Canvass not found - 409: Invalid status transition

Purchase Order Workflow

Submit Purchase Order

Endpoint: POST /v1/purchase-orders/{id}/submit

Purpose: Submit a purchase order for approval

Request Body:

JSON
1
2
3
4
5
{
  "warrantyId": 1,
  "isNewDeliveryAddress": true,
  "newDeliveryAddress": "Warehouse B, 123 Main St"
}

Response:

JSON
1
2
3
4
5
6
7
8
9
{
  "message": "Purchase order submitted successfully",
  "purchaseOrder": {
    "id": 789,
    "status": "for_po_approval",
    "poNumber": "PO-01A0001",
    "updatedAt": "2023-06-01T00:00:00.000Z"
  }
}

Required State: for_po_review

Resulting State: for_po_approval

Required Permissions: submit_po

Frontend Component: SubmitPOButton

React Query Invalidation: ['items'], ['purchaseOrder'], ['purchaseOrders']

Error Handling: - 400: Invalid request body - 403: Insufficient permissions or not assigned to purchase order - 404: Purchase order not found - 409: Invalid status transition

Approve Purchase Order

Endpoint: POST /v1/purchase-orders/{id}/approve

Purpose: Approve a purchase order

Request Body:

JSON
1
2
3
{
  "comments": "Approved as requested"
}

Response:

JSON
1
2
3
{
  "message": "Purchase order successfully approved"
}

Required State: for_po_approval

Resulting State: for_delivery (if all approvers approve)

Required Permissions: approve_po

Frontend Component: ApprovePOButton

React Query Invalidation: ['purchaseOrder'], ['purchaseOrders'], ['purchaseOrderApprovers']

Error Handling: - 400: Invalid request body - 403: Insufficient permissions or not a pending approver - 404: Purchase order not found - 409: Invalid status transition

Reject Purchase Order

Endpoint: POST /v1/purchase-orders/{id}/reject

Purpose: Reject a purchase order

Request Body:

JSON
1
2
3
{
  "comments": "Rejected due to high price"
}

Response:

JSON
1
2
3
{
  "message": "Purchase order successfully rejected"
}

Required State: for_po_approval

Resulting State: reject_po

Required Permissions: reject_po

Frontend Component: RejectPOButton

React Query Invalidation: ['purchaseOrder'], ['purchaseOrders'], ['purchaseOrderApprovers']

Error Handling: - 400: Invalid request body or missing rejection reason - 403: Insufficient permissions or not a pending approver - 404: Purchase order not found - 409: Invalid status transition

Frontend-Backend Synchronization

To maintain synchronization between frontend and backend:

  1. Use React Query Invalidation: After each mutation, invalidate relevant queries to refresh data
  2. Check Status Before Actions: Verify current status before showing action buttons
  3. Handle Error Responses: Display appropriate error messages for invalid transitions
  4. Implement Permission Checks: Only show actions that the user has permission to perform
  5. Use Consistent Status Values: Map backend status values to frontend display values consistently