Last active
December 5, 2021 03:07
-
-
Save justinsbarrett/b9470882a06d911c2826a2cdf7323064 to your computer and use it in GitHub Desktop.
Donation processing script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const detailedOutput = false; | |
// Get tables | |
let proctable = base.getTable("Donation Processing"); | |
let reqtable = base.getTable("Donation Requests"); | |
let orgtable = base.getTable("Organizations"); | |
let contactstable = base.getTable("Contacts"); | |
// Get records from processing table | |
let procrecords = await proctable.selectRecordsAsync(); | |
// Function: myoutput | |
// Usage: selective output of certain sections, only for troubleshooting | |
function myoutput (toprint) { | |
if (detailedOutput) { | |
output.text(toprint); | |
} | |
} | |
// Build classes for organization, contact, and donation records | |
class ContactRecord { | |
constructor () { | |
this.id = ""; | |
this.name = ""; | |
this.email = ""; | |
this.phone = ""; | |
this.orgRelationship = ""; | |
this.primary = true; | |
} | |
async store () { | |
if (this.id === "") { | |
output.text("Making a new contact"); | |
this.id = await contactstable.createRecordAsync({}); | |
} | |
contactstable.updateRecordAsync(this.id, { | |
"Name": this.name, | |
"Contact Email": this.email, | |
"Contact Phone": this.phone, | |
"Relationship to Org": this.orgRelationship, | |
"Primary": this.primary | |
}); | |
} | |
} | |
class OrgRecord { | |
constructor() { | |
this.id = ""; | |
this.name = ""; | |
this.address = []; | |
this.newcontact = null; | |
} | |
async store () { | |
// Store the contact first | |
this.newcontact.store(); | |
// Store the organization data | |
if (this.id == "") { | |
this.id = await orgtable.createRecordAsync({}); | |
} | |
orgtable.updateRecordAsync(this.id, { | |
"Name": this.name, | |
"Address": this.address.join("") | |
}); | |
// Add the new contact to any existing contacts | |
let orgrecords = await orgtable.selectRecordsAsync({fields: ["Contacts"]}); | |
for (let record of orgrecords.records) { | |
if (record.id === this.id) { | |
orgtable.updateRecordAsync(record, { | |
"Contacts": [ | |
...record.getCellValue("Contacts"), | |
{id: this.newcontact.id} | |
] | |
}); | |
} | |
} | |
} | |
} | |
class DonationRecord { | |
constructor (originalid) { | |
this.id = ""; | |
this.org = null; | |
this.eventStart = new Date(); | |
this.eventEnd = new Date(); | |
this.location = ""; | |
this.audienceSize = 0; | |
this.use = ""; | |
this.useComment = ""; | |
this.originalRecord = originalid; | |
} | |
async store () { | |
// Make the new record | |
this.id = await reqtable.createRecordAsync({ | |
"Status": {name: "Incoming"} | |
}); | |
// Store the org record first | |
this.org.store(); | |
// Store the donation data | |
reqtable.updateRecordAsync(this.id, { | |
// @ts-ignore | |
"Organization": [{id: this.org.id}], | |
"Event Start": this.eventStart, | |
"Event End": this.eventEnd, | |
"Size of Audience": this.audienceSize, | |
// @ts-ignore | |
"Use": [{name: this.use}] | |
}) | |
} | |
} | |
// Make an array to contain all donations | |
let donations = []; | |
// Process all collected records | |
for (let record of procrecords.records) { | |
// Only continue if we have data for this record | |
let data = record.getCellValue("Name"); | |
if (data === null) { | |
myoutput(record.id + ": Skipping (empty)"); | |
continue; | |
} else { | |
output.text("--------------------------------------------------\n" + record.id + ": Processing"); | |
} | |
// Create new donation | |
let newdonation = new DonationRecord(record.id); | |
let org = new OrgRecord(); | |
let contact = new ContactRecord(); | |
// Split the data by newlines | |
let lines = data.split("\n"); | |
for (let line of lines) { | |
// Split each line | |
let parts = line.split(":"); | |
let linename = parts[0]; | |
// If we only have one part, assume it's part of the organization address, and append it | |
if (parts.length == 1) { | |
org.address.push(", " + linename.trim()); | |
continue; | |
} | |
// Collect the data from the Notes and Name fields | |
let notes = parts[1].trim(); | |
// Depending on what the name is, place that data somewhere | |
switch (linename) { | |
case "Organization Name": | |
myoutput(record.id + ": Org name"); | |
org.name = notes; | |
break; | |
case "Contact Name": | |
myoutput(record.id + ": Contact name"); | |
contact.name = notes; | |
break; | |
case "Contact Title / Relationship to organization": | |
myoutput(record.id + ": Contact title"); | |
contact.orgRelationship = notes; | |
break; | |
case "Contact Email": | |
myoutput(record.id + ": Contact email"); | |
contact.email = notes; | |
break; | |
case "Contact Phone": | |
myoutput(record.id + ": Contact phone"); | |
contact.phone = notes; | |
break; | |
case "Organization Address": | |
myoutput(record.id + ": Org address"); | |
org.address.push(notes.trim()); | |
break; | |
case "Event Date": | |
myoutput(record.id + ": Event start"); | |
let startdate = new Date(notes); | |
newdonation.eventStart = startdate; | |
break; | |
case "Event end date (for multi-day events)": | |
myoutput(record.id + ": Event end"); | |
let enddate = new Date(notes); | |
newdonation.eventEnd = enddate; | |
break; | |
case "Event Location": | |
myoutput(record.id + ": Event location"); | |
newdonation.location = notes; | |
break; | |
case "Expected Number of Attendees": | |
myoutput(record.id + ": Size of audience"); | |
newdonation.audienceSize = Number(notes); | |
break; | |
case "If approved, donated item will be used for": | |
myoutput(record.id + ": Use (" + notes + ")"); | |
newdonation.use = notes; | |
break; | |
case "Please specify": | |
myoutput(record.id + ": Other comment"); | |
newdonation.useComment = notes; | |
break; | |
} | |
} | |
org.newcontact = contact; | |
newdonation.org = org; | |
donations.push(newdonation); | |
} | |
// Store donations after checking for duplicate contacts and organizations | |
let allcontacts = await contactstable.selectRecordsAsync(); | |
let allorgs = await orgtable.selectRecordsAsync(); | |
for (let donation of donations) { | |
let result = ""; | |
// Look for duplicate contacts | |
for (let contact of allcontacts.records) { | |
if (donation.org.newcontact.name === contact.getCellValue("Name")) { | |
result += "⚠️ Duplicate contact name: Attaching new request to existing name."; | |
donation.org.newcontact.id = contact.id; | |
} | |
} | |
// Look for duplicate organizations | |
for (let org of allorgs.records) { | |
if (donation.org.name === org.getCellValue("Name")) { | |
result += "⚠️ Duplicate organization: Attaching new request to existing name."; | |
donation.org.id = org.id; | |
} | |
} | |
// Once we're done checking, go ahead and store the donation | |
output.text("Before..."); | |
output.inspect(donation); | |
await donation.store(); | |
output.text("After..."); | |
output.inspect(donation); | |
output.text("------------------------------------------------") | |
//proctable.updateRecordAsync(donation.originalRecord, {"Notes": result}); | |
} | |
// We're finished | |
let prefix = donations.length > 0 ? "--------------------------------------------------\n" : "" | |
let suffix = donations.length != 1 ? "s" : ""; | |
output.text(prefix + "Finished processing " + donations.length + " donation" + suffix); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment