SlideShare una empresa de Scribd logo
1 de 14
Descargar para leer sin conexión
do something useful with 
Apps Script in 5 minutes 
3.Simple invoicing app 
Bruce McPherson 
www.mcpher.com
Snippet objectives 
● Use the lessons learned in ‘using a spreadsheet as a 
database’ 
● Gets transactions and master data from database. I’m 
using sheets as the database here. 
● Calculates and generates personalized invoice emails 
Libraries used 
● database abstraction 
● driver sheet
Add libraries to script 
create a script 
Open resources 
Add references to libraries 
Mrckbr9_w7PCphJtOzhzA_Cz3TLx7pV4j 
MHfCjPQlweartW45xYs6hFai_d-phDA33
Take a copy of the test data 
Product and Customer data 
https://docs.google.com/spreadsheets/d/1EhgZ1-q9tP1u9BSEQPIQiSGozdfjsHn3zB1JfQGbftw/edit?usp=sharing 
Transaction data 
https://docs.google.com/spreadsheets/d/1gmOEvILq0wygW3iN9exe4P0iu0x2wgwlX25D_QHgq10/edit?usp=sharing
layout what you are going to do 
function myFunction() { 
// get customer handle 
// get product handle 
// get transactions handle 
// get all the transaction data ready to be invoiced 
// organize into customers/transactions 
// now we have an array of customers and their associated transactions - join to masters 
// produce and email invoice with multiple transactions per customer 
}
create function for repeated patterns 
/** 
* open a sheet as a database 
* @param {string} sheetName the sheetName 
* @param {string} sheetId the spreadsheet id 
* @return {DbAbstraction} the handle 
*/ 
function getHandle ( sheetName, sheetId) { 
// open spreadsheet as database 
var handler = new cDbAbstraction.DbAbstraction (cDriverSheet, { 
siloid:sheetName, 
dbid:sheetId, 
}); 
if (!handler.isHappy()) throw 'unable to open sheet'; 
return handler; 
} 
We’ll call this function for each 
of the database tables we 
need to open
Get handlers for each table 
// get customer handle 
var customerHandle = getHandle ('customers' , '1EhgZ1-q9tP1u9BSEQPIQiSGozdfjsHn3zB1JfQGbftw'); 
// get product handle 
var productHandle = getHandle ('products' , '1EhgZ1-q9tP1u9BSEQPIQiSGozdfjsHn3zB1JfQGbftw'); 
// get transactions handle 
var transactionHandle = getHandle ('transactions' , '1gmOEvILq0wygW3iN9exe4P0iu0x2wgwlX25D_QHgq10');
Get the transaction data and sort it 
// get all the transaction data ready to be invoiced 
var transactionResult = transactionHandle.query ({status:'delivered'},{sort:'customer id'}); 
if (transactionResult.handleCode < 0) throw transactionResult.handleError;
Reduce transactions 
// organize into customers/transactions - data is already sorted 
var customerTransactions = transactionResult.data.reduce ( function (p,c) { 
var t = p.length ? p[p.length-1] : null; 
if (!t || c['customer id'] !== t.cid) { 
// its a new customer 
p.push( t = {cid:c['customer id'], transactions:[]} ); 
} 
t.transactions.push(c); 
return p; 
},[]); 
Reduce to one object per 
customer, so we can 
consolidate transactions to a 
single invoice
Join transactions to masters 
// now we have an array of customers and their associated transactions - join to masters 
customerTransactions.forEach ( function (d) { 
var result = customerHandle.query ({"customer id":d.cid}); 
// just fail if customer not found 
if ( result.handleCode < 0 || result.data.length !== 1 ) throw JSON.stringify(result); 
d.customer = result.data.slice()[0]; 
Look up the master data from 
customers and product table 
and join to transactions 
// get the product data 
d.transactions.forEach (function (p){ 
var result = productHandle.query ({"product id":p['product id']}); 
if ( result.handleCode < 0 || result.data.length !== 1 ) throw JSON.stringify(result); 
p.product = result.data.slice()[0]; 
}); 
});
Function to create email content 
function getEmailContent (d) { 
return '<div>' 
+ d.customer.company + '<br>' 
+ '<table><tbody><th>Product name</th><th>Quantity</th><th>Total</th>' 
+ d.transactions.map(function(e) { 
return '<tr><td>'+e.product['product name'] 
+'</td><td>'+e.quantity 
+'</td><td>'+e.quantity*e.product['unit price'] 
+'</td></tr>'; 
}).join(‘’) 
+ '<tr><td>Total</td><td></td><td>' 
+ d.transactions.reduce(function(p,c) { 
return p+c.quantity*c.product['unit price']; 
},0) 
+ '</td></tr>' 
+ '</tbody></table>' 
+ '</div>'; 
} 
Very basic email invoice. You’d 
probably want to spruce up 
and use a proper template
Send email invoices 
customerTransactions.forEach (function(d) { 
MailApp.sendEmail({ 
to: d.customer.email, 
subject: "Invoice from desktop liberation", 
htmlBody: getEmailContent (d) 
}); 
}); 
Very basic email invoice. You’d 
probably want to spruce up 
and use a proper template
Further homework 
● Using what you learned in graduating to a 
database, why not migrate some of the test 
data to a database and redo. 
● Incorporate a real email templating solution 
like Romain Vialard’s YAMM 
● Improve error handling 
● Update database status when email is sent
Follow up materials 
Take a copy of this script 
Take a copy of these slides 
Join me on G+, or the G+ community 
More on desktop liberation 
More on database abstraction

