Skip to content

Improving Frontend-Backend Workflow Alignment

This document provides recommendations for improving the alignment between frontend and backend workflow implementations in the PRS system.

Current Challenges

The PRS system currently faces several challenges related to frontend-backend workflow alignment:

  1. Inconsistent Status Representation:
  2. Frontend and backend use different status values
  3. Status mapping is scattered across multiple components
  4. No centralized status constants

  5. No Central Workflow Management:

  6. Status transitions are handled independently in frontend and backend
  7. No shared validation logic between frontend and backend
  8. Workflow rules are duplicated across components

  9. Optimistic Updates Without Validation:

  10. Frontend may update UI before backend confirms status change
  11. No rollback mechanism if backend rejects status change
  12. Potential for inconsistent state

  13. Incomplete Permission Checks:

  14. Frontend may show actions that backend would reject
  15. Permission checks are not consistently applied
  16. No centralized permission management

  17. Zustand Store and Database Synchronization:

  18. Zustand stores in frontend don't properly synchronize with backend database status fields
  19. Local state may become out of sync with server state
  20. No clear mechanism for handling concurrent updates

Recommendations Without Code Changes

The following recommendations can be implemented without immediate code changes:

1. Document Status Mapping

Create a comprehensive status mapping document that maps backend status values to frontend display values:

Markdown
# Status Mapping

## Requisition Workflow

| Backend Status | Frontend Display | CSS Class |
|---------------|------------------|-----------|
| draft | Draft | draft |
| submitted | For Approval | for_approval |
| approved | Approved | approved |
| rejected | Rejected | rejected |
| ... | ... | ... |

2. Create Workflow Transition Matrix

Document all valid state transitions for each workflow:

Markdown
1
2
3
4
5
6
7
8
9
# Workflow Transition Matrix

## Requisition Workflow

| Current State | Valid Next States | Required Permissions | Frontend Actions |
|---------------|-------------------|----------------------|------------------|
| draft | submitted | submit_requisition | Submit button |
| submitted | approved, rejected | approve_requisition | Approve/Reject buttons |
| ... | ... | ... | ... |

3. Document API Contract

Create a clear API contract document for all status transition endpoints:

Markdown
# API Contract

## Requisition Workflow

### PUT /v1/requisitions/submit
- **Required State**: draft
- **Resulting State**: submitted
- **Required Permissions**: submit_requisition
- **Frontend Component**: SubmitRequisitionButton
- **React Query Invalidation**: ['requisition'], ['requisitions']

4. Create Testing Scenarios

Document comprehensive testing scenarios for workflow transitions:

Markdown
# Testing Scenarios

## Requisition Workflow

1. **Submit Requisition**:
   - Create a draft requisition
   - Add items
   - Submit the requisition
   - Verify status changes to "submitted"
   - Verify approvers are notified

Implementation Roadmap

Once you're ready to implement changes, consider this phased approach:

Phase 1: Standardize Status Representation

  1. Create Shared Status Constants:
  2. Define a single source of truth for status values
  3. Ensure consistent naming between frontend and backend

  4. Centralize Status Mapping:

  5. Create a central status mapping utility
  6. Update all UI components to use this utility

Phase 2: Improve State Synchronization

  1. Implement a Workflow State Service:
  2. Create a service to manage workflow state
  3. Handle status transitions consistently

  4. Enhance Error Handling:

  5. Add proper error handling for status transitions
  6. Implement rollback for failed transitions

Phase 3: Add Frontend Validation

  1. Implement Pre-submission Validation:
  2. Add validation before sending status updates
  3. Disable actions that would be rejected by backend

  4. Enhance Permission Checks:

  5. Implement consistent permission checks
  6. Align frontend and backend permissions

Specific Implementation Recommendations

1. Create a Status Constants Module

Create a shared module for status constants:

JavaScript
// src/constants/statusConstants.js
export const REQUISITION_STATUS = Object.freeze({
  DRAFT: 'draft',
  SUBMITTED: 'submitted',
  APPROVED: 'approved',
  REJECTED: 'rejected',
  // ...
});

export const CANVASS_STATUS = Object.freeze({
  DRAFT: 'draft',
  FOR_APPROVAL: 'for_approval',
  APPROVED: 'approved',
  REJECTED: 'rejected',
  // ...
});

export const PO_STATUS = Object.freeze({
  FOR_PO_REVIEW: 'for_po_review',
  FOR_PO_APPROVAL: 'for_po_approval',
  FOR_DELIVERY: 'for_delivery',
  REJECT_PO: 'reject_po',
  CANCELLED_PO: 'cancelled_po',
  // ...
});

