Skip to content

Action Reasons

Overview

The Action Reasons feature provides a configurable system for managing predefined reasons that admins can select when performing contract workflow actions. Instead of relying solely on free-text explanations, admins can choose from context-specific reasons when:

  • Voiding/Cancelling a contract (contract_void)
  • Requesting changes to a contract (contract_changes_requested)

This feature improves consistency in workflow communications and provides better analytics on why contracts are voided or require changes.

Key Features

  • Context-aware reasons: Reasons are organized by context (e.g., contract void, changes requested)
  • Admin-managed: Full CRUD operations through the Admin Console settings page
  • Drag-and-drop reordering: Customize the display order of reasons
  • Enable/disable toggle: Temporarily hide reasons without deleting them
  • Extensible design: Additional contexts can be added without schema changes

Architecture

┌─────────────────────────────────────────────────────────────┐
│                      Admin Console                           │
│  ┌─────────────────────────────────────────────────────┐    │
│  │         Action Reasons Settings Page                 │    │
│  │  (/settings/action-reasons)                         │    │
│  │  - Create/Edit/Delete reasons                        │    │
│  │  - Drag-and-drop reordering                         │    │
│  │  - Enable/disable toggle                            │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐    │
│  │         Partner Contract List                        │    │
│  │  - Reason dropdown in Void/Request Changes panels    │    │
│  │  - Reason ID sent with action requests               │    │
│  └─────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│                      Partner Service                         │
│  ┌─────────────────────────────────────────────────────┐    │
│  │            ActionReasonsModule                       │    │
│  │  - ActionReasonsController                          │    │
│  │  - ActionReasonsService                             │    │
│  │  - DTOs and Entity                                  │    │
│  └─────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│                       PostgreSQL                             │
│  ┌─────────────────────────────────────────────────────┐    │
│  │              action_reasons table                    │    │
│  │  - id, context, slug, name, description              │    │
│  │  - display_order, enabled, timestamps                │    │
│  └─────────────────────────────────────────────────────┘    │
│  ┌─────────────────────────────────────────────────────┐    │
│  │           partner_contracts table                    │    │
│  │  - void_reason_id (FK)                              │    │
│  │  - changes_requested_reason_id (FK)                 │    │
│  └─────────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────────┘

API Reference

Endpoints

All endpoints are prefixed with /api/partners/admin/action-reasons

Method Endpoint Description
GET / List reasons by context
GET /:id Get a single reason by ID
POST / Create a new reason
PATCH /:id Update an existing reason
DELETE /:id Delete a reason
PUT /reorder Bulk reorder reasons within a context

Query Parameters

Parameter Type Description
context string Filter by context (e.g., contract_void)
includeDisabled string Set to "true" to include disabled reasons

Request/Response Examples

List Reasons

GET /api/partners/admin/action-reasons?context=contract_void

Response:

[
  {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "context": "contract_void",
    "slug": "compliance-issue",
    "name": "Compliance Issue",
    "description": "Contract voided due to regulatory compliance concerns",
    "display_order": 0,
    "enabled": true,
    "created_at": "2026-01-26T10:00:00.000Z",
    "updated_at": "2026-01-26T10:00:00.000Z"
  }
]

Create Reason

POST /api/partners/admin/action-reasons
Content-Type: application/json

{
  "context": "contract_void",
  "slug": "partner-request",
  "name": "Partner Request",
  "description": "Voided at partner's request"
}

Update Reason

PATCH /api/partners/admin/action-reasons/550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json

{
  "name": "Updated Name",
  "enabled": false
}

Reorder Reasons

PUT /api/partners/admin/action-reasons/reorder
Content-Type: application/json

{
  "context": "contract_void",
  "ids": [
    "550e8400-e29b-41d4-a716-446655440001",
    "550e8400-e29b-41d4-a716-446655440000",
    "550e8400-e29b-41d4-a716-446655440002"
  ]
}

Data Model

ActionReason Entity

interface ActionReason {
  id: string;           // UUID primary key
  context: string;      // Context identifier (e.g., 'contract_void')
  slug: string;         // URL-friendly unique identifier within context
  name: string;         // Display name
  description: string | null;  // Optional description
  display_order: number;       // Sort order (0-based)
  enabled: boolean;     // Whether reason is available for selection
  created_at: Date;
  updated_at: Date;
}

Available Contexts

Context Description
contract_void Reasons for voiding/cancelling a contract
contract_changes_requested Reasons for requesting changes to a contract

Frontend Integration

Admin Console - Settings Page

Location: /settings/action-reasons

The Action Reasons settings page provides:

  • Tab navigation: Switch between different contexts (Void Reasons, Change Reasons)
  • Reason list: Drag-and-drop sortable list with inline controls
  • Create/Edit dialog: Modal form for creating or editing reasons
  • Delete confirmation: Safety dialog before permanent deletion

Contract Actions Integration

When voiding a contract or requesting changes, the admin can:

  1. Select a predefined reason from a dropdown
  2. Provide additional context in the free-text comment field
  3. Submit the action with both the reason ID and comment

The reason ID is stored in partner_contracts.void_reason_id or partner_contracts.changes_requested_reason_id.

Development

Project Structure

services/partner-service/src/modules/action-reasons/
├── action-reasons.controller.ts  # HTTP endpoints
├── action-reasons.service.ts     # Business logic
├── action-reasons.module.ts      # NestJS module
├── dto/
│   ├── create-action-reason.dto.ts
│   ├── update-action-reason.dto.ts
│   └── reorder-action-reasons.dto.ts
└── entities/
    └── action-reason.entity.ts   # TypeScript interface

Adding a New Context

To add a new context (e.g., for document rejection):

  1. Add the context constant to action-reason.entity.ts:

    export const ACTION_REASON_CONTEXTS = {
      CONTRACT_VOID: 'contract_void',
      CONTRACT_CHANGES_REQUESTED: 'contract_changes_requested',
      DOCUMENT_REJECTION: 'document_rejection',  // New
    } as const;
    

  2. Add the context to the frontend's partner.service.ts

  3. Add a new tab in ActionReasonsPage.tsx

  4. Update the relevant workflow to use the new context

Validation Rules

  • slug: Required, 1-100 chars, lowercase alphanumeric with hyphens/underscores only
  • name: Required, 1-255 chars
  • description: Optional
  • display_order: Optional (auto-incremented if not provided), must be >= 0
  • context + slug: Must be unique (database constraint)

Internationalization

The feature supports full i18n through the admin-console's translation system. Translation keys are located in frontends/admin-console/src/i18n/locales/en.json under settings.actionReasons.

Future Extensions

The action_reasons table is designed for extensibility. Potential future use cases:

Context Workflow Current Field
document_rejection Partner document review verification_reason
service_proposal_rejection Service proposal approval review_message
service_text_rejection Service text approval admin_note
contract_proposal_rejection Contract proposal approval review_message
task_dismissal Admin task management (new field)

See Also