Más contenido relacionado

La actualidad más candente

Introduction tomongodb
Introduction tomongodbIntroduction tomongodb
Introduction tomongodb
Lee Theobald
 

La actualidad más candente (20)

Do something in 5 with apps scripts number 6 - fusion crossfilter
Do something in 5 with apps scripts number 6 - fusion crossfilterDo something in 5 with apps scripts number 6 - fusion crossfilter
Do something in 5 with apps scripts number 6 - fusion crossfilter
 
Dbabstraction
DbabstractionDbabstraction
Dbabstraction
 
Do something in 5 with gas 9-copy between databases with oauth2
Do something in 5 with gas 9-copy between databases with oauth2Do something in 5 with gas 9-copy between databases with oauth2
Do something in 5 with gas 9-copy between databases with oauth2
 
Goa tutorial
Goa tutorialGoa tutorial
Goa tutorial
 
Google cloud datastore driver for Google Apps Script DB abstraction
Google cloud datastore driver for Google Apps Script DB abstractionGoogle cloud datastore driver for Google Apps Script DB abstraction
Google cloud datastore driver for Google Apps Script DB abstraction
 
Data backup
Data backupData backup
Data backup
 
VBA API for scriptDB primer
VBA API for scriptDB primerVBA API for scriptDB primer
VBA API for scriptDB primer
 
Introduction tomongodb
Introduction tomongodbIntroduction tomongodb
Introduction tomongodb
 
Ajax - a quick introduction
Ajax - a quick introductionAjax - a quick introduction
Ajax - a quick introduction
 
Data visualization by Kenneth Odoh
Data visualization by Kenneth OdohData visualization by Kenneth Odoh
Data visualization by Kenneth Odoh
 
MongoDB - Aggregation Pipeline
MongoDB - Aggregation PipelineMongoDB - Aggregation Pipeline
MongoDB - Aggregation Pipeline
 
Using Cerberus and PySpark to validate semi-structured datasets
Using Cerberus and PySpark to validate semi-structured datasetsUsing Cerberus and PySpark to validate semi-structured datasets
Using Cerberus and PySpark to validate semi-structured datasets
 
New text document
New text documentNew text document
New text document
 
Testowanie JavaScript
Testowanie JavaScriptTestowanie JavaScript
Testowanie JavaScript
 
KMI System
KMI SystemKMI System
KMI System
 
Fetch data from form
Fetch data from formFetch data from form
Fetch data from form
 
RxSubject And Operators
RxSubject And OperatorsRxSubject And Operators
RxSubject And Operators
 
G* on GAE/J 挑戦編
G* on GAE/J 挑戦編G* on GAE/J 挑戦編
G* on GAE/J 挑戦編
 
MongoDB Aggregation
MongoDB Aggregation MongoDB Aggregation
MongoDB Aggregation
 
Gaelyk
GaelykGaelyk
Gaelyk
 

Similar a Do something in 5 with gas 3-simple invoicing app

[MongoDB.local Bengaluru 2018] Using Change Streams to Keep Up With Your Data
[MongoDB.local Bengaluru 2018] Using Change Streams to Keep Up With Your Data[MongoDB.local Bengaluru 2018] Using Change Streams to Keep Up With Your Data
[MongoDB.local Bengaluru 2018] Using Change Streams to Keep Up With Your Data
MongoDB
 
Developing A Real World Logistic Application With Oracle Application - UKOUG ...
Developing A Real World Logistic Application With Oracle Application - UKOUG ...Developing A Real World Logistic Application With Oracle Application - UKOUG ...
Developing A Real World Logistic Application With Oracle Application - UKOUG ...
Roel Hartman
 
