0% found this document useful (0 votes)
4 views12 pages

App - Script Snapshot and Code

The document contains a JavaScript code for a Smart Supply Tracker & Reorder Alert system using Google Apps Script. It includes functions for initial setup, daily inventory checks, sending reorder alerts, logging reorder history, and applying usage logs, as well as a placeholder for monthly AI predictions. The script automates inventory management by creating necessary sheets, setting up triggers, and processing data to maintain stock levels efficiently.

Uploaded by

gijomex447
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views12 pages

App - Script Snapshot and Code

The document contains a JavaScript code for a Smart Supply Tracker & Reorder Alert system using Google Apps Script. It includes functions for initial setup, daily inventory checks, sending reorder alerts, logging reorder history, and applying usage logs, as well as a placeholder for monthly AI predictions. The script automates inventory management by creating necessary sheets, setting up triggers, and processing data to maintain stock levels efficiently.

Uploaded by

gijomex447
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 12

Script.

js Snapshot
Script.js Code
// Smart Supply Tracker & Reorder Alert - Apps Script

/**

* initialSetup

* - Creates time-driven triggers for daily inventory checks and monthly AI predictions

* - Performs sheet checks and creates missing sheets

*/
function initialSetup() {

var ss = SpreadsheetApp.getActiveSpreadsheet();

var required = ['Inventory Master','Usage Log','Reorder History','AI Predictions'];

required.forEach(function(name) {

if (!ss.getSheetByName(name)) {

ss.insertSheet(name);

});

// Create triggers if they don't exist

var triggers = ScriptApp.getProjectTriggers();

var hasDaily = triggers.some(t => t.getHandlerFunction()=='checkInventoryLevels' &&


t.getEventType()==ScriptApp.EventType.CLOCK);

if (!hasDaily) {

// daily trigger at 8am

ScriptApp.newTrigger('checkInventoryLevels')

.timeBased()

.atHour(8)

.everyDays(1)

.create();

// monthly AI prediction trigger

var hasMonthly = triggers.some(t => t.getHandlerFunction()=='runAIPrediction' &&


t.getEventType()==ScriptApp.EventType.CLOCK);

if (!hasMonthly) {

ScriptApp.newTrigger('runAIPrediction')

.timeBased()

.onMonthDay(1)

.atHour(6)

.create();

SpreadsheetApp.getUi().alert('Initial setup completed. Please authorize the script when


prompted.');
}

/**

* checkInventoryLevels

* Runs daily. Checks Inventory Master for items below threshold, sends email,

* marks alert as sent, and logs in Reorder History.

*/

function checkInventoryLevels() {

var ss = SpreadsheetApp.getActiveSpreadsheet();

var sheet = ss.getSheetByName('Inventory Master');

if (!sheet) return;

var data = sheet.getDataRange().getValues();

var header = data[0];

var now = new Date();

for (var i=1;i<data.length;i++){

var row = data[i];

var item = row[0];

var quantity = parseFloat(row[1]);

var threshold = parseFloat(row[2]);

var alertSent = row[3];

// Basic validation

if (isNaN(quantity) || isNaN(threshold)) {

// flag invalid row in a dedicated column (col 5)

sheet.getRange(i+1,5).setValue('Invalid qty/threshold');

continue;

if (quantity < 0) {

sheet.getRange(i+1,5).setValue('Negative quantity!');

continue;

if (quantity <= threshold && alertSent !== true) {


sendReorderAlert(item, quantity, threshold);

sheet.getRange(i+1,4).setValue(true); // mark alert sent

logReorder(item, quantity, threshold, now);

/**

* sendReorderAlert

* Sends a reorder request to vendor AND confirmation to owner

*/

function sendReorderAlert(item, quantity, threshold) {

// 1. Vendor email address (update to real vendor address)

var vendorEmail = '[email protected]';

// 2. Owner/Manager email address

var ownerEmail = '[email protected]';

// --- Vendor email content ---

var vendorSubject = 'Restock Request: ' + item;

var vendorBody =

'Dear Vendor,\n\n' +

'Please arrange for a restock of the following product:\n\n' +

'Item: ' + item + '\n' +

'Current Stock: ' + quantity + '\n' +

'Threshold: ' + threshold + '\n\n' +

'Kindly confirm the expected delivery date.\n\n' +

'--\nAutomated Supply Tracker';

// --- Owner confirmation content ---

var ownerSubject = 'Reorder Alert Sent to Vendor: ' + item;


var ownerBody =

'This is to confirm that a reorder request has been sent to the vendor for:\n\n' +

'Item: ' + item + '\n' +

'Current Stock: ' + quantity + '\n' +

'Threshold: ' + threshold + '\n\n' +

'The vendor has been notified to restock.\n\n' +

'--\nAutomated Supply Tracker';

// Send to vendor

MailApp.sendEmail(vendorEmail, vendorSubject, vendorBody);

// Send confirmation to owner

MailApp.sendEmail(ownerEmail, ownerSubject, ownerBody);

/**

* logReorder

* Appends a row to Reorder History with timestamp, item, qty, threshold, status

*/

function logReorder(item, qty, threshold, when) {

var ss = SpreadsheetApp.getActiveSpreadsheet();

var hist = ss.getSheetByName('Reorder History');

if (!hist) {

hist = ss.insertSheet('Reorder History');

hist.appendRow([when || new Date(), item, qty, threshold, 'Alert Sent']);

/**

* applyUsageLog

* Processes new rows in Usage Log and updates Inventory Master quantities.
* Usage Log expected columns: Timestamp, Item, QuantityUsed, Notes

*/

function applyUsageLog() {

var ss = SpreadsheetApp.getActiveSpreadsheet();

var usage = ss.getSheetByName('Usage Log');

var inv = ss.getSheetByName('Inventory Master');

if (!usage || !inv) return;

var udata = usage.getDataRange().getValues();

var idata = inv.getDataRange().getValues();

var invMap = {};

for (var i=1;i<idata.length;i++){

invMap[idata[i][0]] = {row:i+1, qty: parseFloat(idata[i][1])};

for (var j=1;j<udata.length;j++){

var urow = udata[j];

if (urow[4] === 'APPLIED') continue; // skip already applied logs (col E)

var item = urow[1];

var used = parseFloat(urow[2]);

if (!invMap[item]) {

usage.getRange(j+1,5).setValue('UNKNOWN_ITEM');

continue;

if (isNaN(used) || used < 0) {

usage.getRange(j+1,5).setValue('INVALID_QTY');

continue;

var invRow = invMap[item].row;

var newQty = invMap[item].qty - used;

inv.getRange(invRow,2).setValue(newQty);

usage.getRange(j+1,5).setValue('APPLIED');

}
}

/**

* runAIPrediction

* Placeholder for monthly AI-based prediction (Gemini).

* Writes sample predictions from inventory data and usage log to 'AI Predictions' sheet.

*/

function runAIPrediction() {

var ss = SpreadsheetApp.getActiveSpreadsheet();

var out = ss.getSheetByName('AI Predictions') || ss.insertSheet('AI Predictions');

out.clear();

out.appendRow(['GeneratedAt', 'PredictedAtRiskItem', 'Confidence', 'Notes']);

var apiKey = PropertiesService.getScriptProperties().getProperty('AI_API_KEY');

if (!apiKey) {

out.appendRow([new Date(), 'ERROR', 'N/A', 'Missing AI_API_KEY in Script Properties']);

return;

// Inventory data

var invSheet = ss.getSheetByName('Inventory Master');

var invData = invSheet ? invSheet.getDataRange().getValues() : [];

var invRows = invData.slice(1).map(r => ({ item: r[0], quantity: r[1], threshold: r[2] }));

// Usage data

var usageSheet = ss.getSheetByName('Usage Log');

var usageData = usageSheet ? usageSheet.getDataRange().getValues() : [];

var usageRows = usageData.slice(1).map(r => ({ timestamp: r[0], item: r[1], quantityUsed: r[2] }));

// Prompt
var prompt = "Given the following inventory and usage log data, predict which items are at highest
risk of stockout next month. " +

"Return ONLY a JSON array of objects with fields: item, confidence (0-1), notes. No
explanations, just JSON.\n\n" +

"Inventory Data:\n" + JSON.stringify(invRows, null, 2) + "\n\n" +

"Usage Data:\n" + JSON.stringify(usageRows, null, 2);

try {

var url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-


flash:generateContent?key=" + apiKey;

var payload = {

contents: [{ parts: [{ text: prompt }] }]

};

var response = UrlFetchApp.fetch(url, {

method: 'post',

contentType: 'application/json',

payload: JSON.stringify(payload),

muteHttpExceptions: true

});

if (response.getResponseCode() !== 200) {

out.appendRow([new Date(), 'ERROR', 'N/A', 'API status ' + response.getResponseCode()]);

return;

var json = JSON.parse(response.getContentText());

var modelText = json.candidates && json.candidates[0].content.parts[0].text;

if (!modelText) {

out.appendRow([new Date(), 'ERROR', 'N/A', 'No prediction text returned']);

return;

}
// --- JSON cleaner fallback ---

var cleanedText = modelText.match(/\[([\s\S]*)\]/);

if (cleanedText) {

modelText = "[" + cleanedText[1].trim() + "]";

var predictions;

try {

predictions = JSON.parse(modelText);

} catch (e) {

out.appendRow([new Date(), 'ERROR', 'N/A', 'Could not parse cleaned JSON']);

return;

predictions.forEach(function(p) {

out.appendRow([new Date(), p.item || '', p.confidence || '', p.notes || '']);

});

} catch (e) {

out.appendRow([new Date(), 'ERROR', 'N/A', e.toString()]);

/**

* manualResetAlert

* Utility: manually reset the Alert Sent flag for an item (for testing)

*/

function manualResetAlert(itemName) {

var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Inventory Master');

var data = sheet.getDataRange().getValues();

for (var i=1;i<data.length;i++){

if (data[i][0] === itemName) {

sheet.getRange(i+1,4).setValue(false);

return;

You might also like