Skip to content

Instantly share code, notes, and snippets.

@sainak
Created November 25, 2024 12:39
Show Gist options
  • Save sainak/d728042d44a0049c9a6129e856716263 to your computer and use it in GitHub Desktop.
Save sainak/d728042d44a0049c9a6129e856716263 to your computer and use it in GitHub Desktop.
// enable drive api service
// manually set a time-driven trigger(the alarm icon) that runs monthly after 25th evening,
function entrypoint() {
return main();
}
function deIndent(str) {
return str.replace(/^[ \t]+/gm, "");
}
function dateWithOrdinalSuffix(date) {
const day = date.getDate();
let suffix = "th";
if (day % 10 === 1 && day !== 11) {
suffix = "st";
} else if (day % 10 === 2 && day !== 12) {
suffix = "nd";
} else if (day % 10 === 3 && day !== 13) {
suffix = "rd";
}
return day + suffix + Utilities.formatDate(date, "Asia/Kolkata", " MMMM, yyyy");
}
function getConsultancyFeesText(date) {
const firstDay = new Date(date.getFullYear(), date.getMonth(), 1)
const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0)
return `Consultancy fees for ${dateWithOrdinalSuffix(firstDay)} to ${dateWithOrdinalSuffix(lastDay)}`
}
function tgMessage(message) {
const botToken = ""
const chatId = ""
UrlFetchApp.fetch(
`https://api.telegram.org/bot${botToken}/sendMessage`,
{
method: 'post',
payload: {
chat_id: chatId,
text: message
}
}
);
}
function fetchWithAuth(url) {
return UrlFetchApp.fetch(url, {
method: "GET",
headers: { "Authorization": "Bearer " + ScriptApp.getOAuthToken() },
muteHttpExceptions: false
})
}
function main() {
const date = new Date();
const monthYear = Utilities.formatDate(date, "Asia/Kolkata", "MMMM yyyy");
try {
const invoiceFolderName = "Invoices"
const signatureImageFileId = "" // drive file id of signature image keep it under 200px in png format
const sender = "[email protected]";
const recieverName = "Finance Manager"
const data = {
"H4": Utilities.formatDate(date, "Asia/Kolkata", "dd/MM/yyyy"), // date
"A12": getConsultancyFeesText(date),
"H12": 0, // salary
"B16": "", // name, also used in email body
"B17": "", //address
"B18": "", // pan
"D22": "", // account holder
"D23": "", // ac number
"D24": "", // bank name
"D25": "", // ifsc
"D26": "", // account type
}
const invoiceFolder = DriveApp.getFoldersByName(invoiceFolderName).next();
// Get invoice thread for current month
const threads = GmailApp.search(`from:${sender} subject:Invoice | Consultation Charges | ${monthYear}`);
if (threads.length === 0) {
tgMessage(`🔥 Invoice processing for ${monthYear} failed: invoice email not found`)
};
const thread = threads[0];
// Save file to drive
const templateFileId = Drive.Files.insert(
{
title: monthYear,
mimeType: MimeType.GOOGLE_SHEETS,
parents: [{ id: invoiceFolder.getId() }]
},
thread.getMessages()[0].getAttachments()[0]
).id;
const templateFile = DriveApp.getFileById(templateFileId)
// Open and Edit Google Sheet
const sheet = SpreadsheetApp.openById(templateFile.getId()).getActiveSheet();
Object.entries(data).forEach(([key, value]) => {
sheet.getRange(key).setValue(value);
});
// fix ac getting cutoff
sheet.getRange("D23").setNumberFormat("@");
// fill attendance; deprecated
/* let range = sheet.getRange("B31:F52");
let values = range.getValues();
for (let i = 0; i < values.length; i += 4) {
for (let j = 0; j < values[i].length; j++) {
if (values[i][j] !== "" && values[i+1][j] == "") {
values[i+1][j] = "WFH";
}
}
}
range.setValues(values); */
// Add signature
sheet.insertImage(DriveApp.getFileById(signatureImageFileId).getBlob(), 2, 31);
SpreadsheetApp.flush();
// Convert back to Excel
const templateFileRes = fetchWithAuth(`https://docs.google.com/spreadsheets/d/${templateFile.getId()}/export?format=xlsx`)
const finalFile = invoiceFolder.createFile(templateFileRes.getBlob().setName(monthYear + '.xlsx'));
// Delete the temporary Google Sheet
templateFile.setTrashed(true)
const message_body = deIndent(
`Hi ${recieverName},
Please find my invoice for the month of ${monthYear} attached.
Thanks & Regards,
${data.B16}`
)
// Draft Reply
thread.createDraftReply(message_body, { attachments: [finalFile.getBlob()] });
tgMessage(`🚀 Invoice processed for ${monthYear} successfully: ${finalFile.getUrl()}`)
} catch (err) {
tgMessage(`🔥 Invoice processing for ${monthYear} failed: ${err}`)
throw err
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment