Skip to content

Instantly share code, notes, and snippets.

@justinsbarrett
Last active December 5, 2021 03:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justinsbarrett/b9470882a06d911c2826a2cdf7323064 to your computer and use it in GitHub Desktop.
Save justinsbarrett/b9470882a06d911c2826a2cdf7323064 to your computer and use it in GitHub Desktop.
Donation processing script
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