{
  "name": "WF-1: \u30ea\u30fc\u30c9\u80b2\u6210\u30b9\u30c6\u30c3\u30d7\u30e1\u30fc\u30eb (Daily Cron)",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 0 * * *"
            }
          ]
        }
      },
      "id": "812c1de2-5977-4da9-952c-326d4bad3079",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.1,
      "position": [
        0,
        0
      ]
    },
    {
      "parameters": {
        "url": "https://fwruumlkxzfihlmygrww.supabase.co/rest/v1/email_templates",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "is_active",
              "value": "eq.true"
            },
            {
              "name": "order",
              "value": "step.asc"
            },
            {
              "name": "select",
              "value": "id,step,name,subject,html_body,attachment_url"
            }
          ]
        },
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpCustomAuth"
      },
      "id": "5f749b7c-32e4-4b8d-973e-21563a2a3808",
      "name": "HTTP Request: \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u53d6\u5f97",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        240,
        0
      ],
      "credentials": {
        "httpCustomAuth": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000
    },
    {
      "parameters": {
        "url": "https://fwruumlkxzfihlmygrww.supabase.co/rest/v1/email_subscribers",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "status",
              "value": "eq.pending"
            },
            {
              "name": "step_email_stage",
              "value": "gt.0"
            },
            {
              "name": "select",
              "value": "id,email,step_email_stage,subscribed_at"
            }
          ]
        },
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpCustomAuth"
      },
      "id": "e964906c-4f2d-422a-bdca-d3089b10ce6e",
      "name": "HTTP Request: \u30ea\u30fc\u30c9\u53d6\u5f97",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        480,
        0
      ],
      "credentials": {
        "httpCustomAuth": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000
    },
    {
      "parameters": {
        "jsCode": "// ============================================================\n// WF-1: Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f (\u4fee\u6b63\u7248)\n// \u4e0a\u6d41\u30ce\u30fc\u30c9\u306e\u30c7\u30fc\u30bf\u306e\u307f\u4f7f\u7528\u3002$httpRequest \u306f\u4f7f\u308f\u306a\u3044\u3002\n// ============================================================\n\n// Step 1: \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u53d6\u5f97\uff08\u4e0a\u6d41\u30ce\u30fc\u30c9\u304b\u3089\uff09\nconst templateItems = $(\"HTTP Request: \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u53d6\u5f97\").all();\nlet templates = [];\n\n// HTTP\u30ec\u30b9\u30dd\u30f3\u30b9\u304c\u914d\u5217\u306e\u5834\u5408\u3068\u3001\u76f4\u63a5\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u5834\u5408\u306b\u5bfe\u5fdc\nif (templateItems.length === 1 && Array.isArray(templateItems[0].json)) {\n  templates = templateItems[0].json;\n} else {\n  templates = templateItems.map(item => item.json);\n}\ntemplates.sort((a, b) => (a.step || 0) - (b.step || 0));\n\nif (templates.length === 0) {\n  return [];\n}\n\n// Step 2: \u30b5\u30d6\u30b9\u30af\u30e9\u30a4\u30d0\u30fc\u53d6\u5f97\uff08\u4e0a\u6d41\u30ce\u30fc\u30c9\u304b\u3089\uff09\nconst subscriberItems = $(\"HTTP Request: \u30ea\u30fc\u30c9\u53d6\u5f97\").all();\nlet allSubscribers = [];\n\nif (subscriberItems.length === 1 && Array.isArray(subscriberItems[0].json)) {\n  allSubscribers = subscriberItems[0].json;\n} else {\n  allSubscribers = subscriberItems.map(item => item.json);\n}\n\nif (allSubscribers.length === 0) {\n  return [];\n}\n\n// Step 3: \u9001\u4fe1\u5bfe\u8c61\u3092\u7d5e\u308a\u8fbc\u3080\nconst now = new Date();\nconst results = [];\n\nfor (const subscriber of allSubscribers) {\n  const stage = subscriber.step_email_stage || 0;\n  if (stage >= templates.length) continue;\n\n  const template = templates[stage];\n  const subscribedAt = new Date(subscriber.subscribed_at);\n  const daysSinceSignup = Math.floor(\n    (now.getTime() - subscribedAt.getTime()) / (1000 * 60 * 60 * 24)\n  );\n\n  if (daysSinceSignup >= (template.step || 0)) {\n    const unsubscribeUrl = \"https://solve-wise.com/unsubscribe?email=\"\n      + encodeURIComponent(subscriber.email);\n    const bodyHtml = (template.html_body || \"\")\n      .replace(/\\{\\{email\\}\\}/g, subscriber.email)\n      .replace(/\\{\\{attachment_url\\}\\}/g, template.attachment_url || \"\")\n      .replace(/\\{\\{unsubscribe_url\\}\\}/g, unsubscribeUrl);\n\n    results.push({\n      json: {\n        subscriber: subscriber,\n        template: template,\n        bodyHtml: bodyHtml\n      }\n    });\n  }\n}\n\nreturn results;\n"
      },
      "id": "23ca953c-ec88-4b8d-a3f1-d4e5f6a7b890",
      "name": "Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        720,
        0
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.resend.com/emails",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Idempotency-Key",
              "value": "=wf1:{{ $json.subscriber.email }}:step{{ $json.template.step }}"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ from: \"SolveWise <noreply@solve-wise.com>\", to: [$json.subscriber.email], subject: $json.template.subject, html: $json.bodyHtml }) }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "id": "75ce2126-d257-4f9a-a431-03234bfd879d",
      "name": "HTTP Request: Resend\u9001\u4fe1",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1440,
        -96
      ],
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "method": "PATCH",
        "url": "=https://fwruumlkxzfihlmygrww.supabase.co/rest/v1/email_subscribers?id=eq.{{ $('Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f').item.json.subscriber.id }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Prefer",
              "value": "return=minimal"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ step_email_stage: $(\"Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f\").item.json.subscriber.step_email_stage + 1, last_email_sent_at: $now.toISO() }) }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpCustomAuth"
      },
      "id": "87b42ff2-c845-489b-aa8d-5c1b9e356fc0",
      "name": "HTTP Request: \u30b9\u30c6\u30fc\u30b8\u66f4\u65b0",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1680,
        -96
      ],
      "credentials": {
        "httpCustomAuth": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://fwruumlkxzfihlmygrww.supabase.co/rest/v1/step_email_log",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Prefer",
              "value": "return=minimal"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ subscriber_id: $(\"Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f\").item.json.subscriber.id, template_step: $(\"Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f\").item.json.template.step, template_name: $(\"Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f\").item.json.template.name, subject: $(\"Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f\").item.json.template.subject, status: \"sent\" }) }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpCustomAuth"
      },
      "id": "86467fbd-dc2c-4087-838c-15415aecaf79",
      "name": "HTTP Request: step_email_log\u8a18\u9332",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1920,
        -96
      ],
      "credentials": {
        "httpCustomAuth": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://fwruumlkxzfihlmygrww.supabase.co/rest/v1/step_email_log",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Prefer",
              "value": "return=minimal"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({ subscriber_id: $(\"Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f\").item.json.subscriber.id, template_step: $(\"Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f\").item.json.template.step, template_name: $(\"Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f\").item.json.template.name, subject: $(\"Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f\").item.json.template.subject, status: \"failed\", error_message: ($json.error?.message || $json.message || JSON.stringify($json)).slice(0, 500) }) }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpCustomAuth"
      },
      "id": "wf1-step-email-log-failed",
      "name": "HTTP Request: step_email_log\u8a18\u9332 (failed)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1680,
        96
      ],
      "credentials": {
        "httpCustomAuth": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000
    },
    {
      "parameters": {
        "batchSize": 1,
        "options": {}
      },
      "id": "b1c2d3e4-f5a6-7890-bcde-f01234567891",
      "name": "SplitInBatches: 1\u4ef6\u305a\u3064",
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        860,
        0
      ]
    },
    {
      "parameters": {
        "method": "PATCH",
        "url": "=https://fwruumlkxzfihlmygrww.supabase.co/rest/v1/email_subscribers?status=eq.pending&step_email_stage=eq.0&subscribed_at=lt.{{ new Date(Date.now() - 2*24*3600*1000).toISOString() }}",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Prefer",
              "value": "return=minimal"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\"step_email_stage\": 1}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpCustomAuth"
      },
      "id": "c2d3e4f5-a6b7-8901-cdef-012345678912",
      "name": "Stuck Recovery: stage=0 \u2192 1",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        240,
        200
      ],
      "credentials": {
        "httpCustomAuth": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000
    }
  ],
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "HTTP Request: \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u53d6\u5f97",
            "type": "main",
            "index": 0
          },
          {
            "node": "Stuck Recovery: stage=0 \u2192 1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request: \u30c6\u30f3\u30d7\u30ec\u30fc\u30c8\u53d6\u5f97": {
      "main": [
        [
          {
            "node": "HTTP Request: \u30ea\u30fc\u30c9\u53d6\u5f97",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request: \u30ea\u30fc\u30c9\u53d6\u5f97": {
      "main": [
        [
          {
            "node": "Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: \u9001\u4fe1\u5bfe\u8c61\u7d5e\u308a\u8fbc\u307f": {
      "main": [
        [
          {
            "node": "SplitInBatches: 1\u4ef6\u305a\u3064",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SplitInBatches: 1\u4ef6\u305a\u3064": {
      "main": [
        [
          {
            "node": "HTTP Request: Resend\u9001\u4fe1",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "HTTP Request: Resend\u9001\u4fe1": {
      "main": [
        [
          {
            "node": "HTTP Request: \u30b9\u30c6\u30fc\u30b8\u66f4\u65b0",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "HTTP Request: step_email_log\u8a18\u9332 (failed)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request: \u30b9\u30c6\u30fc\u30b8\u66f4\u65b0": {
      "main": [
        [
          {
            "node": "HTTP Request: step_email_log\u8a18\u9332",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request: step_email_log\u8a18\u9332": {
      "main": [
        [
          {
            "node": "SplitInBatches: 1\u4ef6\u305a\u3064",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request: step_email_log\u8a18\u9332 (failed)": {
      "main": [
        [
          {
            "node": "SplitInBatches: 1\u4ef6\u305a\u3064",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": false,
    "callerPolicy": "workflowsFromSameOwner"
  },
  "staticData": {
    "node:Schedule Trigger": {
      "recurrenceRules": []
    }
  },
  "tags": []
}