This workflow corresponds to n8n.io template #7177 — we link there as the canonical source.
This workflow follows the Emailsend → Google Sheets recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"id": "YP981T0Pa3Ab6Dwg",
"meta": {
"templateCredsSetupCompleted": true
},
"name": "Automated Pharmacy Inventory Alerts for Low Stock & Expiry Dates with Google Sheets",
"tags": [],
"nodes": [
{
"id": "2697ea1c-7dcd-44eb-bf86-b3889ed5025d",
"name": "Daily Stock Check",
"type": "n8n-nodes-base.cron",
"position": [
-1000,
440
],
"parameters": {
"triggerTimes": {
"item": [
{
"hour": 9
}
]
}
},
"typeVersion": 1
},
{
"id": "93f65b9b-ee7f-4343-bea2-afcae41cc399",
"name": "Fetch Stock Data",
"type": "n8n-nodes-base.googleSheets",
"position": [
-780,
440
],
"parameters": {
"range": "PharmacyInventory!A:E",
"options": {},
"sheetId": "{{your_google_sheet_id}}",
"authentication": "serviceAccount"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "a71b7215-8278-49e1-8b32-74385c65b77c",
"name": "Update Google Sheet",
"type": "n8n-nodes-base.googleSheets",
"position": [
-120,
440
],
"parameters": {
"range": "PharmacyInventory!A:E",
"options": {},
"sheetId": "{{your_google_sheet_id}}",
"operation": "update",
"authentication": "serviceAccount"
},
"credentials": {
"googleApi": {
"name": "<your credential>"
}
},
"typeVersion": 2
},
{
"id": "5697579e-94b6-4fbb-8c66-b009cb7e7aaa",
"name": "Send Email Alert",
"type": "n8n-nodes-base.emailSend",
"position": [
100,
440
],
"parameters": {
"text": "=Hello Pharmacist,\n\nThis is an automated notification from the Pharmacy Inventory Monitoring System.\n\nThe following medicines require immediate attention as of {{ $now.format('YYYY-MM-DD') }}:\n\nLOW STOCK ALERTS:\n{{ $json.lowStockList }}\n\nEXPIRY ALERTS (Near expiry or expired):\n{{ $json.expiryList }}\n\nACTION REQUIRED:\n- Please restock medicines with low quantity levels\n- Remove or return expired/near-expiry items to ensure patient safety\n- Update inventory levels in the Google Sheet after taking action\n\nFor questions about inventory management or system updates, please contact the pharmacy operations team.\n\nBest regards,\nAutomated Pharmacy Inventory System\nSunrise Pharmacy Operations\n\n---\nThis is an automated message. Please do not reply to this email.\n",
"options": {},
"subject": "Pharmacy Inventory Alert - Low Stock & Expiry Notice - {{ $now.format('YYYY-MM-DD') }}",
"toEmail": "user@example.com",
"fromEmail": "user@example.com",
"emailFormat": "text"
},
"credentials": {
"smtp": {
"name": "<your credential>"
}
},
"typeVersion": 2.1
},
{
"id": "1d189b60-955c-4f26-ab16-8055166e8415",
"name": "Sticky Note",
"type": "n8n-nodes-base.stickyNote",
"position": [
-1000,
-40
],
"parameters": {
"color": 4,
"width": 1020,
"height": 280,
"content": "## \ud83d\udccc Automated Pharmacy Inventory Monitoring Workflow\n\n**Daily Operations Overview:**\n- **Daily Stock Check (9 AM)**: Automated trigger to monitor inventory levels\n- **Fetch Stock Data**: Retrieves current medicine data from Google Sheets\n- **Wait For All Data**: Ensures complete data retrieval before processing\n- **Check Expiry Date and Low Stock**: Analyzes inventory for alerts\n- **Update Google Sheet**: Records alert status and timestamps\n- **Send Email Alert**: Notifies pharmacist of low stock and expiry issues\n\n**Key Features:**\n\u2705 Low stock threshold monitoring\n\u2705 Expiry date tracking (30-day advance warning)\n\u2705 Automated email notifications\n\u2705 Google Sheets integration for easy management"
},
"typeVersion": 1
},
{
"id": "e062c1ab-c264-4eaa-9a9f-91354cc2bd30",
"name": "Wait For All Data",
"type": "n8n-nodes-base.wait",
"position": [
-560,
440
],
"parameters": {},
"typeVersion": 1.1
},
{
"id": "10f4705c-3f93-4190-bb9b-86151ee49834",
"name": "Check Expiry Date and Low Stock",
"type": "n8n-nodes-base.code",
"position": [
-340,
440
],
"parameters": {
"jsCode": "// Get all input items from Google Sheets\nconst items = $input.all();\nconst alerts = [];\nconst lowStockItems = [];\nconst expiryItems = [];\n\nfor (const item of items) {\n const data = item.json;\n\n // Skip header row or empty entries\n if (!data.medicine_name || data.medicine_name === 'medicine_name') {\n continue;\n }\n\n // Stock threshold (default 10 units if not specified)\n const threshold = data.threshold || 10;\n\n // Expiry warning in days (30 days before expiry)\n const expiryWarningDays = 30;\n\n // Check Low Stock\n if (data.stock_quantity && parseInt(data.stock_quantity) <= threshold) {\n const lowStockAlert = {\n medicine_name: data.medicine_name,\n stock_quantity: data.stock_quantity,\n threshold: threshold,\n type: \"Low Stock\",\n alert_message: `LOW STOCK: ${data.medicine_name} has only ${data.stock_quantity} units remaining (threshold: ${threshold})`\n };\n \n alerts.push(lowStockAlert);\n lowStockItems.push(`\u2022 ${data.medicine_name}: ${data.stock_quantity} units (threshold: ${threshold})`);\n }\n\n // Check Expiry Date\n if (data.expiry_date) {\n const today = new Date();\n const expiryDate = new Date(data.expiry_date);\n const daysLeft = Math.ceil((expiryDate - today) / (1000 * 60 * 60 * 24));\n\n if (daysLeft <= expiryWarningDays) {\n const expiryAlert = {\n medicine_name: data.medicine_name,\n expiry_date: data.expiry_date,\n days_left: daysLeft,\n type: daysLeft > 0 ? \"Near Expiry\" : \"Expired\",\n alert_message: daysLeft > 0\n ? `NEAR EXPIRY: ${data.medicine_name} expires in ${daysLeft} days (${data.expiry_date})`\n : `EXPIRED: ${data.medicine_name} expired ${Math.abs(daysLeft)} days ago (${data.expiry_date})`\n };\n \n alerts.push(expiryAlert);\n expiryItems.push(daysLeft > 0 \n ? `\u2022 ${data.medicine_name}: Expires in ${daysLeft} days (${data.expiry_date})`\n : `\u2022 ${data.medicine_name}: EXPIRED ${Math.abs(daysLeft)} days ago (${data.expiry_date})`);\n }\n }\n}\n\n// Create summary for email\nconst emailSummary = {\n lowStockList: lowStockItems.length > 0 ? lowStockItems.join('\\n') : 'No low stock items found.',\n expiryList: expiryItems.length > 0 ? expiryItems.join('\\n') : 'No items near expiry or expired.',\n totalAlerts: alerts.length,\n timestamp: new Date().toISOString()\n};\n\n// Return all alerts with email summary\nif (alerts.length > 0) {\n return [{ json: emailSummary }, ...alerts.map(alert => ({ json: alert }))];\n} else {\n // Return empty summary if no alerts\n return [{ json: emailSummary }];\n}"
},
"typeVersion": 2
}
],
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "89c25bc6-c09d-433d-85ff-88f9baad4581",
"connections": {
"Fetch Stock Data": {
"main": [
[
{
"node": "Wait For All Data",
"type": "main",
"index": 0
}
]
]
},
"Daily Stock Check": {
"main": [
[
{
"node": "Fetch Stock Data",
"type": "main",
"index": 0
}
]
]
},
"Wait For All Data": {
"main": [
[
{
"node": "Check Expiry Date and Low Stock",
"type": "main",
"index": 0
}
]
]
},
"Update Google Sheet": {
"main": [
[
{
"node": "Send Email Alert",
"type": "main",
"index": 0
}
]
]
},
"Check Expiry Date and Low Stock": {
"main": [
[
{
"node": "Update Google Sheet",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
googleApismtp
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
This n8n workflow monitors pharmacy inventory stored in a Google Sheet, checks daily for low stock or near-expiry medicines, and sends alerts to the pharmacist via email, ensuring timely restocking and waste prevention.
Source: https://n8n.io/workflows/7177/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Security teams, DevOps engineers, vulnerability analysts, and automation builders who want to eliminate repetitive Nessus scan parsing, AI-based risk triage, and manual reporting. Designed for orgs fo
This workflow fully automates the reconciliation process between your Local Database transactions and Payment Gateway transactions. It compares both data sources, identifies mismatches, categorizes di
This n8n workflow automatically finds apartments for rent in Germany, filters them by your city, rent budget, and number of rooms, and applies to them via email. Each application includes: A personali
👤 Who it’s for Blue Team leads, CISOs, and SOC managers who want automated visibility into threat metrics, endpoint alerts, and response actions — without needing a full SIEM or BI platform.
Workflow Overview Zoom Attendance Evaluator with Follow-up is an n8n automation workflow that automatically evaluates Zoom meeting attendance and sends follow-up emails to no-shows and early leavers w