2. Create a Status Display Utility

Create a utility for consistent status display:

JavaScript
// src/utils/statusUtils.js
import { REQUISITION_STATUS, CANVASS_STATUS, PO_STATUS } from '../constants/statusConstants';

const STATUS_DISPLAY_MAP = {
  [REQUISITION_STATUS.DRAFT]: 'Draft',
  [REQUISITION_STATUS.SUBMITTED]: 'For Approval',
  [REQUISITION_STATUS.APPROVED]: 'Approved',
  [REQUISITION_STATUS.REJECTED]: 'Rejected',
  // ...
  [CANVASS_STATUS.DRAFT]: 'CS Draft',
  [CANVASS_STATUS.FOR_APPROVAL]: 'For CS Approval',
  // ...
  [PO_STATUS.FOR_PO_REVIEW]: 'For PO Review',
  [PO_STATUS.FOR_PO_APPROVAL]: 'For PO Approval',
  // ...
};

const STATUS_CLASS_MAP = {
  [REQUISITION_STATUS.DRAFT]: 'draft',
  [REQUISITION_STATUS.SUBMITTED]: 'for_approval',
  [REQUISITION_STATUS.APPROVED]: 'approved',
  [REQUISITION_STATUS.REJECTED]: 'rejected',
  // ...
};

export const getStatusDisplay = (status) => STATUS_DISPLAY_MAP[status] || status;
export const getStatusClass = (status) => STATUS_CLASS_MAP[status] || 'default';

3. Create a Workflow Validation Utility

Create a utility for workflow validation:

JavaScript
// src/utils/workflowUtils.js
import { REQUISITION_STATUS, CANVASS_STATUS, PO_STATUS } from '../constants/statusConstants';

const REQUISITION_TRANSITIONS = {
  [REQUISITION_STATUS.DRAFT]: [REQUISITION_STATUS.SUBMITTED],
  [REQUISITION_STATUS.SUBMITTED]: [REQUISITION_STATUS.APPROVED, REQUISITION_STATUS.REJECTED],
  [REQUISITION_STATUS.APPROVED]: [REQUISITION_STATUS.ASSIGNING],
  // ...
};

export const isValidTransition = (currentStatus, nextStatus, workflowType) => {
  let transitionMap;

  switch (workflowType) {
    case 'requisition':
      transitionMap = REQUISITION_TRANSITIONS;
      break;
    case 'canvass':
      transitionMap = CANVASS_TRANSITIONS;
      break;
    case 'purchaseOrder':
      transitionMap = PO_TRANSITIONS;
      break;
    default:
      return false;
  }

  return transitionMap[currentStatus]?.includes(nextStatus) || false;
};

4. Enhance React Query Mutations

Enhance React Query mutations with proper error handling and invalidation:

JavaScript
// src/hooks/useSubmitRequisition.js
import { useMutation, useQueryClient } from 'react-query';
import { submitRequisition } from '../api/requisitionApi';
import { REQUISITION_STATUS } from '../constants/statusConstants';
import { isValidTransition } from '../utils/workflowUtils';

export const useSubmitRequisition = () => {
  const queryClient = useQueryClient();

  return useMutation(
    (requisition) => {
      // Pre-validation
      if (!isValidTransition(requisition.status, REQUISITION_STATUS.SUBMITTED, 'requisition')) {
        throw new Error('Invalid status transition');
      }

      return submitRequisition(requisition);
    },
    {
      onSuccess: (data) => {
        // Invalidate relevant queries
        queryClient.invalidateQueries(['requisition']);
        queryClient.invalidateQueries(['requisitions']);

        // Show success message
        toast.success('Requisition submitted successfully');
      },
      onError: (error) => {
        // Show error message
        toast.error(`Failed to submit requisition: ${error.message}`);
      }
    }
  );
};

Conclusion

By implementing these recommendations, you can improve the alignment between frontend and backend workflow implementations in the PRS system. This will lead to:

  1. More Consistent User Experience: Users will see consistent status information and available actions
  2. Fewer Errors: Validation will prevent invalid status transitions
  3. Better Maintainability: Centralized workflow management will make the code easier to maintain
  4. Improved Reliability: Proper error handling will make the system more robust

Remember that these changes should be implemented incrementally, with thorough testing at each step to ensure that existing functionality is not broken.