Project

General

Profile

Feature #99 » FTWZ_Automation_Handoff.md

Entire Framework implementation strategic plan - Rajesh Gotur, 09/12/2026 05:18 PM

 

FTWZ Automation — Complete Conversation Handoff

Project: FTWZ BOE Import & DTA Sale Automation (Windows VM → AWS Lambda)
Status: Architecture complete, Claude Code prompt ready, ready to build
Date: June 2026


1. Project Context

What This Is

A customs/logistics automation for FTWZ (Free Trade Warehousing Zone) operations.
The client is Endress+Hauser India (IEC: 300014953), managed through Siddhartha Logistics FTWZ Pvt Ltd.
ERP system is Canofy — a Frappe-based product hosted on AWS.

Current State (Broken)

  • Windows VM running Power Automate
  • Selenium script logs into NSDL SEZ Online portal, downloads trade data
  • win32com.client (COM automation) converts .xls → .xlsx — requires live Windows desktop session
  • Python scripts transform the Excel and produce Canofy import files
  • Manual upload to Canofy via Frappe Data Import
  • Brittle, requires human babysitting, silent failures

Target State (Being Built)

  • Fully serverless AWS Lambda (Docker-based)
  • Playwright headless browser replaces Selenium
  • EasyOCR solves CAPTCHA programmatically — no manual intervention
  • xlrd reads .xls directly — no win32com needed
  • Records POSTed to Canofy via Frappe REST API with nested child tables
  • EventBridge daily schedule — fully unattended

2. Two Reference Codebases

2A — AAI Automation (aai_automation_erpnext)

Production Lambda doing a similar job for a different portal (AMAX + KALE).
This is the primary architectural pattern to follow exactly.

Key files:

  • src/lambda_handler.py — orchestrator, two pipelines (run_amax + run_kale), asyncio.run() pattern
  • src/frappe_client.py — Canofy REST API client (headers, record_exists, upload_pdf, create_staging_record)
  • src/schema.py — dataclass payloads + to_api_dict()
  • src/portal_client.py — Playwright async scraper (login, cookie injection, Excel download, PDF generation)
  • Dockerfile — AL2023 base + Playwright Chromium, Docker-based Lambda
  • template.yaml — AWS SAM, 900s timeout, 3008MB, EventBridge schedule
  • .github/workflows/deploy.yml — GitHub Actions CI/CD

Key patterns established:

  • get_secrets() → AWS Secrets Manager
  • resolve_target_date() → 3 date format handlers
  • cleanup_tmp_files() → /tmp cleanup
  • asyncio.run() called twice per pipeline (Phase 1: Excel, Phase 2: PDFs)
  • Per-record try/except — one failure never kills the batch
  • Idempotency via record_exists() before every create

2B — SEZ Automation Framework (sez-automation-framework)

Working Selenium scraper currently on Windows VM. Must be ported to Playwright.

Key files:

  • pages/login_page.py — NSDL login (username, password, CAPTCHA)
  • pages/dashboard_page.py — Excel export navigation + BOE PDF download
  • pages/base_page.py — base Selenium helpers
  • tests/conftest.py — Chrome driver setup (to be removed, replaced by Playwright)
  • tests/test_print_boe.py — BOE PDF print flow (CAPTCHA → search → iframe → PDF)
  • utils/ocr_engine.py — EasyOCR + OpenCV CAPTCHA solver
  • utils/logger.py — structured logger

Portal details extracted:

  • URL: https://sezonline-ndml.co.in/
  • Auth: Username + Password + Image CAPTCHA (EasyOCR solves it)
  • Tour popup after login: remove via JS (.driver-overlay, .driver-popover)
  • Two modules: BILL OF ENTRY and DTA SALE (dropdown select)
  • Excel export: date range → Export button → .xls file
  • BOE PDF: Search by Request ID → View Print → iframe → Original checkbox → OK → new tab → CDP print

3. Existing Transform Scripts (Windows VM — to be ported)

Two Python scripts currently doing the Excel transformation on the VM:

  • FTWZ_BE_Data_Import_transformation_v1.py
  • FTWZ_DTA_Data_Import_transformation_v1.py

Critical findings from these scripts:

win32com block (DELETE in Lambda):

excel = win32com.client.Dispatch("Excel.Application")
wb = excel.Workbooks.Open(file_path)
wb.SaveAs(new_file_path, FileFormat=51)  # .xls → .xlsx