Google: Drive, Documents and Apps Script - How to work efficiently and happily
Google:  Drive, Documents  and Apps Script - How to work efficiently and happilyGoogle:  Drive, Documents  and Apps Script - How to work efficiently and happily
Google: Drive, Documents and Apps Script - How to work efficiently and happily
Alessandra Santi
 
Taking Web Apps Offline
Taking Web Apps OfflineTaking Web Apps Offline
Taking Web Apps Offline
Pedro Morais
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
Yekmer Simsek
 
Enterprise workflow with Apps Script
Enterprise workflow with Apps ScriptEnterprise workflow with Apps Script
Enterprise workflow with Apps Script
ccherubino
 

Similar a Do something in 5 with gas 3-simple invoicing app (20)

computerscience-170129081612.pdf
computerscience-170129081612.pdfcomputerscience-170129081612.pdf
computerscience-170129081612.pdf
 
Computer science class 12 project on Super Market Billing
Computer science class 12 project on Super Market BillingComputer science class 12 project on Super Market Billing
Computer science class 12 project on Super Market Billing
 
[MongoDB.local Bengaluru 2018] Using Change Streams to Keep Up With Your Data
[MongoDB.local Bengaluru 2018] Using Change Streams to Keep Up With Your Data[MongoDB.local Bengaluru 2018] Using Change Streams to Keep Up With Your Data
[MongoDB.local Bengaluru 2018] Using Change Streams to Keep Up With Your Data
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
Working with data using Azure Functions.pdf
Working with data using Azure Functions.pdfWorking with data using Azure Functions.pdf
Working with data using Azure Functions.pdf
 
Developing A Real World Logistic Application With Oracle Application - UKOUG ...
Developing A Real World Logistic Application With Oracle Application - UKOUG ...Developing A Real World Logistic Application With Oracle Application - UKOUG ...
Developing A Real World Logistic Application With Oracle Application - UKOUG ...
 
Yahoo Query Language: Select * from Internet
Yahoo Query Language: Select * from InternetYahoo Query Language: Select * from Internet
Yahoo Query Language: Select * from Internet
 
Durgesh
DurgeshDurgesh
Durgesh
 
JavaScript Refactoring
JavaScript RefactoringJavaScript Refactoring
JavaScript Refactoring
 
Google: Drive, Documents and Apps Script - How to work efficiently and happily
Google:  Drive, Documents  and Apps Script - How to work efficiently and happilyGoogle:  Drive, Documents  and Apps Script - How to work efficiently and happily
Google: Drive, Documents and Apps Script - How to work efficiently and happily
 
Creating web api and consuming part 2
Creating web api and consuming part 2Creating web api and consuming part 2
Creating web api and consuming part 2
 
Finagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at PinterestFinagle and Java Service Framework at Pinterest
Finagle and Java Service Framework at Pinterest
 
gRPC in Go
gRPC in GogRPC in Go
gRPC in Go
 
Taking Web Apps Offline
Taking Web Apps OfflineTaking Web Apps Offline
Taking Web Apps Offline
 
practical9.pptx
practical9.pptxpractical9.pptx
practical9.pptx
 
Converting R to PMML
Converting R to PMMLConverting R to PMML
Converting R to PMML
 
Android Best Practices
Android Best PracticesAndroid Best Practices
Android Best Practices
 
Data infrastructure for the other 90% of companies
Data infrastructure for the other 90% of companiesData infrastructure for the other 90% of companies
Data infrastructure for the other 90% of companies
 
Enterprise workflow with Apps Script
Enterprise workflow with Apps ScriptEnterprise workflow with Apps Script
Enterprise workflow with Apps Script
 
Practica n° 7
Practica n° 7Practica n° 7
Practica n° 7
 

Último

Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Último (20)

Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024Manulife - Insurer Innovation Award 2024
Manulife - Insurer Innovation Award 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 

