---
type: redmine-readme
project: Canofy Process Standardization
subject: Frappe-side trigger for Phase B: NSDL Sync Run DocType and daily scheduled job
story_key: nsdl-frappe-trigger-sync-run
generated_at: 2026-10-15T16:16:51+05:30
story_type: feature
attachments:
  - file: nsdl-frappe-trigger-sync-run_20261015-1616__nsdl_sync_run.json
    description: NSDL Sync Run DocType definition
  - file: nsdl-frappe-trigger-sync-run_20261015-1616__nsdl_sync_scheduled_job.py
    description: Daily scheduled job that calls the Phase B endpoint
---

# Frappe-side trigger for Phase B: NSDL Sync Run DocType and daily scheduled job

> Each client's Frappe site starts Phase B by calling the AWS endpoint from a daily scheduled job and records every trigger in an `NSDL Sync Run` audit document that Phase B later updates.

## 1. Summary
Phase B delivers one client's staged records, and it must know which client is calling. This story adds the Frappe half: an `NSDL Sync Run` DocType, a scheduled job `trigger_nsdl_sync` registered in `hooks.py` as a daily event, and a single configuration record (`NSDL SEZ DELIVER PENDING` in `API Configuration - Canofy`) that holds the endpoint, the API key and the client identity. Phase B updates the Sync Run document with the outcome. The source was added to the `canofy_tcs` app on the local WSL bench and verified end to end on the local site `frappe.local` through a tunnel. Deployment to the production host is not done.

## 2. Requirement
| # | Requirement | Source | Status |
|---|---|---|---|
| R1 | Frappe triggers Phase B for its own client only | Blueprint | Done (local site) |
| R2 | Every trigger leaves an audit document, updated by Phase B | Build Spec | Done (local site) |
| R3 | Client identity configured inside Frappe, without editing `site_config.json` | user (2026-09-15) | Done |
| R4 | The Lambda repo holds no Frappe code | user (2026-09-15) | Done (`frappe_app/` excluded from commits) |

## 3. Decisions
| Decision | Options considered | Why this one | Date |
|---|---|---|---|
| Where the client name lives | `site_config.json`; new field; `headers` JSON on the existing API Configuration record | The record already has an "Additional Static Headers" field; one place holds URL, key and client identity and is editable in the UI | 2026-09-15 |
| Where to run `bench migrate` | Production; local dev site | Only the local site `frappe.local` was available; the production host of the TEST customer site was not identified | 2026-09-15 |
| Repo for the Frappe files | Same repo; separate Frappe repo | User: the Lambda repo is for the microservice only | 2026-09-15 |

The client name must equal the key in the AWS secret's `CLIENTS` block, which has no guaranteed relation to the site's own name; this is why it cannot be inferred.

## 4. Logic & Workflow
`daily scheduler -> trigger_nsdl_sync -> read API Configuration record -> create NSDL Sync Run (Triggered) -> POST to API Gateway with X-Frappe-Client -> 202 -> Phase B delivers -> Phase B updates the Sync Run`

1. The job loads the `NSDL SEZ DELIVER PENDING` record. A missing record, or a missing `X-Frappe-Client` entry, is written to the Error Log instead of failing the scheduler.
2. It creates the Sync Run with status `Triggered` and sends its name to the endpoint.
3. API Gateway maps the header to `client_name` and starts Phase B asynchronously.
4. Phase B updates the document: `Delivered`, `No Pending Records` or `Failed`.

## 5. Files & Components Changed
| File / resource | Type | Change | Purpose |
|---|---|---|---|
| `nsdl_sync_run.json` | DocType | New, autoname `NSR-{client_name}-{run_date}-{#####}` | Audit document |
| `nsdl_sync_scheduled_job.py` | Scheduled job | New; reads client name from the config record headers | Trigger Phase B |
| `canofy_tcs` app, `hooks.py` | Frappe app | `daily` entry in `scheduler_events` | Register the job |
| `canofy_tcs` app, `import_documents/doctype/nsdl_sync_run/` | Frappe app | DocType folder with controller | Install the DocType |

## 6. Configuration & Deployment
| Item | Value | Where |
|---|---|---|
| Configuration record | `NSDL SEZ DELIVER PENDING` in `API Configuration - Canofy` | Frappe site |
| URL | Phase B API Gateway `/sez/deliver-pending` | Config record |
| API key header | `x-api-key`; key value from API Gateway (not stored here) | Config record |
| Headers JSON | `{"X-Frappe-Client": "<client key in the AWS secret>"}` | Config record |
| `server_script_enabled` | 1 in `common_site_config.json` (bench-wide) | Needed on the local site, where a Server Script blocked creation |

Steps on a site: install the app changes, run `bench migrate`, create the config record.

## 7. Testing
| Test | Data / Site | Expected | Actual | Status |
|---|---|---|---|---|
| Phase B reaches a local site | Cloudflare quick tunnel to `frappe.local`, synthetic request ID | Record created | HTTP 403 until the flag was set in `common_site_config.json`, then created | Pass after fix |
| Scheduled job on the local site | Manual call of `trigger_nsdl_sync()` | Sync Run created | First two attempts logged "NSDL Sync misconfigured" because the config record was missing; after creating it, a Sync Run was created | Pass after fix |
| End to end | Local site, real NSDL data | Records and PDFs delivered, Sync Run updated | 28 of 28 records, 28 PDFs, Sync Run updated; a leftover synthetic record made the status `Failed` until deleted | Pass |

## 8. Known Limitations & Open Items
- Not confirmed: deployment of these files to the production Frappe host, and the `daily` scheduler running there.
- The local test used a temporary tunnel URL that changes on restart.
- Once AWS-side EventBridge triggers Phase B (see `nsdl-eventbridge-scheduling`), the Frappe job is redundant; disabling it is the user's responsibility.
- Subscribing an endpoint to the alerts topic is outstanding.

## 9. Status
| Item | Value |
|---|---|
| Branch | Frappe changes are in the `canofy_tcs` source on the local bench; the Lambda repo carries only the staging copies in `frappe_app/` (untracked) |
| Commits | None in the Lambda repo for these files. Not confirmed for the Frappe repo |
| PR | None |
| Deployed to | Local dev site `frappe.local` only |

## 10. References
Related stories: `nsdl-lambda-core-pipeline` (Phase B), `nsdl-eventbridge-scheduling`, `nsdl-architecture-documentation`.
