{
  "name": "E - Thursday Menu Reminder & Friday Escalation",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 * * 4"
            }
          ]
        }
      },
      "id": "e1000001-0001-4000-8000-000000000001",
      "name": "Cron - Thursday 8AM",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        200,
        340
      ],
      "notesInFlow": true,
      "notes": "Every Thursday at 08:00 ICT (UTC+7)\nAdjust cron if server timezone \u2260 ICT:\n0 1 * * 4 for UTC"
    },
    {
      "parameters": {
        "jsCode": "// Calculate current week's Monday date for lookup\nconst now = new Date();\nconst dayOfWeek = now.getDay();\nconst monday = new Date(now);\nmonday.setDate(now.getDate() - (dayOfWeek === 0 ? 6 : dayOfWeek - 1));\n\n// Format as DD/MM/YYYY to match Sheet format\nconst dd = String(monday.getDate()).padStart(2, '0');\nconst mm = String(monday.getMonth() + 1).padStart(2, '0');\nconst yyyy = monday.getFullYear();\n\n// Also calculate the whole week range for searching\nconst weekDates = [];\nfor (let i = 0; i < 5; i++) {\n  const d = new Date(monday);\n  d.setDate(monday.getDate() + i);\n  weekDates.push(\n    String(d.getDate()).padStart(2, '0') + '/' +\n    String(d.getMonth() + 1).padStart(2, '0') + '/' +\n    d.getFullYear()\n  );\n}\n\nreturn [{\n  json: {\n    week_start: `${dd}/${mm}/${yyyy}`,\n    week_dates: weekDates,\n    check_type: 'thursday_reminder'\n  }\n}];"
      },
      "id": "e1000001-0001-4000-8000-000000000002",
      "name": "Calculate Week Dates",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        440,
        340
      ]
    },
    {
      "parameters": {
        "operation": "read",
        "documentId": {
          "__rl": true,
          "value": "YOUR_GOOGLE_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "id",
          "cachedResultName": "Th\u1ef1c \u0111\u01a1n"
        },
        "options": {
          "range": "A:L"
        }
      },
      "id": "e1000001-0001-4000-8000-000000000003",
      "name": "Read Menu Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        680,
        340
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Check if this week's menu entries exist and have content\nconst weekDates = $('Calculate Week Dates').first().json.week_dates;\nconst allRows = $input.all().map(item => item.json);\n\nconst missingDays = [];\nconst filledDays = [];\n\nfor (const date of weekDates) {\n  const row = allRows.find(r => r['Ng\u00e0y'] === date);\n  if (!row || !row['N\u1ed9i dung'] || row['N\u1ed9i dung'].toString().trim() === '') {\n    missingDays.push(date);\n  } else {\n    filledDays.push(date);\n  }\n}\n\nreturn [{\n  json: {\n    has_missing: missingDays.length > 0,\n    missing_days: missingDays,\n    filled_days: filledDays,\n    missing_count: missingDays.length,\n    total_days: weekDates.length,\n    summary: missingDays.length > 0\n      ? `Thi\u1ebfu th\u1ef1c \u0111\u01a1n cho ${missingDays.length}/${weekDates.length} ng\u00e0y: ${missingDays.join(', ')}`\n      : `\u0110\u00e3 c\u00f3 \u0111\u1ee7 th\u1ef1c \u0111\u01a1n cho c\u1ea3 tu\u1ea7n (${weekDates.length} ng\u00e0y)`\n  }\n}];"
      },
      "id": "e1000001-0001-4000-8000-000000000004",
      "name": "Check Missing Menus",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        920,
        340
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "cond-missing",
              "leftValue": "={{ $json.has_missing }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "e1000001-0001-4000-8000-000000000005",
      "name": "IF - Menu Missing",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        1160,
        340
      ]
    },
    {
      "parameters": {
        "sendTo": "={{ $vars.BAN_TRU_EMAIL || 'bantru@victoria.edu.vn' }}",
        "subject": "=[NH\u1eaeC NH\u1ede] Th\u1ef1c \u0111\u01a1n tu\u1ea7n n\u00e0y ch\u01b0a \u0111\u1ea7y \u0111\u1ee7 - Victoria TL3",
        "emailType": "html",
        "message": "=<h2>\ud83d\udccb Nh\u1eafc nh\u1edf nh\u1eadp th\u1ef1c \u0111\u01a1n</h2>\n<p>Xin ch\u00e0o,</p>\n<p>H\u1ec7 th\u1ed1ng ki\u1ec3m tra th\u1ea5y th\u1ef1c \u0111\u01a1n tu\u1ea7n n\u00e0y <strong>ch\u01b0a \u0111\u1ea7y \u0111\u1ee7</strong>.</p>\n<p><strong>{{ $json.summary }}</strong></p>\n<h3>Ng\u00e0y thi\u1ebfu:</h3>\n<ul>\n{{ $json.missing_days.map(d => '<li>' + d + '</li>').join('\\n') }}\n</ul>\n<p>Vui l\u00f2ng c\u1eadp nh\u1eadt th\u1ef1c \u0111\u01a1n v\u00e0o <a href=\"https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit\">b\u1ea3ng d\u1eef li\u1ec7u</a> tr\u01b0\u1edbc cu\u1ed1i ng\u00e0y h\u00f4m nay.</p>\n<p><em>N\u1ebfu kh\u00f4ng c\u1eadp nh\u1eadt tr\u01b0\u1edbc 12:00 th\u1ee9 S\u00e1u, h\u1ec7 th\u1ed1ng s\u1ebd th\u00f4ng b\u00e1o \u0111\u1ebfn Hi\u1ec7u tr\u01b0\u1edfng.</em></p>\n<hr>\n<p><em>Email t\u1ef1 \u0111\u1ed9ng t\u1eeb h\u1ec7 th\u1ed1ng Victoria TL3.</em></p>",
        "options": {}
      },
      "id": "e1000001-0001-4000-8000-000000000006",
      "name": "Gmail - Thursday Reminder",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        1400,
        240
      ],
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "amount": 28,
        "unit": "hours"
      },
      "id": "e1000001-0001-4000-8000-000000000007",
      "name": "Wait - Until Friday Noon",
      "type": "n8n-nodes-base.wait",
      "typeVersion": 1.1,
      "position": [
        1640,
        240
      ]
    },
    {
      "parameters": {
        "operation": "read",
        "documentId": {
          "__rl": true,
          "value": "YOUR_GOOGLE_SHEET_ID",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "gid=0",
          "mode": "id",
          "cachedResultName": "Th\u1ef1c \u0111\u01a1n"
        },
        "options": {
          "range": "A:L"
        }
      },
      "id": "e1000001-0001-4000-8000-000000000008",
      "name": "Re-Read Menu Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.5,
      "position": [
        1880,
        240
      ],
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "// Re-check after waiting \u2014 same logic as Thursday check\nconst weekDates = $('Calculate Week Dates').first().json.week_dates;\nconst allRows = $input.all().map(item => item.json);\n\nconst stillMissing = [];\nfor (const date of weekDates) {\n  const row = allRows.find(r => r['Ng\u00e0y'] === date);\n  if (!row || !row['N\u1ed9i dung'] || row['N\u1ed9i dung'].toString().trim() === '') {\n    stillMissing.push(date);\n  }\n}\n\nreturn [{\n  json: {\n    still_missing: stillMissing.length > 0,\n    missing_days: stillMissing,\n    missing_count: stillMissing.length\n  }\n}];"
      },
      "id": "e1000001-0001-4000-8000-000000000009",
      "name": "Re-Check Missing",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2120,
        240
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "conditions": [
            {
              "id": "cond-still-missing",
              "leftValue": "={{ $json.still_missing }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "id": "e1000001-0001-4000-8000-000000000010",
      "name": "IF - Still Missing Friday",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2,
      "position": [
        2340,
        240
      ]
    },
    {
      "parameters": {
        "sendTo": "={{ $vars.HIEU_TRUONG_EMAIL || 'hieutruong@victoria.edu.vn' }}",
        "ccEmails": "={{ $vars.BAN_TRU_EMAIL || 'bantru@victoria.edu.vn' }}",
        "subject": "=[KH\u1ea8N] Th\u1ef1c \u0111\u01a1n tu\u1ea7n n\u00e0y v\u1eabn ch\u01b0a \u0111\u01b0\u1ee3c c\u1eadp nh\u1eadt - Victoria TL3",
        "emailType": "html",
        "message": "=<h2>\ud83d\udea8 C\u1ea3nh b\u00e1o: Th\u1ef1c \u0111\u01a1n ch\u01b0a \u0111\u01b0\u1ee3c c\u1eadp nh\u1eadt</h2>\n<p>K\u00ednh g\u1eedi Hi\u1ec7u tr\u01b0\u1edfng,</p>\n<p>Sau khi nh\u1eafc nh\u1edf v\u00e0o th\u1ee9 N\u0103m, th\u1ef1c \u0111\u01a1n tu\u1ea7n n\u00e0y <strong>v\u1eabn ch\u01b0a \u0111\u01b0\u1ee3c c\u1eadp nh\u1eadt \u0111\u1ea7y \u0111\u1ee7</strong>.</p>\n<h3>Ng\u00e0y c\u00f2n thi\u1ebfu:</h3>\n<ul>\n{{ $json.missing_days.map(d => '<li>' + d + '</li>').join('\\n') }}\n</ul>\n<p>Theo quy tr\u00ecnh TT 09/2024, th\u1ef1c \u0111\u01a1n c\u1ea7n \u0111\u01b0\u1ee3c c\u00f4ng khai tr\u00ean website tr\u01b0\u1eddng. Vui l\u00f2ng ph\u1ed1i h\u1ee3p v\u1edbi b\u1ed9 ph\u1eadn b\u00e1n tr\u00fa \u0111\u1ec3 ho\u00e0n t\u1ea5t.</p>\n<hr>\n<p><em>Email t\u1ef1 \u0111\u1ed9ng t\u1eeb h\u1ec7 th\u1ed1ng Victoria TL3. B\u1ed9 ph\u1eadn b\u00e1n tr\u00fa \u0111\u00e3 \u0111\u01b0\u1ee3c CC.</em></p>",
        "options": {}
      },
      "id": "e1000001-0001-4000-8000-000000000011",
      "name": "Gmail - Friday Escalation",
      "type": "n8n-nodes-base.gmail",
      "typeVersion": 2.1,
      "position": [
        2580,
        140
      ],
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {},
      "id": "e1000001-0001-4000-8000-000000000012",
      "name": "No Op - All Good Thursday",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1400,
        460
      ]
    },
    {
      "parameters": {},
      "id": "e1000001-0001-4000-8000-000000000013",
      "name": "No Op - Resolved By Friday",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        2580,
        360
      ]
    }
  ],
  "connections": {
    "Cron - Thursday 8AM": {
      "main": [
        [
          {
            "node": "Calculate Week Dates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Week Dates": {
      "main": [
        [
          {
            "node": "Read Menu Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Menu Sheet": {
      "main": [
        [
          {
            "node": "Check Missing Menus",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Missing Menus": {
      "main": [
        [
          {
            "node": "IF - Menu Missing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Menu Missing": {
      "main": [
        [
          {
            "node": "Gmail - Thursday Reminder",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Op - All Good Thursday",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gmail - Thursday Reminder": {
      "main": [
        [
          {
            "node": "Wait - Until Friday Noon",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait - Until Friday Noon": {
      "main": [
        [
          {
            "node": "Re-Read Menu Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Re-Read Menu Sheet": {
      "main": [
        [
          {
            "node": "Re-Check Missing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Re-Check Missing": {
      "main": [
        [
          {
            "node": "IF - Still Missing Friday",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Still Missing Friday": {
      "main": [
        [
          {
            "node": "Gmail - Friday Escalation",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Op - Resolved By Friday",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "callerPolicy": "workflowsFromSameOwner"
  },
  "versionId": "e-reminder-v1",
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": [
    {
      "name": "victoria-tl3"
    },
    {
      "name": "reminder"
    }
  ]
}