Campaign Process flow

🔄 Simplified Parent-Child Campaign Management Design Flow

Core Principle

At any point in time, only one campaign—either the parent or its successfully completed child—should be considered active and operational. A parent campaign remains active until a child campaign completes successfully and takes over its role.

1️⃣ Initial Child Campaign Creation

  • Validation:

    • Before creating a new child campaign, verify whether the parent already has a child campaign with:

      • isActive: true

    • If such a child exists, reject the request with an appropriate error.

  • On Validation Pass:

    • Create the child campaign with:

      • isActive: true (indicating it's currently being usable)

      • status: 'draft' (or 'started'/'inprogress' based on next steps)

      • parentId: set to the parent campaign's ID

    • The parent campaign remains isActive: true.

  • Why: This ensures only one active child can exist at a time. The parent retains operational status while the child is in development.

2️⃣ During Child Campaign Processing (Update Phase)

  • The child campaign continues with:

    • isActive: true

    • status reflecting progress (e.g., inprogress, validating)

  • The parent campaign remains:

    • isActive: true

  • Why: The child is actively being updated, but hasn't yet taken over. The parent remains the official operational campaign.

3️⃣ On Successful Child Campaign Completion

  • Once the child campaign is fully processed and marked status: 'completed':

    • Child remains isActive: true

    • Parent's isActive is updated to false

  • Why: This marks the official handoff. The child becomes the sole operational campaign, and the parent is retired from active use.

4️⃣ Cancelling a Child Campaign

  • If a child campaign is needed to be cancelled:

    • Set its isActive: false

  • Why: The child is clearly marked as non-operational. The parent continues as the active campaign, and a new child can be initiated later.

5️⃣ On Failed Child Campaign Creation/Update

  • If a failure occurs during child creation/update:

    • Keep isActive: true

    • Set status: 'failed'

    • Parent remains isActive: true

  • Why: The failed child still exists and can be retried. The parent remains active. If it’s decided not to retry the child, it can later be cancelled (setting isActive: false).

🔍 Campaign Search Functionality

Approach: Enhance the existing searchProjectTypeCampaignService and searchProjectCampaignResourcData.

Proposed Changes:

File: src/server/config/models/searchCampaignDetails.ts

  • Add:

    • isChildCampaign?: boolean

    • parentId?: string

File: src/server/utils/campaignUtils.ts → buildSearchQuery()

  • Modify query generation:

    • If isChildCampaign === true, add AND parentId IS NOT NULL

    • If isChildCampaign === false, add AND parentId IS NULL

    • If parentId is specified, add AND parentId = $X

🔎 How to Search

1. All child campaigns:

{

"tenantId": "yourTenantId",

"isChildCampaign": true

}

2. Currently active (parent or completed child):

{

"tenantId": "yourTenantId",

"isActive": true,

"status": "completed" // optional

}

3. Cancelled or inactive child campaigns:

{

"tenantId": "yourTenantId",

"isChildCampaign": true,

"isActive": false

}

4. Parent campaigns not yet replaced:

{

"tenantId": "yourTenantId",

"isChildCampaign": false,

"isActive": true

}

⚙️ Code-Level Integration

✅ Max One Active Child Validation

  • In createProjectTypeCampaignService or processBasedOnAction:

    • Query for existing active children (isActive: true) before proceeding.

✅ Deactivating Parent After Child Completion

  • On child status transition to completed:

    • Fetch parent campaign

    • Set isActive = false

    • Persist the update ( via Kafka)

✅ Campaign Cancellation API

Endpoint: POST /project-factory/v1/project-type/cancel-campaign

Purpose: Cancels a campaign by setting:

  • isActive = false

  • status = "cancelled" The update is sent via Kafka.

🔧 Request Body

Sample Payload
```
   "CampaignDetails":  {
            "id": "2b68a3aa-fca2-462e-8d59-8821c9a56132",
            "tenantId": "mz",
            "status": "drafted",
            "action": "create",
            "campaignNumber": "CMP-2024-10-15-004031",
            "isActive": true,
            "parentId": "43503755-db1d-4cef-9851-72360ee6eaa1",
            "campaignName": "LLIN-OCT15a",
            "projectType": "LLIN-mz",
            "hierarchyType": "HIERARCHYTEST",
            "boundaryCode": "",
            "projectId": null,
            "startDate": 1727202600000,
            "endDate": 1727720999000,
            "additionalDetails": {
                "key": 10,
                "beneficiaryType": "HOUSEHOLD"
            },
            "resources": [
            {
                "type": "facility",
                "filename": "update-facility.xlsx",
                "resourceId": "42c04e62-4b7b-4697-b2bd-aa90a212164c",
                "filestoreId": "20420b29-d913-4412-b3bd-34b850e2677b"
            },
            {
                "type": "boundaryWithTarget",
                "filename": "updated-boundary.xlsx",
                "resourceId": "8567db53-450e-465d-a14a-46e2690cf728",
                "filestoreId": "30ae3fd6-b77c-42e7-9a33-e88e29369764"
            },
            {
                "type": "user",
                "filename": "updated-user.xlsx",
                "resourceId": "fcc4a423-6ac5-4ee4-80c2-0f915a95253f",
                "filestoreId": "3c531af7-d923-47cc-b58a-c501a73e749c"
            }
        ],
            "boundaries": [],
            "deliveryRules": [
                {
                    "active": true,
                    "cycleIndex": "1",
                    "deliveries": [
                        {
                            "active": true,
                            "deliveryIndex": "1",
                            "deliveryRules": [
                                {
                                    "ruleKey": 1,
                                    "delivery": {},
                                    "products": [
                                        {
                                            "key": 1,
                                            "count": 1,
                                            "value": "PVAR-2024-05-09-000333"
                                        }
                                    ],
                                    "attributes": [
                                        {
                                            "key": 1,
                                            "value": "1",
                                            "operator": {
                                                "code": "LESS_THAN_EQUAL_TO"
                                            },
                                            "attribute": {
                                                "code": "CAMPAIGN_BEDNET_INDIVIDUAL_LABEL"
                                            }
                                        },
                                        {
                                            "key": 2,
                                            "value": "3",
                                            "operator": {
                                                "code": "LESS_THAN_EQUAL_TO"
                                            },
                                            "attribute": {
                                                "code": "CAMPAIGN_BEDNET_HOUSEHOLD_LABEL"
                                            }
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ],
            "auditDetails": {
                "createdBy": "63a21269-d40d-4c26-878f-4f4486b1f44b",
                "lastModifiedBy": "63a21269-d40d-4c26-878f-4f4486b1f44b",
                "createdTime": 1728983362986,
                "lastModifiedTime": 1728983362995
            }
        },
```

🟢 Success Response (200)

Returns updated campaign with:

  • isActive: false

  • status: "cancelled"

🔁 Idempotency

Safe to call multiple times. Same result is returned.

🧩 Internals

  • Validates inputs

  • Fetches campaign

  • Updates status

  • Produces to Kafka topic

Last updated

Was this helpful?