Lambda fix: pd.read_excel(file_path, engine='xlrd') reads .xls directly. No conversion needed.

Excel structure:

  • skiprows=2 — 2 metadata rows before column headers
  • Filter: df[df['CLIENT IEC'].astype(str) == '300014953'] → move to Secrets Manager as JSON list
  • One NSDL row = one item. Header/invoice/shipment data repeated across rows.
  • Complex denormalisation: header + shipment + invoice + items → concat axis=1 → flat per-item rows

PO extraction from item description:

import_df['Item Subtext'] = df['Item Description'].str.extract(r'\^([^^]*)\^')
# Split by '/' → PO Number + PO Item No
# e.g. "^1023637424/10^" → PO Number: "1023637424", PO Item No: "10"

5 QC validation checks (must pass before pushing to Canofy):

  1. Header count == final_df Request ID count
  2. Invoice count == final_df Invoice No count
  3. Item count == len(final_df)
  4. Shipment count matches
  5. Sum checks: Quantity, Assessable Value, BCD must match input totals

Shipment consolidation rules:

  • BE: drop shipment rows where HAWB / HBL No. is null
  • DTA: drop shipment rows where Total Number of Packages is null

Date fields — 3 formats handled:

  • YYYY-DD-MM HH:MM:SS
  • YYYY-MM-DD HH:MM:SS
  • MM/DD/YYYY HH:MM:SS AM/PM
    All converted to YYYY-MM-DD for Canofy.

40 duty fields zero-filled if NaN (identical list for BE and DTA).

BE vs DTA key differences:

Feature BE DTA
IGM fields (shipment) ✅ igm_no, igm_date ❌
Country of Consignment ✅ ❌
Supplier fields (invoice) ✅ supplier_name, supplier_country, suppliers_address ❌
Buyer fields (header) ❌ ✅ buyer_name, buyer_country, buyer_id_type, buyer_id_number, buyer_address, buyer_ie_code
Destination ❌ ✅
goods_measurement_unit (items) ✅ ❌
bdrflag (items) ❌ ✅
Shipment drop rule HAWB null Total Packages null
BOE PDF download ✅ Phase 2 ❌ No PDF

4. Canofy Doctype Specification

Doctype Names (exact, for API URLs)

Doctype API Path
FTWZ BOE Import /api/resource/FTWZ%20BOE%20Import
BOE Import Items child of FTWZ BOE Import
BOE Import Invoices child of FTWZ BOE Import
BOE Import Shipment child of FTWZ BOE Import
FTWZ DTA Sale /api/resource/FTWZ%20DTA%20Sale
DTA Sale Items child of FTWZ DTA Sale
DTA Sale Invoices child of FTWZ DTA Sale
DTA Sale Shipments child of FTWZ DTA Sale
Attachments Details child of BOTH (parentfield: attachments)

Idempotency Key

Both doctypes: request_id (NSDL numeric string, e.g. "172600305544")

GET /api/resource/FTWZ BOE Import?filters=[["request_id","=","172600305544"]]&fields=["name"]&limit=1

Critical Field Quirks (from live Canofy records)

  1. Dual shipment storage — BOTH must be populated:

    • Flat header fields: mawb_mbl_no1, hawb_hbl_no1, igm_no1, etc.
    • Child table: table_all_shipment_details list
  2. Field name inconsistency (do NOT fix — replicate exactly):

    • BE header: uom_for_gross_weight_1 (underscore before 1)
    • DTA header: uom_for_gross_weight1 (no underscore)
  3. Computed totals (Lambda must calculate before POST):

    tot_assval = sum(item.assessable_value_item)
    tot_bcd    = sum(item.basic_customs_duty)
    tot_igst   = sum(item.igst_amount)
    tot_sws    = sum(item.social_welfare_surcharge_on_customs)
    tot_duty   = sum(item.tot_duty_item)
    
  4. workflow_state — always "Pending Review" on creation. Never change.

  5. transaction_id == thoka_noting_number — same NSDL value fills both fields.

  6. Denormalized invoice_no — appears on each item row AND in invoices child table.

  7. 4 empty attachment placeholders always created on record creation:

    • AWB_HBL, Invoice, Packing List, Bill of Entry
    • No file URLs at creation time. PDFs linked later via separate upload+attach call.
  8. DTA has no BOE PDF — skip Phase 2 (PDF download) entirely for DTA pipeline.

Live BE Record (verified from Canofy production)

