Add site_code and structured address fields to extraction prompt

The Claude extraction prompt now explicitly asks for site_code (the
Amazon facility code) and structured ship_to address fields (street,
city, state, zip). The site-extractor Lambda prefers these direct
fields when available, falling back to regex for older PO records.
This commit is contained in:
Adam Moussa 2026-04-30 14:42:09 -04:00
parent 194b1aec44
commit 5a86b3c96b
2 changed files with 28 additions and 0 deletions

View file

@ -52,9 +52,14 @@ Analyze the following email and extract structured data. Return ONLY valid JSON
"supplier": {
"name": "string or null"
},
"site_code": "string or null",
"ship_to": {
"name": "string or null",
"address": "string or null",
"street": "string or null",
"city": "string or null",
"state": "string or null",
"zip": "string or null",
"location_code": "string or null",
"attn": "string or null"
},
@ -80,6 +85,13 @@ Rules:
- Extract the PO number from the email (e.g., "2D-18206023")
- Extract all line items with their descriptions, amounts, and metadata
- Ship-to address should include the full address, location code, and attention line
- Ship-to street, city, state, and zip should be parsed from the address into separate fields
- "site_code" is the Amazon facility code (e.g., "SNY5", "DFW6", "WND1") — a 3-5 character alphanumeric code identifying the delivery site. Look for it in:
- The ship-to name, e.g., "Amazon.com Services LLC - SNY5" or "Amazon.com Services LLC (WFB1)"
- The ATTN line, e.g., "ATTN: Wagon Wheel DS - WTN1"
- Line item descriptions, e.g., "WND1 - 2024 - Plumbing PM"
- Anywhere else in the email where a facility code appears
- If the ship-to name IS the site code (e.g., just "DBU2"), use that
- total_amount should be the numeric total in USD
- If a field is not present in the email, set it to null
- Do NOT invent or infer data that is not explicitly in the email

View file

@ -27,6 +27,11 @@ def deserialize_image(image: dict) -> dict:
def extract_site_code(record: dict) -> str | None:
# Prefer the explicit site_code field (set by updated extraction prompt)
direct = (record.get("site_code") or "").strip().upper()
if direct and SITE_CODE_PATTERN.match(direct):
return direct
ship_to = record.get("ship_to") or {}
ship_to_name = ship_to.get("name", "")
@ -68,6 +73,17 @@ def parse_address(record: dict) -> dict:
}
ship_to = record.get("ship_to") or {}
# Prefer structured fields if the extraction prompt provided them
if ship_to.get("street") and ship_to.get("state"):
result["address"] = ship_to["street"]
result["city"] = ship_to.get("city")
result["state"] = ship_to["state"]
result["zip"] = ship_to.get("zip")
parts = [p for p in [result["address"], result["city"], result["state"], result["zip"]] if p]
result["fullAddress"] = ", ".join(parts)
return result
address_text = ship_to.get("address", "")
if not address_text:
return result