Skip to content

Supplier Management Workflow

This document outlines the complete workflow for managing suppliers in the PRS system, from syncing to suspension.

Workflow Diagram

flowchart TD
  Start([Sync Supplier]) -->S2[Active]
  S2 -->|Suspend| S3[Suspended]
  S3 -->|Reactivate| S2

Status Definitions

Status Description
ACTIVE Initial default status after syncing, supplier is active and can be used in canvassing
SUSPENDED Supplier is suspended and cannot be used in any transactions but can be reactivated

Detailed Workflow Steps

1. Supplier Sync

Actor: Purchasing Admin and IT Admin

Actions:

  • Sync Supplier - pull from Cityland Legacy System
  • Edit information as needed (contact details, etc.)

Status Transitions:

  • ACTIVE (default after syncing)

Business Rules:

  • All required fields must be filled
  • Contact number accept alphanumeric characters

2. Supplier Update

Actor: Purchasing Admin and IT Admin

Actions:

  • Update supplier information
  • Change supplier status

Status Transitions:

  • No status change (if only information is updated)

Business Rules:

  • Supplier information can be updated at any time
  • Change in information should reflect in all open documents
    • Canvass: CS Draft and For Approval
    • Purchase Order: For PO Review and For Approval
    • Payment Request: PR Draft and For Approval
    • Non-RS Payment Request: Non RS Draft and For Approval
  • Closed documents shall not be affected
    • RS: RS Closed, Cancelled
    • CS: CS Approved, Cancelled
    • PO: For Sending, For Delivery, Closed, Cancelled
    • PR: PR Closed
    • Non-RS: Non RS Closed

3. Supplier Suspension

Actor: Purchasing Admin and IT Admin

Actions:

  • Suspend a supplier

Status Transitions:

  • ACTIVE → SUSPENDED

Business Rules:

  • Suspended suppliers cannot be used in new transactions
  • Existing transactions with suspended suppliers are affected:
    • Purchase orders with status FOR_PO_REVIEW and FOR_PO_APPROVAL are automatically cancelled
    • Canvass selections are invalidated - should recanvass again
  • Suspending is not allowed when supplier is used in the following documents with status:
    • Open PO - For Sending and For Delivery
    • Open PR - For PR Approval
  • Status change will not affect Closed RS

4. Supplier Reactivation

Actor: Purchasing Admin and IT Admin

Actions:

  • Reactivate a suspended or inactive supplier

Status Transitions:

  • SUSPENDED → ACTIVE

Business Rules:

  • Previously cancelled transactions are not automatically restored

Example Scenarios

Scenario 1: Standard Supplier Creation

  1. Purchasing Staff syncs supplier
  2. Supplier is activated by default
  3. Supplier can now be used in canvassing

Scenario 2: Supplier Suspension

  1. Admin suspends a supplier due to poor performance
  2. System cancels all pending purchase orders for the supplier
  3. System notifies relevant users about the suspension
  4. Supplier cannot be selected in new canvassing

Scenario 3: Supplier Reactivation

  1. Admin reactivates a previously suspended supplier
  2. Supplier becomes available for selection in canvassing
  3. Previously cancelled transactions remain cancelled

Implementation Details

Key Files

  • Controller: src/app/handlers/controllers/supplierController.js
  • Service: src/app/services/supplierService.js
  • Repository: src/infra/repositories/supplierRepository.js
  • Entity: src/domain/entities/supplierEntity.js
  • Constants: src/domain/constants/supplierConstants.js

Status Transition Implementation

JavaScript
// Example status transition logic
async function updateSupplierStatus(supplierId, newStatus, reason, transaction) {
  const supplier = await supplierRepository.findOne({
    where: { id: supplierId },
    transaction,
  });

  // Validate status transition
  const validTransitions = {
    'DRAFT': ['ACTIVE'],
    'ACTIVE': ['INACTIVE', 'SUSPENDED'],
    'INACTIVE': ['ACTIVE', 'SUSPENDED'],
    'SUSPENDED': ['ACTIVE'],
  };

  if (!validTransitions[supplier.status]?.includes(newStatus)) {
    throw new Error(`Invalid status transition from ${supplier.status} to ${newStatus}`);
  }

  // Additional validation for suspension
  if (newStatus === 'SUSPENDED' && !reason) {
    throw new Error('Suspension reason is required');
  }

  // Update status
  await supplier.update({ 
    status: newStatus,
    statusReason: newStatus === 'SUSPENDED' ? reason : null,
    statusChangedAt: new Date(),
  }, { transaction });

  // Handle side effects of suspension
  if (newStatus === 'SUSPENDED') {
    await handleSupplierSuspension(supplierId, transaction);
  }

  return supplier;
}

// Handle side effects of supplier suspension
async function handleSupplierSuspension(supplierId, transaction) {
  // Cancel purchase orders
  const purchaseOrders = await purchaseOrderRepository.findAll({
    where: { 
      supplierId,
      status: {
        [Sequelize.Op.in]: ['FOR_PO_REVIEW', 'FOR_PO_APPROVAL']
      }
    },
    transaction,
  });

  for (const po of purchaseOrders) {
    await po.update({ 
      status: 'CANCELLED_PO',
      cancellationReason: 'Supplier suspended',
    }, { transaction });

    // Remove approvers
    await purchaseOrderApproverRepository.destroy({
      where: { purchaseOrderId: po.id },
      transaction,
    });
  }

  // Invalidate canvass selections
  const canvassItemSuppliers = await canvassItemSupplierRepository.findAll({
    where: { 
      supplierId,
      isSelected: true,
    },
    include: [{
      model: canvassItemModel,
      as: 'canvassItem',
      include: [{
        model: canvassRequisitionModel,
        as: 'canvassRequisition',
        where: {
          status: {
            [Sequelize.Op.in]: ['FOR_APPROVAL', 'APPROVED']
          }
        }
      }]
    }],
    transaction,
  });

  for (const cis of canvassItemSuppliers) {
    await cis.update({ 
      isSelected: false,
    }, { transaction });
  }
}

Common Issues and Solutions

Issue 1: Cannot Suspend Supplier

Cause: Supplier has active transactions that cannot be cancelled.

Solution: - Complete or manually cancel all active transactions - Provide a detailed suspension reason

Issue 2: Supplier Reactivation Issues

Cause: System constraints preventing reactivation.

Solution: - Check for any blocking conditions - Ensure all required fields are still valid - Update any outdated information before reactivation