{
  "doctype": "FTWZ BOE Import",
  "naming_series": "FTWZ-BE-.#####.",
  "workflow_state": "Pending Review",
  "request_id": "172600305544",
  "sez_id": "337",
  "client_iec": "300014953",
  "thoka_noting_number": "1001335",
  "transaction_id": "1001335",
  "boe_type": "Home Consumption",
  "source_of_import": "Abroad",
  "country_of_consignment": "Germany",
  "port_of_origin": "Frankfurt/Main",
  "port_of_discharge": "Chennai (Ex Madras)",
  "port_of_shipment": "Frankfurt/Main",
  "authorised_dealer_code": "6500114",
  "authorised_dealer_name": "HONGKONG AND SHANGHAI BANKING CORPN.LTD.",
  "reimport": "N",
  "previous_import": "N",
  "outwards_remittance_involved": "N",
  "entity_name_importer_name": "SIDDHARTHA LOGISTICS FTWZ PRIVATE LIMITED",
  "entity_id": "3417",
  "sez_name": "SRI  CITY  SEZ (MULTI PRODUCT)",
  "joint_filing_client_details": "ENDRESS HAUSER INDIA PRIVATE LIMITED",
  "client_gstin": "27AAACE5283C1ZV",
  "client_country": "India",
  "client_type": "INDIAN",
  "entity_status_on_previous_day": "Active-Operational",
  "purpose_of_transaction": "Service",
  "request_status": "OutOfCharge",
  "request_submission_date": "2026-03-02",
  "request_assessment_date": "2026-03-02",
  "request_out_of_charge_date": "2026-04-28",
  "transaction_date": "2026-03-02",
  "tot_assval": 732013.46,
  "tot_duty": 66647.8914,
  "tot_bcd": 60588.9921,
  "tot_igst": 0,
  "tot_sws": 6058.8993,
  "igm_no1": "2998942",
  "igm_date1": "2026-02-27",
  "mawb_mbl_no1": "17623105224",
  "mawb_mbl_date1": "2026-02-20",
  "hawb_hbl_no1": "FBG26010506",
  "hawb_hbl_date1": "2026-02-20",
  "uom_for_gross_weight_1": "KGS",
  "gross_weight1": "6.7",
  "total_no_of_packages1": 2,
  "uom_for_packages1": "PKG",
  "items": [
    {
      "doctype": "BOE Import Items",
      "item_description": "^1023637424/10^ ...",
      "cth_no": "90279090",
      "country_of_origin": "Germany",
      "currency": "EURO",
      "exchange_rate": 109.2,
      "quantity": 1,
      "unit_price_invoice_currency": 1785.72,
      "product_value_invoice_currency": 1785.72,
      "cif_value_item_in_inr": 195000.624,
      "assessable_value_item": 195000.62,
      "freight_in_inr": "0",
      "insurance_in_inr": 0,
      "goods_measurement_unit": "PCS",
      "mode_of_transport": "Air",
      "item_type": "Traded Goods",
      "provisional_request": "N",
      "sector_finalized": "Trading And Services",
      "duty_forgone_paid_flag": "DUTY FORGONE",
      "duty_forgone_paid_amount": 16087.55,
      "invoice_no": "9270030204",
      "bcd_to_be_considered_for_calculating_igst": "0",
      "basic_customs_duty": 14625.0468,
      "igst_amount": 0,
      "social_welfare_surcharge_on_customs": 1462.5047,
      "tot_duty_item": 16087.5515,
      "po_number": "1023637424",
      "po_item_no": "10",
      "item_subtext": "1023637424/10",
      "product_match": "No",
      "nccd": 0, "compensation_cess_amount": 0, "surcharge_on_bcd": 0,
      "health_cess_customs": 0, "sapta_bcd": 0, "other_customs_duties": 0,
      "ade_under_section_3_1_duty": "0", "sp_excise_duty_sch_ii": 0,
      "cess_excise": 0, "she_cess_excise": 0, "safeguard": 0,
      "aidc_on_customs": 0, "additional_duty_of_excise_ttw": 0,
      "health_cess_excise": 0, "other_additional_customs_duty": 0,
      "additional_duty_of_excise_nccd_excise": 0, "aidc_on_excise": 0,
      "additional_duty_of_excise_tta": 0, "education_cess_customs": 0,
      "other_additional_central_excise_duty": 0,
      "countervailing_duty_of_additional_customs_duty": 0,
      "other_central_excise_duties": 0, "education_cess_excise": 0,
      "sad": 0, "social_welfare_surcharge_on_gst": 0, "cess_customs": 0,
      "she_cess_customs": 0, "anti_dumping": 0,
      "road_and_infrastructure_cess_on_customs": 0,
      "additional_duty_of_excise_gsi": 0
    }
  ],
  "invoices": [
    {
      "doctype": "BOE Import Invoices",
      "invoice_type": "CIF",
      "invoice_no": "9270030204",
      "invoice_date": "2026-02-19",
      "supplier_name": "Endress Hauser SICK GmbHCo. KG",
      "supplier_country": "Germany",
      "suppliers_address": "Bergener Ring 27 01458 Ottendorf Germany"
    }
  ],
  "table_all_shipment_details": [
    {
      "doctype": "BOE Import Shipment",
      "igm_no": "2998942",
      "igm_date": "2026-02-27",
      "mawb_mbl_no": "17623105224",
      "mawb_mbl_date": "2026-02-20",
      "hawb_hbl_no": "FBG26010506",
      "hawb_hbl_date": "2026-02-20",
      "total_no_of_packages": 2,
      "uom_for_packages": "PKG",
      "gross_weight": 6.7,
      "uom_for_gross_weight": "KGS"
    }
  ],
  "attachments": [
    {"doctype": "Attachments Details", "attachment_type": "AWB_HBL"},
    {"doctype": "Attachments Details", "attachment_type": "Invoice"},
    {"doctype": "Attachments Details", "attachment_type": "Packing List"},
    {"doctype": "Attachments Details", "attachment_type": "Bill of Entry"}
  ]
}

