{
  "name": "job.2_email_classifier",
  "nodes": [
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT \n  ecs.email_id,\n  e.subject,\n  e.body\nFROM\n  email_classification_status ecs\nJOIN\n  emails e ON ecs.email_id = e.email_id\nORDER BY\n  ecs.email_id ASC \nLIMIT 10;",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        -880,
        160
      ],
      "id": "d5d38764-dd43-4337-a90e-efe4e1df96d8",
      "name": "Execute EMAIL_RECEIVED Query",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "events",
          "mode": "list",
          "cachedResultName": "events"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "event_type": "EMAIL_CLASSIFIED",
            "payload": "={{{\nemail_id: $json.email_id,\ncategory: $json.category,\nconfidence: $json.confidence,\nrole_title: $json.role_title,\nrole_id:$json.external_ref_id,\nupcoming_date:$json.extracted_date,\ndate_context:$json.date_context,\nllm_company_guess:$json.company_name,\nsource : $json.source\n}\n}}",
            "triggered_by": "system",
            "application_id": "={{ null }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "event_id",
              "displayName": "event_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "event_type",
              "displayName": "event_type",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "application_id",
              "displayName": "application_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "payload",
              "displayName": "payload",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "object",
              "canBeUsedToMatch": true
            },
            {
              "id": "triggered_by",
              "displayName": "triggered_by",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "created_at",
              "displayName": "created_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true,
              "removed": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        48,
        -16
      ],
      "id": "1ac9147c-bc77-4b19-9a88-566b5b1780a7",
      "name": "Emit Classification Event",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "http://classifier-api:8000/classify",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{\n{\n    \"email_id\": $json.email_id,\n    \"subject\": $json.subject,\n    \"body\": $json.body\n}\n}}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -656,
        160
      ],
      "id": "6e450449-d313-47c1-904d-f52f236aba5b",
      "name": "HTTP Request"
    },
    {
      "parameters": {
        "jsCode": " return items.map(item => {\n   // 'item.json' here will be the direct JSON response from your classifier-api\n   const apiResponse = item.json;\n\n   // Basic validation to ensure we got a valid response\n   if (!apiResponse || apiResponse.email_id === undefined || apiResponse.category === undefined) {\n       throw new Error(\"Invalid or incomplete response from Classifier API.\");\n   }\n\n   // Extract data directly from the API response\n   const email_id = apiResponse.email_id;\n   const category = apiResponse.category;\n   const confidence = apiResponse.confidence;\n   const extracted_data = apiResponse.extracted_data || {}; // Ensure it's an object even if null\n\n   return {\n     json: {\n       email_id: email_id,\n       category: category,\n       confidence: confidence,\n       // Extracted data fields are now nested under 'extracted_data'\n       // We are flattening them here for easier access in subsequent nodes\n       company_name: extracted_data.company_name || null,\n       role_title: extracted_data.role_title || null,\n       external_ref_id: extracted_data.external_ref_id || null,\n       extracted_date: extracted_data.extracted_date || null,\n       date_context: extracted_data.date_context || null,\n       job_links: { \"links\": extracted_data.job_links || [] }\n     }\n   };\n });"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -464,
        160
      ],
      "id": "34c488ae-1027-496c-841c-80d2ed197c5a",
      "name": "Insert into links table"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "fd432a46-d9a9-4c9b-b243-ecac61545097",
              "leftValue": "={{ $json.category === 'OPPORTUNITY_SIGNAL' }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -272,
        160
      ],
      "id": "0c75c319-c61c-474b-a217-0cb85228530e",
      "name": "If links or No links in body"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "2120ff6d-b29a-4c48-8299-c01bd600274e",
              "leftValue": "={{ $json.job_links.links.length > 0 }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        16,
        304
      ],
      "id": "bf9e4a60-cb64-46dc-9a4c-94b23fad5f89",
      "name": "if links or no links"
    },
    {
      "parameters": {
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "manual_review_queue",
          "mode": "list",
          "cachedResultName": "manual_review_queue"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "email_id": "={{ $json.email_id }}",
            "reason": "=No links found",
            "status": "llm_revision"
          },
          "matchingColumns": [
            "id"
          ],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": false,
              "defaultMatch": true,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "email_id",
              "displayName": "email_id",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "reason",
              "displayName": "reason",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "displayName": "status",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "created_at",
              "displayName": "created_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true,
              "removed": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        336,
        464
      ],
      "id": "541fb9d2-7a55-41b9-bccd-d5601edde766",
      "name": "Insert to MQP table - no links",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "opportunity_processing_queue",
          "mode": "list",
          "cachedResultName": "opportunity_processing_queue"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "email_id": "={{ $json.email_id }}",
            "job_links": "={{ $json.job_links }}"
          },
          "matchingColumns": [
            "id"
          ],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": false,
              "defaultMatch": true,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "email_id",
              "displayName": "email_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "job_links",
              "displayName": "job_links",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "object",
              "canBeUsedToMatch": true
            },
            {
              "id": "status",
              "displayName": "status",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "created_at",
              "displayName": "created_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "processed_at",
              "displayName": "processed_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true,
              "removed": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        336,
        208
      ],
      "id": "9a257b2c-bae9-466f-a6fe-70117a536585",
      "name": "Insert in OPQ table",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "DELETE FROM email_classification_status \nWHERE email_id = {{ $json.payload.email_id }};",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        304,
        -16
      ],
      "id": "54b68303-196e-40ac-a848-3b587627380f",
      "name": "DELETE from ECS table for others",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "DELETE FROM email_classification_status \nWHERE email_id = {{ $json.email_id }};",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        608,
        208
      ],
      "id": "7328d220-72fb-4eda-bd5c-040cd075c6f0",
      "name": "DELETE from ECS table for OPPO_SIGNAL",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "DELETE FROM email_classification_status\nWHERE email_id = {{ $json.email_id }};",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        624,
        464
      ],
      "id": "7fdd956a-372e-49b6-9ee6-bc44e5776670",
      "name": "Delete from ECS",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "fieldToSplitOut": "job_links.links",
        "include": "selectedOtherFields",
        "fieldsToInclude": "id, email_id",
        "options": {
          "destinationFieldName": "job_url"
        }
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        1040,
        208
      ],
      "id": "400e1aa3-1ce8-4819-930a-f7ee0e210ae6",
      "name": "Split Out For Links"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT id, email_id, job_links FROM opportunity_processing_queue WHERE\n     status = 'pending' ORDER BY created_at ASC LIMIT 50;",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        832,
        208
      ],
      "id": "975851b4-6c7b-4739-aabe-d34f0064affa",
      "name": "Fetch from OPQ",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "compare": "selectedFields",
        "fieldsToCompare": "link_text",
        "options": {
          "removeOtherFields": true
        }
      },
      "type": "n8n-nodes-base.removeDuplicates",
      "typeVersion": 2,
      "position": [
        1664,
        208
      ],
      "id": "2b0c0762-f70e-45eb-9719-18047c71733d",
      "name": "Remove Duplicates"
    },
    {
      "parameters": {
        "jsCode": "  // Input: { id: 1, email_id: 22, job_url: \"linkA\" }\n const crypto = require('crypto');\n\n return items.map(item => {\n   const jobUrl = item.json.job_url;\n   const queueEntryId = item.json.id;\n   const emailId = item.json.email_id;\n\n   const md5Hash = crypto.createHash('md5').update(jobUrl).digest('hex');\n\n     return {\n       json: {\n         queue_entry_id: queueEntryId,\n         email_id: emailId,\n         id: md5Hash,\n         job_url: jobUrl,\n         apply_url: jobUrl,\n         source_type: 'email',\n         source_id: emailId.toString(),\n         discovered_at: new Date().toISOString(),\n       }\n     };\n   });"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1248,
        208
      ],
      "id": "2daceb7b-6655-49b1-b6de-b8a84dc278e7",
      "name": "Normalize for opportunities"
    },
    {
      "parameters": {
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "table": {
          "__rl": true,
          "value": "opportunities",
          "mode": "list",
          "cachedResultName": "opportunities"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "id": "={{ $json.id }}",
            "job_url": "={{ $json.apply_url }}",
            "apply_url": "={{ $json.apply_url }}",
            "source_type": "={{ $json.source_type }}",
            "source_id": "={{ $json.source_id }}",
            "discovered_at": "={{ $json.discovered_at }}",
            "link_text": "={{ $json.queue_entry_id }}"
          },
          "matchingColumns": [
            "id"
          ],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": true,
              "defaultMatch": true,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "job_url",
              "displayName": "job_url",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "apply_url",
              "displayName": "apply_url",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "link_text",
              "displayName": "link_text",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "score",
              "displayName": "score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "reasons",
              "displayName": "reasons",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "object",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "discovered_at",
              "displayName": "discovered_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true
            },
            {
              "id": "source_type",
              "displayName": "source_type",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "source_id",
              "displayName": "source_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "metadata",
              "displayName": "metadata",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "skipOnConflict": true
        }
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        1456,
        208
      ],
      "id": "4a3d06d7-72b5-41c9-832b-6ed8e2ac93ad",
      "name": "insert opportunities",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "DELETE FROM opportunity_processing_queue\nWHERE id = {{ $json.link_text }};",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        1872,
        208
      ],
      "id": "4be5dc0d-ec17-44c2-b392-c89e545b6237",
      "name": "Delete from OPQ table",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "path": "21681f63-9a20-492f-bde9-3a6cde82585a",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -1088,
        160
      ],
      "id": "2ba0e258-83a1-4e86-8048-370b8cc86955",
      "name": "Trigger from wf1"
    }
  ],
  "connections": {
    "Execute EMAIL_RECEIVED Query": {
      "main": [
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Emit Classification Event": {
      "main": [
        [
          {
            "node": "DELETE from ECS table for others",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Insert into links table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert into links table": {
      "main": [
        [
          {
            "node": "If links or No links in body",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If links or No links in body": {
      "main": [
        [
          {
            "node": "Emit Classification Event",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "if links or no links",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "if links or no links": {
      "main": [
        [
          {
            "node": "Insert in OPQ table",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Insert to MQP table - no links",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert in OPQ table": {
      "main": [
        [
          {
            "node": "DELETE from ECS table for OPPO_SIGNAL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert to MQP table - no links": {
      "main": [
        [
          {
            "node": "Delete from ECS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DELETE from ECS table for others": {
      "main": [
        []
      ]
    },
    "Split Out For Links": {
      "main": [
        [
          {
            "node": "Normalize for opportunities",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch from OPQ": {
      "main": [
        [
          {
            "node": "Split Out For Links",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Remove Duplicates": {
      "main": [
        [
          {
            "node": "Delete from OPQ table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize for opportunities": {
      "main": [
        [
          {
            "node": "insert opportunities",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "insert opportunities": {
      "main": [
        [
          {
            "node": "Remove Duplicates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DELETE from ECS table for OPPO_SIGNAL": {
      "main": [
        [
          {
            "node": "Fetch from OPQ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger from wf1": {
      "main": [
        [
          {
            "node": "Execute EMAIL_RECEIVED Query",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "availableInMCP": false
  },
  "versionId": "4e2435f8-c842-44aa-be74-5550e69e3180",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "xLjJbuDddO3Bcq4p",
  "tags": []
}