Feature #99 » FTWZ_Automation_Handoff.md
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
-
xlrdreads.xlsdirectly — 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 ENTRYandDTA SALE(dropdown select) - Excel export: date range → Export button →
.xlsfile - 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.pyFTWZ_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):
- Header count == final_df Request ID count
- Invoice count == final_df Invoice No count
- Item count == len(final_df)
- Shipment count matches
- 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 Packagesis null
Date fields — 3 formats handled:
YYYY-DD-MM HH:MM:SSYYYY-MM-DD HH:MM:SS-
MM/DD/YYYY HH:MM:SS AM/PM
All converted toYYYY-MM-DDfor 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)
-
Dual shipment storage — BOTH must be populated:
- Flat header fields:
mawb_mbl_no1,hawb_hbl_no1,igm_no1, etc. - Child table:
table_all_shipment_detailslist
- Flat header fields:
-
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)
- BE header:
-
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) -
workflow_state — always
"Pending Review"on creation. Never change. -
transaction_id == thoka_noting_number — same NSDL value fills both fields.
-
Denormalized invoice_no — appears on each item row AND in invoices child table.
-
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.
-
-
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 —DEVorPROD
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)
- No
win32comanywhere - No
pytest,conftest,selenium - No
sleep()— usepage.wait_for_selector(),page.wait_for_download(),page.wait_for_url() - No hardcoded credentials
- No hardcoded
CLIENT IEC— read from Secrets Manager - No file output from parser — returns Python objects only
- Per-record errors never crash the batch
- Idempotency checked before every create
- Both flat header shipment fields AND child table populated
-
workflow_statealways"Pending Review" -
transaction_idalways equalsthoka_noting_number - Totals computed in Lambda before POST
- 4 empty attachment placeholders on every record creation
- DTA pipeline has no PDF download phase
-
uom_for_gross_weight_1(BE) vsuom_for_gross_weight1(DTA) — replicate exactly, do not normalize - 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
|