Live DTA Record (verified from Canofy production)

{
  "doctype": "FTWZ DTA Sale",
  "naming_series": "FTWZ-DTA-S-.#####.",
  "workflow_state": "Pending Review",
  "request_id": "262600426675",
  "sez_id": "337",
  "client_iec": "300014953",
  "thoka_noting_number": "2004022",
  "transaction_id": "2004022",
  "boe_type": "Home Consumption",
  "buyer_name": "ENDRESS  HAUSER (INDIA) PRIVATE LIMITED",
  "buyer_ie_code": "300014953",
  "buyer_country": "India",
  "buyer_id_type": "G",
  "buyer_id_number": "27AAACE5283C1ZV",
  "destination": "DTA Unit",
  "previous_procurement": "N",
  "previous_dta_sales": "N",
  "outwards_remittance_involved": "Y",
  "entity_name_importer_name": "SIDDHARTHA LOGISTICS FTWZ PRIVATE LIMITED",
  "entity_id": "3417",
  "sez_name": "SRI  CITY  SEZ (MULTI PRODUCT)",
  "joint_filing_client_details": "ENDRESS HAUSER INDIA PRIVATE LIMITED",
  "client_gstin": "27AAACE5283C1ZV",
  "client_country": "India",
  "client_type": "INDIAN",
  "entity_status_on_previous_day": "Active-Operational",
  "purpose_of_transaction": "Service",
  "request_status": "OutOfCharge",
  "request_submission_date": "2026-06-11",
  "request_assessment_date": "2026-06-11",
  "request_out_of_charge_date": "2026-06-11",
  "transaction_date": "2026-06-11",
  "tot_assval": 27878.2,
  "tot_duty": 5018.0752,
  "tot_bcd": 0,
  "tot_igst": 5018.0752,
  "tot_sws": 0,
  "mawb_mbl_no1": "4570449100",
  "mawb_mbl_date1": "2026-06-05",
  "hawb_hbl_no1": "4570449100",
  "gross_weight1": 81.5,
  "uom_for_gross_weight1": "KGS",
  "total_no_of_packages1": 23,
  "uom_for_packages1": "PKG",
  "items": [
    {
      "doctype": "DTA Sale Items",
      "item_description": "^1023659813/30^ Memosens CLS16E",
      "cth_no": "90278930",
      "country_of_origin": "Germany",
      "currency": "EURO",
      "exchange_rate": 113,
      "quantity": 1,
      "unit_price_invoice_currency": 241.85,
      "product_value_invoice_currency": 241.85,
      "cif_value_item_in_inr": 27329.05,
      "assessable_value_item": 27878.2,
      "freight_in_inr": "0",
      "insurance_in_inr": 0,
      "mode_of_transport": "Land",
      "item_type": "Traded Goods",
      "provisional_request": "N",
      "sector_finalized": "Trading And Services",
      "duty_forgone_paid_flag": "Duty Payable",
      "duty_forgone_paid_amount": 5018.08,
      "invoice_no": "6009106794",
      "bcd_to_be_considered_for_calculating_igst": "0",
      "basic_customs_duty": 0,
      "igst_amount": 5018.0752,
      "social_welfare_surcharge_on_customs": 0,
      "bdrflag": "False",
      "tot_duty_item": 5018.0752,
      "po_number": "1023659813",
      "po_item_no": "30",
      "item_subtext": "1023659813/30",
      "product_match": "No"
    }
  ],
  "invoices": [
    {
      "doctype": "DTA Sale Invoices",
      "invoice_type": "CIF",
      "invoice_no": "6009106794",
      "invoice_date": "2026-06-03"
    }
  ],
  "table_all_shipment_details": [
    {
      "doctype": "DTA Sale Shipments",
      "mawb_mbl_no": "4570449100",
      "mawb_mbl_date": "2026-06-05",
      "hawb_hbl_no": "4570449100",
      "total_no_of_packages": 23,
      "uom_for_packages": "PKG",
      "gross_weight": 81.5,
      "uom_for_gross_weight": "KGS"
    }
  ],
  "attachments": [
    {"doctype": "Attachments Details", "attachment_type": "AWB_HBL"},
    {"doctype": "Attachments Details", "attachment_type": "Invoice"},
    {"doctype": "Attachments Details", "attachment_type": "Packing List"},
    {"doctype": "Attachments Details", "attachment_type": "Bill of Entry"}
  ]
}

5. Target Repository Structure

ftwz_automation/
├── Dockerfile
├── template.yaml
├── samconfig.toml
├── .github/
│   └── workflows/
│       ├── deploy-dev.yml      # auto-trigger on push to main
│       └── deploy-prod.yml     # manual trigger only (workflow_dispatch)
└── src/
    ├── lambda_handler.py       # orchestrator — AAI pattern
    ├── nsdl_portal_client.py   # Playwright scraper — SEZ → Lambda port
    ├── nsdl_parser.py          # Excel transform — win32com scripts → pure pandas
    ├── frappe_client.py        # Canofy REST API — AAI pattern + FTWZ doctypes
    ├── schema.py               # dataclasses + payload builders
    ├── ocr_engine.py           # EasyOCR CAPTCHA solver — from SEZ
    ├── logger.py               # structured CloudWatch logger
    └── requirements.txt

6. Architecture Decisions (Final, Non-Negotiable)

Decision Choice Reason
Browser Playwright async Lambda-proven in AAI; Selenium needs ChromeDriver version mgmt
XLS reading pd.read_excel(engine='xlrd') NSDL exports .xls; xlrd reads directly, no win32com
CAPTCHA EasyOCR + OpenCV Already working in SEZ; fully programmatic, no manual cookie refresh
Pipeline structure Single Lambda, two internal pipelines Matches AAI pattern; simpler deployment
asyncio calls Two per pipeline (Excel download, PDF download) Idempotency check between phases
Canofy integration Frappe REST API POST with nested child tables Direct JSON insert, no Data Import CLI
CLIENT IEC filter Secrets Manager JSON list Not hardcoded — multi-client ready
Error handling Per-record try/except, batch continues One bad record never kills 200 others
Docker image size ~6-7GB (PyTorch CPU + Playwright + EasyOCR) Within Lambda 10GB limit
Env separation DEV / PROD via environment param in event Same Lambda image, different Frappe URLs
Schedule cron(0 2 * * ? *) = 07:30 AM IST Daily unattended run
Timeout 900s Headless browser + bulk processing
Memory 3008MB Headless Chromium requirement
Ephemeral storage 2048MB XLS files + bulk PDFs in /tmp

7. Secrets Manager Schema

Secret name: ftwz-automation

{
  "NSDL_USERNAME": "...",
  "NSDL_PASSWORD": "...",
  "CLIENT_IEC_CODES": "[\"300014953\"]",
  "DEV_FRAPPE_URL": "https://canofy-dev.example.com",
  "DEV_FRAPPE_API_KEY": "...",
  "DEV_FRAPPE_API_SECRET": "...",
  "PROD_FRAPPE_URL": "https://canofy.example.com",
  "PROD_FRAPPE_API_KEY": "...",
  "PROD_FRAPPE_API_SECRET": "..."
}

No NSDL session cookies — EasyOCR solves CAPTCHA programmatically. Fully unattended from day one (key improvement over AAI which needs daily manual cookie refresh).


