{
  "id": "dT2rlVKbfgI3XzCg",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "School Report Card -> Email Parent Delivery",
  "tags": [],
  "nodes": [
    {
      "id": "214009eb-41d7-4ecc-b446-b3f421e4cf10",
      "name": "Run Workflow Manually",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -1312,
        576
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "7854bc56-4241-41b9-8249-5fab7391de4b",
      "name": "Loop Over Students",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -816,
        576
      ],
      "parameters": {
        "options": {}
      },
      "retryOnFail": false,
      "typeVersion": 3
    },
    {
      "id": "c86b339b-008e-490b-b745-3d521843122c",
      "name": "Skip Already Sent",
      "type": "n8n-nodes-base.if",
      "position": [
        -512,
        592
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition-skip-sent",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json['Status'] }}",
              "rightValue": "Sent"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "1150d65b-c682-4211-bda0-6f1bf92b0e02",
      "name": "Calculate Grade and Remarks",
      "type": "n8n-nodes-base.code",
      "position": [
        -256,
        480
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const item = $input.item.json;\n\n// \u2500\u2500\u2500 SUBJECT MARKS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst subjects = {\n  'Math':    parseInt(item['Math']    || 0),\n  'Science': parseInt(item['Science'] || 0),\n  'English': parseInt(item['English'] || 0),\n  'Hindi':   parseInt(item['Hindi']   || 0),\n  'SST':     parseInt(item['SST']     || 0)\n};\n\nconst maxPerSubject = parseInt(item['Max_Per_Subject'] || 100);\nconst totalSubjects = Object.keys(subjects).length;\nconst maxMarks      = maxPerSubject * totalSubjects;\nconst totalMarks    = Object.values(subjects).reduce((a, b) => a + b, 0);\nconst percentage    = ((totalMarks / maxMarks) * 100).toFixed(1);\n\n// \u2500\u2500\u2500 GRADE & COLOR \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nlet grade, gradeColor, gradeBg, remark;\n\nif (percentage >= 90) {\n  grade     = 'A+';\n  gradeColor = '#1b5e20';\n  gradeBg   = '#e8f5e9';\n  remark    = 'Outstanding performance! Truly exceptional dedication and hard work this term.';\n} else if (percentage >= 75) {\n  grade     = 'A';\n  gradeColor = '#1565c0';\n  gradeBg   = '#e3f2fd';\n  remark    = 'Excellent work. A consistent and hardworking student. Keep it up!';\n} else if (percentage >= 60) {\n  grade     = 'B';\n  gradeColor = '#e65100';\n  gradeBg   = '#fff3e0';\n  remark    = 'Good performance. Focused attention on weaker subjects will bring further improvement.';\n} else if (percentage >= 45) {\n  grade     = 'C';\n  gradeColor = '#6a1b9a';\n  gradeBg   = '#f3e5f5';\n  remark    = 'Satisfactory. Regular study habits and parental support will help improve results.';\n} else {\n  grade     = 'D';\n  gradeColor = '#b71c1c';\n  gradeBg   = '#ffebee';\n  remark    = 'Needs significant improvement. Please schedule a meeting with the class teacher at the earliest.';\n}\n\n// \u2500\u2500\u2500 SUBJECT RESULTS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst passMarkPct = 0.33; // 33% to pass each subject\nconst subjectResults = Object.entries(subjects).map(([name, marks]) => ({\n  name,\n  marks,\n  max: maxPerSubject,\n  pct: ((marks / maxPerSubject) * 100).toFixed(0),\n  pass: marks >= (maxPerSubject * passMarkPct),\n  passColor: marks >= (maxPerSubject * passMarkPct) ? '#2e7d32' : '#c62828',\n  passBg:    marks >= (maxPerSubject * passMarkPct) ? '#e8f5e9' : '#ffebee',\n  passLabel: marks >= (maxPerSubject * passMarkPct) ? 'Pass' : 'Fail'\n}));\n\n// \u2500\u2500\u2500 ATTENDANCE STYLING \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst attendance = parseFloat(item['Attendance'] || 0);\nconst attendanceColor = attendance >= 85 ? '#1b5e20' : attendance >= 75 ? '#e65100' : '#b71c1c';\n\nreturn {\n  ...item,\n  calc_subjects:        JSON.stringify(subjectResults),\n  calc_totalMarks:      totalMarks,\n  calc_maxMarks:        maxMarks,\n  calc_percentage:      parseFloat(percentage),\n  calc_grade:           grade,\n  calc_gradeColor:      gradeColor,\n  calc_gradeBg:         gradeBg,\n  calc_remark:          remark,\n  calc_attendance:      attendance,\n  calc_attendanceColor: attendanceColor,\n  calc_term:            item['Term'] || 'Term 2',\n  calc_year:            item['Academic_Year'] || '2024-25'\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "b7cd1bc0-d852-4175-9cbe-7f5ff610c051",
      "name": "Build HTML Report Card",
      "type": "n8n-nodes-base.code",
      "position": [
        0,
        480
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const d = $input.item.json;\nconst subjects = JSON.parse(d.calc_subjects);\n\n// \u2500\u2500\u2500 BUILD SUBJECT TABLE ROWS \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst tableRows = subjects.map(s => `\n  <tr>\n    <td style=\"padding:10px 16px;border-bottom:1px solid #f0f0f0;font-weight:600;color:#333;font-size:13px\">${s.name}</td>\n    <td style=\"padding:10px 16px;border-bottom:1px solid #f0f0f0;text-align:center;font-size:13px;color:#555\">${s.marks} / ${s.max}</td>\n    <td style=\"padding:10px 16px;border-bottom:1px solid #f0f0f0;text-align:center;font-size:13px;font-weight:700;color:#333\">${s.pct}%</td>\n    <td style=\"padding:10px 16px;border-bottom:1px solid #f0f0f0;text-align:center\">\n      <span style=\"background:${s.passBg};color:${s.passColor};padding:4px 14px;border-radius:20px;font-size:11px;font-weight:800;letter-spacing:0.5px\">${s.passLabel}</span>\n    </td>\n  </tr>`).join('');\n\n// \u2500\u2500\u2500 FULL HTML REPORT CARD \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nconst html = `<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"UTF-8\">\n<style>\n  * { margin: 0; padding: 0; box-sizing: border-box; }\n  body { font-family: 'Segoe UI', 'Helvetica Neue', Arial, sans-serif; background: #fff; color: #333; -webkit-print-color-adjust: exact; }\n  .page { width: 210mm; min-height: 297mm; padding: 16mm 18mm; }\n\n  /* HEADER */\n  .header { text-align: center; padding-bottom: 16px; margin-bottom: 20px; border-bottom: 3px solid ${d.calc_gradeColor}; }\n  .school-emblem { width: 64px; height: 64px; border-radius: 50%; background: ${d.calc_gradeColor}; display: inline-flex; align-items: center; justify-content: center; font-size: 28px; margin-bottom: 10px; }\n  .school-name { font-size: 22px; font-weight: 900; color: ${d.calc_gradeColor}; letter-spacing: 0.5px; text-transform: uppercase; }\n  .school-sub { font-size: 12px; color: #888; margin-top: 3px; }\n  .report-badge { display: inline-block; margin-top: 12px; background: ${d.calc_gradeColor}; color: #fff; padding: 6px 24px; border-radius: 4px; font-size: 12px; font-weight: 800; letter-spacing: 2px; text-transform: uppercase; }\n  .report-term { font-size: 12px; color: #888; margin-top: 6px; }\n\n  /* STUDENT INFO */\n  .student-card { display: grid; grid-template-columns: 1fr 1fr; gap: 0; border: 1.5px solid ${d.calc_gradeColor}40; border-radius: 10px; overflow: hidden; margin: 18px 0; }\n  .info-cell { padding: 12px 16px; border-right: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0; }\n  .info-cell:nth-child(2n) { border-right: none; }\n  .info-cell:nth-last-child(-n+2) { border-bottom: none; }\n  .info-lbl { font-size: 10px; color: #999; font-weight: 700; text-transform: uppercase; letter-spacing: 0.8px; }\n  .info-val { font-size: 14px; font-weight: 800; color: #222; margin-top: 3px; }\n\n  /* TABLE */\n  .section-lbl { font-size: 11px; font-weight: 800; color: ${d.calc_gradeColor}; text-transform: uppercase; letter-spacing: 1.5px; margin: 18px 0 10px; }\n  table { width: 100%; border-collapse: collapse; border-radius: 8px; overflow: hidden; border: 1px solid #e8e8e8; }\n  thead { background: ${d.calc_gradeColor}; }\n  th { padding: 11px 16px; text-align: left; font-size: 11px; font-weight: 800; color: #fff; letter-spacing: 0.8px; text-transform: uppercase; }\n  th:not(:first-child) { text-align: center; }\n  .total-row { background: ${d.calc_gradeBg}; }\n  .total-row td { font-weight: 800; font-size: 13px; padding: 12px 16px; }\n  .total-row td:not(:first-child) { text-align: center; }\n\n  /* GRADE SUMMARY */\n  .grade-strip { background: linear-gradient(135deg, ${d.calc_gradeColor}, ${d.calc_gradeColor}bb); color: #fff; border-radius: 10px; padding: 16px 20px; margin: 18px 0; display: flex; align-items: center; gap: 20px; }\n  .grade-letter { font-size: 56px; font-weight: 900; line-height: 1; opacity: 0.95; min-width: 60px; }\n  .grade-details .grade-pct { font-size: 26px; font-weight: 800; }\n  .grade-details .grade-sub { font-size: 12px; opacity: 0.85; margin-top: 2px; }\n\n  /* STATS ROW */\n  .stats-row { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; margin: 14px 0; }\n  .stat-card { background: #fafafa; border: 1px solid #eee; border-radius: 8px; padding: 12px 14px; text-align: center; }\n  .stat-val { font-size: 20px; font-weight: 900; color: ${d.calc_gradeColor}; }\n  .stat-lbl { font-size: 10px; color: #999; margin-top: 3px; text-transform: uppercase; font-weight: 700; letter-spacing: 0.5px; }\n\n  /* REMARK */\n  .remark-box { background: #fffde7; border-left: 4px solid #ffc107; padding: 12px 16px; border-radius: 0 8px 8px 0; margin: 14px 0; }\n  .remark-title { font-size: 10px; color: #888; font-weight: 800; text-transform: uppercase; letter-spacing: 0.8px; margin-bottom: 5px; }\n  .remark-text { font-size: 13px; color: #444; line-height: 1.65; font-style: italic; }\n\n  /* SIGNATURES */\n  .signatures { margin-top: 40px; display: grid; grid-template-columns: 1fr 1fr 1fr; text-align: center; }\n  .sig-block { border-top: 1px solid #ccc; padding-top: 8px; margin: 0 12px; font-size: 11px; color: #777; }\n\n  /* FOOTER */\n  .watermark { text-align: center; margin-top: 20px; font-size: 10px; color: #bbb; padding-top: 12px; border-top: 1px solid #f0f0f0; }\n</style>\n</head>\n<body>\n<div class=\"page\">\n\n  <!-- SCHOOL HEADER -->\n  <div class=\"header\">\n    <div class=\"school-emblem\">\ud83c\udf93</div>\n    <div class=\"school-name\">YOUR SCHOOL NAME</div>\n    <div class=\"school-sub\">Affiliated to CBSE, New Delhi &nbsp;|&nbsp; School Code: 00000</div>\n    <div class=\"school-sub\">123, School Road, Your City &nbsp;|&nbsp; Tel: +91 XXXXXXXXXX &nbsp;|&nbsp; user@example.com</div>\n    <div class=\"report-badge\">Student Progress Report</div>\n    <div class=\"report-term\">${d.calc_term} &nbsp;&bull;&nbsp; Academic Year ${d.calc_year}</div>\n  </div>\n\n  <!-- STUDENT INFO GRID -->\n  <div class=\"student-card\">\n    <div class=\"info-cell\">\n      <div class=\"info-lbl\">Student Name</div>\n      <div class=\"info-val\">${d['Student_Name'] || ''}</div>\n    </div>\n    <div class=\"info-cell\">\n      <div class=\"info-lbl\">Class &amp; Section</div>\n      <div class=\"info-val\">Class ${d['Class'] || ''} &mdash; Section ${d['Section'] || ''}</div>\n    </div>\n    <div class=\"info-cell\">\n      <div class=\"info-lbl\">Roll Number</div>\n      <div class=\"info-val\">${d['Roll_No'] || ''}</div>\n    </div>\n    <div class=\"info-cell\">\n      <div class=\"info-lbl\">Examination</div>\n      <div class=\"info-val\">${d.calc_term}, ${d.calc_year}</div>\n    </div>\n  </div>\n\n  <!-- MARKS TABLE -->\n  <div class=\"section-lbl\">\ud83d\udcca Subject-wise Performance</div>\n  <table>\n    <thead>\n      <tr>\n        <th>Subject</th>\n        <th>Marks Obtained</th>\n        <th>Percentage</th>\n        <th>Result</th>\n      </tr>\n    </thead>\n    <tbody>\n      ${tableRows}\n      <tr class=\"total-row\">\n        <td>Total / Grand Total</td>\n        <td style=\"text-align:center\">${d.calc_totalMarks} / ${d.calc_maxMarks}</td>\n        <td style=\"text-align:center\">${d.calc_percentage}%</td>\n        <td style=\"text-align:center\">\n          <span style=\"background:${d.calc_gradeBg};color:${d.calc_gradeColor};padding:4px 14px;border-radius:20px;font-size:11px;font-weight:800\">Grade ${d.calc_grade}</span>\n        </td>\n      </tr>\n    </tbody>\n  </table>\n\n  <!-- GRADE CARD -->\n  <div class=\"grade-strip\">\n    <div class=\"grade-letter\">${d.calc_grade}</div>\n    <div class=\"grade-details\">\n      <div class=\"grade-pct\">${d.calc_percentage}% &mdash; ${d.calc_totalMarks} / ${d.calc_maxMarks}</div>\n      <div class=\"grade-sub\">Overall Performance &bull; ${d.calc_term} ${d.calc_year}</div>\n    </div>\n  </div>\n\n  <!-- STATS -->\n  <div class=\"stats-row\">\n    <div class=\"stat-card\">\n      <div class=\"stat-val\" style=\"color:${d.calc_gradeColor}\">${d.calc_grade}</div>\n      <div class=\"stat-lbl\">Grade</div>\n    </div>\n    <div class=\"stat-card\">\n      <div class=\"stat-val\">${d.calc_percentage}%</div>\n      <div class=\"stat-lbl\">Overall %</div>\n    </div>\n    <div class=\"stat-card\">\n      <div class=\"stat-val\" style=\"color:${d.calc_attendanceColor}\">${d.calc_attendance}%</div>\n      <div class=\"stat-lbl\">Attendance</div>\n    </div>\n  </div>\n\n  <!-- REMARK -->\n  <div class=\"remark-box\">\n    <div class=\"remark-title\">\ud83d\udcdd Class Teacher's Remark</div>\n    <div class=\"remark-text\">${d.calc_remark}</div>\n  </div>\n\n  <!-- SIGNATURES -->\n  <div class=\"signatures\">\n    <div class=\"sig-block\">Class Teacher</div>\n    <div class=\"sig-block\">Exam Controller</div>\n    <div class=\"sig-block\">Principal</div>\n  </div>\n\n  <!-- WATERMARK -->\n  <div class=\"watermark\">\n    This is a system-generated report &bull; Generated on ${new Date().toLocaleDateString('en-IN', { day: 'numeric', month: 'long', year: 'numeric' })} &bull; For queries contact the school office\n  </div>\n\n</div>\n</body>\n</html>`;\n\n// Convert HTML string to binary so Gotenberg can receive it\nconst binaryData = await this.helpers.prepareBinaryData(\n  Buffer.from(html, 'utf8'),\n  'report_card.html',\n  'text/html'\n);\n\nreturn {\n  json: {\n    ...$input.item.json,\n    reportHtml: html // This sends the full HTML as a text property\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "e4bbd1c0-2b4b-4f6e-9c25-19b573956635",
      "name": "Get row(s)",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        -1072,
        576
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "Status",
              "condition": "isEmpty"
            }
          ]
        },
        "matchType": "allConditions",
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "zQlRqq5eqJ5cvvhT",
          "cachedResultUrl": "/projects/YORR4xM3FFToOHnO/datatables/zQlRqq5eqJ5cvvhT",
          "cachedResultName": "Jainam-Email-parent-Reportcard"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "7732d783-427b-4fb2-b791-9f1c0105e753",
      "name": "Convert HTML to PDF",
      "type": "n8n-nodes-htmlcsstopdf.htmlcsstopdf",
      "position": [
        256,
        480
      ],
      "parameters": {
        "html_content": "={{ $json.reportHtml }}",
        "dynamic_params": {
          "params": []
        }
      },
      "credentials": {
        "htmlcsstopdfApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7ee8ade0-1d98-4c82-8c35-7bb2b5131bc7",
      "name": "Update row(s)",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        992,
        480
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "Sent",
            "Sent_At": "={{ $now.toFormat('dd/MM/yyyy HH:mm:ss') }}",
            "Report_URL": "={{ $('Convert HTML to PDF').item.json.pdf_url }}"
          },
          "schema": [
            {
              "id": "Student_Name",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Student_Name",
              "defaultMatch": false
            },
            {
              "id": "Parent_Name",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Parent_Name",
              "defaultMatch": false
            },
            {
              "id": "Parent_WhatsApp",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Parent_WhatsApp",
              "defaultMatch": false
            },
            {
              "id": "Parent_Email",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Parent_Email",
              "defaultMatch": false
            },
            {
              "id": "Class",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Class",
              "defaultMatch": false
            },
            {
              "id": "Section",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Section",
              "defaultMatch": false
            },
            {
              "id": "Roll_No",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Roll_No",
              "defaultMatch": false
            },
            {
              "id": "Term",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Term",
              "defaultMatch": false
            },
            {
              "id": "Academic_Year",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Academic_Year",
              "defaultMatch": false
            },
            {
              "id": "Math",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Math",
              "defaultMatch": false
            },
            {
              "id": "Science",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Science",
              "defaultMatch": false
            },
            {
              "id": "English",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "English",
              "defaultMatch": false
            },
            {
              "id": "Hindi",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Hindi",
              "defaultMatch": false
            },
            {
              "id": "SST",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "SST",
              "defaultMatch": false
            },
            {
              "id": "Max_Per_Subject",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Max_Per_Subject",
              "defaultMatch": false
            },
            {
              "id": "Attendance",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "Attendance",
              "defaultMatch": false
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false
            },
            {
              "id": "Report_URL",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Report_URL",
              "defaultMatch": false
            },
            {
              "id": "Sent_At",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "Sent_At",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "filters": {
          "conditions": [
            {
              "keyName": "Roll_No",
              "keyValue": "={{ $('Loop Over Students').item.json.Roll_No }}"
            }
          ]
        },
        "options": {},
        "operation": "update",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "zQlRqq5eqJ5cvvhT",
          "cachedResultUrl": "/projects/YORR4xM3FFToOHnO/datatables/zQlRqq5eqJ5cvvhT",
          "cachedResultName": "Jainam-Email-parent-Reportcard"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "8f91fb96-bf7d-4f07-aa09-d92fb80e8d97",
      "name": "Send a message to Parents",
      "type": "n8n-nodes-base.gmail",
      "position": [
        496,
        480
      ],
      "parameters": {
        "sendTo": "={{ $('Get row(s)').item.json.Parent_Email }}",
        "message": "=Dear {{ $('Build HTML Report Card').item.json.Parent_Name }}, <br><br>\n  Please find attached the digital progress report for <b>{{ $('Build HTML Report Card').item.json.Student_Name }}</b> for <b>{{ $('Build HTML Report Card').item.json.Term }}</b>.<br><br>\n  <b>Quick Summary:</b><br>\n  - Grade: {{ $('Build HTML Report Card').item.json.calc_grade }}\n  - Score: {{ $('Build HTML Report Card').item.json.calc_percentage }}%<br><br>\n  You can view/download the report here: <a href={{ $json.pdf_url }}>View Report Card</a><br><br>\n  Regards,<br>\n  Principal<br>\n  School_Name",
        "options": {},
        "subject": "=Progress Report: {{ $('Build HTML Report Card').item.json.Student_Name }}, Class: {{ $('Get row(s)').item.json.Class }}{{ $('Get row(s)').item.json.Section }},{{ $('Get row(s)').item.json.Academic_Year }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "7a11d27e-bda9-4c5b-b3e3-2e9779bd5061",
      "name": "Wait 3 Seconds",
      "type": "n8n-nodes-base.wait",
      "position": [
        736,
        480
      ],
      "parameters": {
        "amount": 3
      },
      "typeVersion": 1.1
    },
    {
      "id": "50f67832-5d87-4007-be06-b6c97d0af6ce",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1392,
        384
      ],
      "parameters": {
        "color": "#786868",
        "height": 336,
        "content": "## \ud83c\udfac Manual Trigger\n\nStarts the workflow manually from the n8n editor.\n\n### \ud83d\udd39 Use Case:\n\u2022 Testing the workflow  \n\u2022 Debugging logic  \n\u2022 One-time execution  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "27affd71-af3e-40bf-8733-44dd7d22316d",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1136,
        240
      ],
      "parameters": {
        "color": "#592744",
        "width": 256,
        "height": 480,
        "content": "## \ud83d\udce5 Fetch Student Records\n\nRetrieves student data from the Data Table.\n\n### \ud83d\udd39 What it does:\n\u2022 Fetches rows where **Status is empty**  \n\u2022 Filters only pending report cards  \n\n### \ud83c\udfaf Purpose:\n\u2022 Prevent duplicate processing  \n\u2022 Acts as the main data source  "
      },
      "typeVersion": 1
    },
    {
      "id": "ff5ffbe2-dd66-4407-8cf3-2fe39d752d63",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -864,
        240
      ],
      "parameters": {
        "color": "#293065",
        "height": 480,
        "content": "## \ud83d\udd01 Loop Through Students\n\nProcesses records one-by-one using batching.\n\n### \ud83d\udd39 What it does:\n\u2022 Splits data into individual items  \n\u2022 Runs workflow per student  \n\n### \ud83c\udfaf Purpose:\n\u2022 Avoid overload  \n\u2022 Improve reliability  \n\u2022 Enable controlled execution "
      },
      "typeVersion": 1
    },
    {
      "id": "d3a3b7fd-db54-41cd-a46f-139e75306b41",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -608,
        288
      ],
      "parameters": {
        "color": "#136267",
        "width": 256,
        "height": 432,
        "content": "## \ud83d\udeab Skip Already Sent Reports\n\nFilters out students whose reports are already sent.\n\n### \ud83d\udd39 Condition:\n\u2022 If Status \u2260 \"Sent\" \u2192 Continue  \n\u2022 Else \u2192 Skip  \n\n### \ud83c\udfaf Purpose:\n\u2022 Prevent duplicate emails  \n\u2022 Ensure idempotent workflow  \n"
      },
      "typeVersion": 1
    },
    {
      "id": "82c76e25-7254-471f-be0e-657888069296",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -320,
        112
      ],
      "parameters": {
        "color": "#21783B",
        "height": 512,
        "content": "## \ud83d\udcca Calculate Grades & Remarks\n\nCore logic for student evaluation.\n\n### \ud83d\udd39 What it calculates:\n\u2022 Subject-wise marks  \n\u2022 Total & percentage  \n\u2022 Grade (A+, A, B, C, D)  \n\u2022 Pass/Fail per subject  \n\u2022 Attendance status  \n\n### \ud83e\udde0 Extra:\n\u2022 Dynamic remarks based on performance  \n\u2022 Color coding for UI  "
      },
      "typeVersion": 1
    },
    {
      "id": "0b7b6a7b-2d49-408e-8721-f2ff01d7ff91",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -64,
        128
      ],
      "parameters": {
        "color": "#7E5207",
        "height": 496,
        "content": "## \ud83e\uddfe Generate HTML Report Card\n\nCreates a fully styled report card in HTML.\n\n### \ud83d\udd39 Includes:\n\u2022 School header  \n\u2022 Student details  \n\u2022 Subject table  \n\u2022 Grade summary  \n\u2022 Attendance & remarks  \n\n### \ud83c\udfaf Purpose:\n\u2022 Prepare printable design  \n\u2022 Maintain consistent layout  "
      },
      "typeVersion": 1
    },
    {
      "id": "858d4245-515e-4920-952e-05e90ed1ad9d",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        192,
        144
      ],
      "parameters": {
        "color": "#925D5D",
        "height": 480,
        "content": "## \ud83d\udcc4 Convert HTML to PDF\n\nTransforms HTML report into a PDF file.\n\n### \ud83d\udd39 What it does:\n\u2022 Sends HTML to PDF API  \n\u2022 Generates downloadable PDF link  \n\n### \ud83c\udfaf Purpose:\n\u2022 Shareable format  \n\u2022 Print-ready output  "
      },
      "typeVersion": 1
    },
    {
      "id": "bc86f0b2-36dd-4739-8440-d9453c104a1f",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        144
      ],
      "parameters": {
        "color": "#0A7894",
        "height": 480,
        "content": "## \ud83d\udce7 Send Email to Parents\n\nDelivers report card via email.\n\n### \ud83d\udd39 Includes:\n\u2022 Student name  \n\u2022 Grade & percentage  \n\u2022 PDF download link  \n\n### \ud83c\udfaf Purpose:\n\u2022 Notify parents instantly  \n\u2022 Digital delivery system  "
      },
      "typeVersion": 1
    },
    {
      "id": "47599e68-368f-4d01-b923-516bdc679fe5",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        704,
        208
      ],
      "parameters": {
        "color": "#20604D",
        "width": 208,
        "height": 416,
        "content": "## \u23f3 Delay Execution\n\nAdds a delay before next operation.\n\n### \ud83d\udd39 What it does:\n\u2022 Waits for 3 seconds  \n\n### \ud83c\udfaf Purpose:\n\u2022 Prevent API rate limits  \n\u2022 Avoid email throttling  "
      },
      "typeVersion": 1
    },
    {
      "id": "fd3b4e94-b16c-4fff-9fa5-ccaa55882c02",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        928,
        160
      ],
      "parameters": {
        "color": "#65485F",
        "height": 464,
        "content": "## \u2705 Update Student Record\n\nMarks report as sent in Data Table.\n\n### \ud83d\udd39 Updates:\n\u2022 Status \u2192 Sent  \n\u2022 Sent_At \u2192 Timestamp  \n\u2022 Report_URL \u2192 PDF link  \n\n### \ud83c\udfaf Purpose:\n\u2022 Track delivery  \n\u2022 Prevent reprocessing  "
      },
      "typeVersion": 1
    },
    {
      "id": "7da556a5-032b-46fa-b342-7939ac53a8c0",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1360,
        0
      ],
      "parameters": {
        "color": "#F7F7F7",
        "width": 720,
        "height": 192,
        "content": "## \ud83c\udf93 Report Card Automation\n\nThis workflow automatically generates and sends student report cards to parents.\n\nIt fetches student data, calculates performance (marks, percentage, grade, remarks), creates a professional PDF report card, emails it to parents, and updates the system to avoid duplicate sending.\n\n### \ud83d\udd04 Flow:\nFetch Data \u2192 Process Students \u2192 Generate Report \u2192 Convert to PDF \u2192 Send Email \u2192 Update Status"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "635f5484-b3e1-4e10-98e4-0af142a547ba",
  "connections": {
    "Get row(s)": {
      "main": [
        [
          {
            "node": "Loop Over Students",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update row(s)": {
      "main": [
        [
          {
            "node": "Loop Over Students",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait 3 Seconds": {
      "main": [
        [
          {
            "node": "Update row(s)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Skip Already Sent": {
      "main": [
        [
          {
            "node": "Calculate Grade and Remarks",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Students",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Students": {
      "main": [
        [],
        [
          {
            "node": "Skip Already Sent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert HTML to PDF": {
      "main": [
        [
          {
            "node": "Send a message to Parents",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run Workflow Manually": {
      "main": [
        [
          {
            "node": "Get row(s)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build HTML Report Card": {
      "main": [
        [
          {
            "node": "Convert HTML to PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send a message to Parents": {
      "main": [
        [
          {
            "node": "Wait 3 Seconds",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Grade and Remarks": {
      "main": [
        [
          {
            "node": "Build HTML Report Card",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}