Do something in 5 with gas 3-simple invoicing app

  • 1. do something useful with Apps Script in 5 minutes 3.Simple invoicing app Bruce McPherson www.mcpher.com
  • 2. Snippet objectives ● Use the lessons learned in ‘using a spreadsheet as a database’ ● Gets transactions and master data from database. I’m using sheets as the database here. ● Calculates and generates personalized invoice emails Libraries used ● database abstraction ● driver sheet
  • 3. Add libraries to script create a script Open resources Add references to libraries Mrckbr9_w7PCphJtOzhzA_Cz3TLx7pV4j MHfCjPQlweartW45xYs6hFai_d-phDA33
  • 4. Take a copy of the test data Product and Customer data https://docs.google.com/spreadsheets/d/1EhgZ1-q9tP1u9BSEQPIQiSGozdfjsHn3zB1JfQGbftw/edit?usp=sharing Transaction data https://docs.google.com/spreadsheets/d/1gmOEvILq0wygW3iN9exe4P0iu0x2wgwlX25D_QHgq10/edit?usp=sharing
  • 5. layout what you are going to do function myFunction() { // get customer handle // get product handle // get transactions handle // get all the transaction data ready to be invoiced // organize into customers/transactions // now we have an array of customers and their associated transactions - join to masters // produce and email invoice with multiple transactions per customer }
  • 6. create function for repeated patterns /** * open a sheet as a database * @param {string} sheetName the sheetName * @param {string} sheetId the spreadsheet id * @return {DbAbstraction} the handle */ function getHandle ( sheetName, sheetId) { // open spreadsheet as database var handler = new cDbAbstraction.DbAbstraction (cDriverSheet, { siloid:sheetName, dbid:sheetId, }); if (!handler.isHappy()) throw 'unable to open sheet'; return handler; } We’ll call this function for each of the database tables we need to open
  • 7. Get handlers for each table // get customer handle var customerHandle = getHandle ('customers' , '1EhgZ1-q9tP1u9BSEQPIQiSGozdfjsHn3zB1JfQGbftw'); // get product handle var productHandle = getHandle ('products' , '1EhgZ1-q9tP1u9BSEQPIQiSGozdfjsHn3zB1JfQGbftw'); // get transactions handle var transactionHandle = getHandle ('transactions' , '1gmOEvILq0wygW3iN9exe4P0iu0x2wgwlX25D_QHgq10');
  • 8. Get the transaction data and sort it // get all the transaction data ready to be invoiced var transactionResult = transactionHandle.query ({status:'delivered'},{sort:'customer id'}); if (transactionResult.handleCode < 0) throw transactionResult.handleError;
  • 9. Reduce transactions // organize into customers/transactions - data is already sorted var customerTransactions = transactionResult.data.reduce ( function (p,c) { var t = p.length ? p[p.length-1] : null; if (!t || c['customer id'] !== t.cid) { // its a new customer p.push( t = {cid:c['customer id'], transactions:[]} ); } t.transactions.push(c); return p; },[]); Reduce to one object per customer, so we can consolidate transactions to a single invoice
  • 10. Join transactions to masters // now we have an array of customers and their associated transactions - join to masters customerTransactions.forEach ( function (d) { var result = customerHandle.query ({"customer id":d.cid}); // just fail if customer not found if ( result.handleCode < 0 || result.data.length !== 1 ) throw JSON.stringify(result); d.customer = result.data.slice()[0]; Look up the master data from customers and product table and join to transactions // get the product data d.transactions.forEach (function (p){ var result = productHandle.query ({"product id":p['product id']}); if ( result.handleCode < 0 || result.data.length !== 1 ) throw JSON.stringify(result); p.product = result.data.slice()[0]; }); });
  • 11. Function to create email content function getEmailContent (d) { return '<div>' + d.customer.company + '<br>' + '<table><tbody><th>Product name</th><th>Quantity</th><th>Total</th>' + d.transactions.map(function(e) { return '<tr><td>'+e.product['product name'] +'</td><td>'+e.quantity +'</td><td>'+e.quantity*e.product['unit price'] +'</td></tr>'; }).join(‘’) + '<tr><td>Total</td><td></td><td>' + d.transactions.reduce(function(p,c) { return p+c.quantity*c.product['unit price']; },0) + '</td></tr>' + '</tbody></table>' + '</div>'; } Very basic email invoice. You’d probably want to spruce up and use a proper template
  • 12. Send email invoices customerTransactions.forEach (function(d) { MailApp.sendEmail({ to: d.customer.email, subject: "Invoice from desktop liberation", htmlBody: getEmailContent (d) }); }); Very basic email invoice. You’d probably want to spruce up and use a proper template
  • 13. Further homework ● Using what you learned in graduating to a database, why not migrate some of the test data to a database and redo. ● Incorporate a real email templating solution like Romain Vialard’s YAMM ● Improve error handling ● Update database status when email is sent
  • 14. Follow up materials Take a copy of this script Take a copy of these slides Join me on G+, or the G+ community More on desktop liberation More on database abstraction