> For the complete documentation index, see [llms.txt](https://docs.digit.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.digit.org/health/v2.0/design/architecture/low-level-design/services/console-services/project-factory-campaign-manager/manage-campaign-apis/update-ongoing-campaign.md).

# Update Ongoing Campaign

## Overview

This document details the low-level design for handling campaign creation and update flows when a parent campaign is present. The system supports hierarchical campaigns, boundary inheritance, resource template generation, and robust retry mechanisms. This design aims to ensure data consistency, correct parent-child relationships, and efficient error recovery.

***

## Data Model Changes

#### Database: Campaign Details Table

* **New Columns**
  * `isActive` (boolean): Indicates if the campaign is currently active.
  * `parentId` (string): References the parent campaign’s unique ID, if any.

```sql
ALTER TABLE CampaignDetails
  ADD COLUMN isActive BOOLEAN DEFAULT TRUE,
  ADD COLUMN parentId VARCHAR(64) NULL;
```

***

## Request Validation Logic

#### Parent Campaign Validation

* **If `parentId` is present in the request:**
  * **On `create` action:**
    * Parent campaign (`parentId`) must exist and `isActive = true`.
  * **On `update` action:**
    * Parent campaign (`parentId`) must exist and `isActive = false` (inactive).

***

## Boundary Management Logic

* **For child campaigns:**
  * The `boundaries` array in the request must contain only new boundaries.
  * Existing boundaries are fetched from the parent campaign.
  * Merged boundaries = parent boundaries + new boundaries (for use in template/resource generation).

***

## Resource & Template Generation

#### On Campaign Creation (with Parent Campaign)

* Generate templates for all three types: **boundary**, **user**, **facility**.
* If `actionInUrl = create` and `parentId` is present, templates are generated freshly using both parent and new boundaries.

#### On Campaign Update

* For newly added boundaries, create new projects/resources only for those.
* If existing targets are updated, call update on the respective project with new target mappings.
* Facility and user sheets can be edited: updating these updates related mappings (ProjectFacility, ProjectStaff).

***

## Retry Mechanism

* If campaign creation or update fails, a retry API allows the process to restart from the failure point.
* Retry is stateful and resumes based on the persisted CampaignDetails and status.

**Retry API Example:**

```http
POST /project-factory/v1/project-type/retry
Body: {
  CampaignDetails: { ... }, // Full campaign object
  RequestInfo: { ... }
}
```

***

## Campaign Object Structure

* See below for sample fields (simplified):

```json
{
  "id": "campaign-uuid",
  "tenantId": "mz",
  "status": "drafted",
  "action": "create",
  "campaignNumber": "...",
  "isActive": true,
  "parentId": "parent-campaign-uuid",
  "campaignName": "...",
  "projectType": "...",
  "hierarchyType": "...",
  "boundaries": [...],
  "resources": [
    { "type": "facility", "filename": "...", "resourceId": "...", "filestoreId": "..." },
    { "type": "boundaryWithTarget", "filename": "...", "resourceId": "...", "filestoreId": "..." },
    { "type": "user", "filename": "...", "resourceId": "...", "filestoreId": "..." }
  ],
  "deliveryRules": [...],
  "auditDetails": { ... }
}
```

* After each update and once the campaign is in the "Created" state, templates are consolidated for future updates.

***

## Update & Multiple Update Handling

* After a campaign reaches the "Created" state:
  * Uploaded template sheets (Facility, User, Target) are consolidated back to the initial format.
  * Any subsequent update is handled as the first update (fresh diff against the current state).

***

## Edit Mappings in Update Flow

* In the update flow, facility mappings to boundary codes can be edited and toggled (active/inactive).
* Updates propagate to ProjectFacility and ProjectStaff mapping tables.

***

## Sequence Flow

1. **Request** received with or without `parentId`.
2. **Validation:**
   * If `parentId` present, validate parent state as per action.
3. **Boundary merge:**
   * To create, merge the parent and new boundaries.
   * For updates, only new boundaries are considered for new projects.
4. **Template/Resource Generation:**
   * Generate templates for relevant types (boundary, user, facility).
   * Edit and manage sheets/mappings as per user input.
5. **Retry:**
   * On failure, retry resumes from the last state using the latest CampaignDetails object.

***

## Error & Edge Case Handling

* **Validation Errors:**
  * If the parent campaign is not in the required state, reject the request.
  * If new boundaries overlap with the parent, reject or merge as per the business rule.
* **Retry Errors:**
  * If the retry fails repeatedly, log the state and escalate for manual intervention.

***

{% hint style="info" %}
Points to consider:

* All actions logged with audit details (user, timestamp).
* Only authorised roles can create/update hierarchical campaigns.
* Parent-child relationships can be extended to deeper hierarchies if needed.
* Additional resource/template types can be added.
* Retry logic can be enhanced for partial retries and granular checkpoints.
  {% endhint %}

***

## Sample Payload

<details>

<summary>Sample Payload</summary>

````
```
   "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
            }
        },
```
````

</details>

**Multiple updates to a Campaign**

1. Once the ongoing campaign is updated and reaches the "Created" state, the updated sheet templates (i.e., Facility, User, and Target) are consolidated back into the format used during the initial "Create" flow.
2. This ensures that when you attempt to update the campaign again, it will be treated as the first update.

**Retry API Payload**

<details>

<summary>Sample Payload</summary>

````
```
   "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
            }
        },
```
````

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.digit.org/health/v2.0/design/architecture/low-level-design/services/console-services/project-factory-campaign-manager/manage-campaign-apis/update-ongoing-campaign.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