8. Lambda Handler Event Shape

{
  "from_date": "2026-06-01",
  "to_date": "2026-06-25",
  "pipelines": ["BE", "DTA"],
  "environment": "PROD"
}
  • from_date / to_date: optional, defaults to last 7 days
  • pipelines: optional, defaults to both
  • environment: required — DEV or PROD

9. Pipeline Flow (Both Pipelines)

BE Pipeline

Phase 1: asyncio.run(download_excel("BILL OF ENTRY", from_date, to_date))
           → /tmp/be_trade_data.xls

Phase 2: parse_be_excel(xls_path, client_iec_codes)
           → List[List[dict]]  (grouped by request_id)
           → QC validation (5 checks) — raises if fails

Phase 3: Idempotency check per request_id
           → filter to new_records only

Phase 4: asyncio.run(download_boe_pdfs(new_request_ids))
           → {request_id: /tmp/{request_id}.pdf}

Phase 5-6: For each request_id group:
             build_be_payload(group) → to_api_dict()
             upload_pdf() → file_url
             create_be_record() → record_name
             attach_pdf_to_record()

Phase 7: cleanup_tmp_files()

DTA Pipeline

Same as BE except:
- Module: "DTA SALE"
- No Phase 4 (no PDFs for DTA)
- Uses: parse_dta_excel, record_exists_dta, build_dta_payload, create_dta_record

10. Hard Rules (Non-Negotiable)

  1. No win32com anywhere
  2. No pytest, conftest, selenium
  3. No sleep() — use page.wait_for_selector(), page.wait_for_download(), page.wait_for_url()
  4. No hardcoded credentials
  5. No hardcoded CLIENT IEC — read from Secrets Manager
  6. No file output from parser — returns Python objects only
  7. Per-record errors never crash the batch
  8. Idempotency checked before every create
  9. Both flat header shipment fields AND child table populated
  10. workflow_state always "Pending Review"
  11. transaction_id always equals thoka_noting_number
  12. Totals computed in Lambda before POST
  13. 4 empty attachment placeholders on every record creation
  14. DTA pipeline has no PDF download phase
  15. uom_for_gross_weight_1 (BE) vs uom_for_gross_weight1 (DTA) — replicate exactly, do not normalize
  16. All files complete — no stubs, no TODOs, no pass

11. Build Sequence

1. src/logger.py
2. src/ocr_engine.py
3. src/nsdl_parser.py
4. src/schema.py
5. src/frappe_client.py
6. src/nsdl_portal_client.py
7. src/lambda_handler.py
8. src/requirements.txt
9. Dockerfile
10. template.yaml
11. samconfig.toml
12. .github/workflows/deploy-dev.yml
13. .github/workflows/deploy-prod.yml

Post-build verification:

python -m py_compile src/*.py
grep -r "win32com\|selenium\|sleep(" src/   # must be empty
grep -r "300014953" src/                     # must be empty (no hardcoded IEC)

12. What Is Out of Scope (This Phase)

Item Status
SD File pipeline (SDv1, SDv2) Phase 2 — format spec not yet received
Broker File ingestion Phase 2
Email notifications Handled by Canofy server script
Canofy Doctype creation Already exists in production
Dashboard / monitoring UI CloudWatch + structured logs sufficient

13. Deliverable Already Produced

claude_code_prompt.md (~49K tokens) — Complete Claude Code build prompt containing:

  • All 16 reference source files embedded inline (AAI Lambda + SEZ Selenium)
  • Both live Canofy records as JSON
  • All 13 per-file build instructions
  • 17 hard rules
  • Build sequence with verification steps

To use: Open Claude Code in a new ftwz_automation/ repo, paste the entire claude_code_prompt.md as first message.


14. Open Questions (Pre-Production)

# Question Impacts
Q1 NSDL date range strategy — last N days or explicit from/to per EventBridge trigger? resolve_date_range() default logic
Q2 Does DTA Sale have a BOE PDF on NSDL portal under Search Request? run_dta_pipeline() Phase 4
Q3 Is FTWZ Automation Error Log doctype already in Canofy? frappe_client.push_error_log()
Q4 Should Lambda post a success notification to Canofy after each run? lambda_handler.py final block
Q5 Are there other SEZ IDs / FTWZ entities beyond 337 / 3417? Filter logic in nsdl_parser.py
Q6 AWS ECR repository URL for ftwz-automation? template.yaml + deploy.yml
(9-9/10)