Bug fixes: - Fix pagination when pulling from Notion pages. - Fix the parsing of rollup fields.
248 lines
8.4 KiB
Nim
248 lines
8.4 KiB
Nim
import std/json, std/options, std/sequtils, std/sets, std/strutils, std/tables,
|
|
std/times
|
|
|
|
import timeutils
|
|
|
|
import ./utils
|
|
|
|
type
|
|
AddressObj* = object
|
|
id*: string
|
|
city*: string
|
|
state*: string
|
|
street*: string
|
|
suiteOrBuilding*: string
|
|
zipCode*: string
|
|
createdAt*: Option[DateTime]
|
|
lastUpdatedAt*: Option[DateTime]
|
|
|
|
|
|
FamilyObj* = object
|
|
id*: string
|
|
name*: string
|
|
headsOfHousehold*: seq[string]
|
|
headOfHouseholdIds*: seq[string]
|
|
primaryAddress*: string
|
|
primaryAddressId*: string
|
|
members*: seq[string]
|
|
memberIds*: seq[string]
|
|
createdAt*: Option[DateTime]
|
|
lastUpdatedAt*: Option[DateTime]
|
|
|
|
PersonObj* = object
|
|
id*: string
|
|
preferredName*: string
|
|
firstName*: string
|
|
middleNames*: string
|
|
lastName*: string
|
|
birthDate*: Option[DateTime]
|
|
gender*: string
|
|
primaryPhoneNumber*: string
|
|
primaryEmailAddress*: string
|
|
addresses*: seq[string]
|
|
addressIds*: seq[string]
|
|
marriedTo*: string
|
|
marriedToId*: string
|
|
anniversary*: Option[DateTime]
|
|
parents*: seq[string]
|
|
parentIds*: seq[string]
|
|
children*: seq[string]
|
|
childIds*: seq[string]
|
|
relationshipToHff*: seq[string]
|
|
createdAt*: Option[DateTime]
|
|
lastUpdatedAt*: Option[DateTime]
|
|
apiPermissions*: seq[string]
|
|
|
|
RecordType* = enum rtPerson, rtFamily, rtAddress
|
|
|
|
SyncRecordObj* = object
|
|
id*: string
|
|
knownIds*: HashSet[string]
|
|
recType*: RecordType
|
|
notionId*: string
|
|
pcoId*: string
|
|
|
|
|
|
Address* = ref AddressObj
|
|
Family* = ref FamilyObj
|
|
Person* = ref PersonObj
|
|
SyncRecord* = ref SyncRecordObj
|
|
|
|
MembershipDataSet* = ref object
|
|
addresses*: TableRef[string, Address]
|
|
families*: TableRef[string, Family]
|
|
people*: TableRef[string, Person]
|
|
|
|
func sameContents[T](a: seq[T], b: seq[T]): bool =
|
|
let aCount = toCountTable(a)
|
|
let bCount = toCountTable(b)
|
|
|
|
for k in aCount.keys:
|
|
if not bCount.hasKey(k) or aCount[k] != bCount[k]: return false
|
|
|
|
return aCount.len == bCount.len
|
|
|
|
|
|
func `==`*(a, b: Family): bool =
|
|
return a.name == b.name and
|
|
sameContents(a.headOfHouseholdIds, b.headOfHouseholdIds) and
|
|
sameContents(a.memberIds, b.memberIds) and
|
|
a.primaryAddressId == b.primaryAddressId
|
|
|
|
func `==`*(a, b: Person): bool =
|
|
return a.preferredName == b.preferredName and
|
|
a.firstName == b.firstName and
|
|
a.middleNames == b.middleNames and
|
|
a.lastName == b.lastName and
|
|
a.birthDate == b.birthDate and
|
|
a.gender == b.gender and
|
|
a.primaryPhoneNumber == b.primaryPhoneNumber and
|
|
a.primaryEmailAddress == b.primaryEmailAddress and
|
|
a.anniversary == b.anniversary and
|
|
a.marriedToId == b.marriedToId and
|
|
sameContents(a.addressIds, b.addressIds) and
|
|
sameContents(a.parentIds, b.parentIds) and
|
|
sameContents(a.childIds, b.childIds) and
|
|
sameContents(a.relationshipToHff, b.relationshipToHff)
|
|
|
|
func `$`*(rt: RecordType): string =
|
|
case rt:
|
|
of rtPerson: "Person"
|
|
of rtFamily: "Family"
|
|
of rtAddress: "Address"
|
|
|
|
func initSyncRecord*(recType: RecordType, notionId, pcoId: string, knownIds = initHashSet[string]()): SyncRecord =
|
|
result = SyncRecord(
|
|
recType: recType,
|
|
notionId: notionId,
|
|
pcoId: pcoId,
|
|
knownIds: knownIds)
|
|
|
|
result.knownIds.incl(notionId)
|
|
result.knownIds.incl(pcoId)
|
|
|
|
|
|
func toPage*(a: Address): JsonNode =
|
|
%*{
|
|
"properties": {
|
|
"City": makeTextProp("rich_text", a.city),
|
|
"State": makeSelectProp(a.state),
|
|
"Street Address": makeTextProp("title", a.street),
|
|
"Suite or Building": makeTextProp("rich_text", a.suiteOrBuilding),
|
|
"Zip Code": makeTextProp("rich_text", a.zipCode)
|
|
}
|
|
}
|
|
|
|
func toPage*(f: Family): JsonNode =
|
|
%*{
|
|
"properties": {
|
|
"Name": makeTextProp("title", f.name),
|
|
"Head(s) of Household": makeRelationProp(f.headOfHouseholdIds),
|
|
"Primary Address": makeRelationProp(@[f.primaryAddressId]),
|
|
"Members": makeRelationProp(f.memberIds)
|
|
}
|
|
}
|
|
|
|
func toPage*(p: Person): JsonNode =
|
|
%*{
|
|
"properties": {
|
|
"Preferred Name": makeTextProp("title", p.preferredName),
|
|
"First Name": makeTextProp("rich_text", p.firstName),
|
|
"Middle Names": makeTextProp("rich_text", p.middleNames),
|
|
"Last Name": makeTextProp("rich_text", p.lastName),
|
|
"Birth Date": makeDateProp(p.birthDate),
|
|
"Gender": makeSelectProp(p.gender),
|
|
"Primary Phone Number": { "phone_number": p.primaryPhoneNumber },
|
|
"Email Address": { "email": p.primaryEmailAddress },
|
|
"Relationship to HFF": makeMultiSelectProp(p.relationshipToHff),
|
|
"Address": makeRelationProp(p.addressIds),
|
|
"Married To": makeRelationProp(@[p.marriedToId]),
|
|
"Anniversary": makeDateProp(p.anniversary),
|
|
"Parents": makeRelationProp(p.parentIds),
|
|
"Children": makeRelationProp(p.childIds),
|
|
"System: API Permissions": makeMultiSelectProp(p.apiPermissions),
|
|
}
|
|
}
|
|
|
|
func toPage*(sr: SyncRecord): JsonNode =
|
|
result = %*{
|
|
"properties": {
|
|
"Notion Rec Id": makeTextProp("title", sr.notionId),
|
|
"PCO Rec Id": makeTextProp("rich_text", sr.pcoId),
|
|
"Alternate IDs": makeTextProp("rich_text", toSeq(sr.knownIds).join(";"))
|
|
}
|
|
}
|
|
|
|
case sr.recType
|
|
of rtAddress: result{"properties", "Rec Type"}= %"Address"
|
|
of rtFamily: result{"properties", "Rec Type"}= %"Family"
|
|
of rtPerson: result{"properties", "Rec Type"}= %"Person"
|
|
|
|
proc addressFromPage*(page: JsonNode): Address =
|
|
result = Address(
|
|
id: page["id"].getStr,
|
|
city: page.getText("City"),
|
|
state: page.getSelect("State"),
|
|
street: page.getTitle("Street Address"),
|
|
suiteOrBuilding: page.getText("Suite or Building"),
|
|
zipCode: page.getText("Zip Code"),
|
|
createdAt: some(parseIso8601(page["created_time"].getStr)),
|
|
lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)))
|
|
|
|
proc familyFromPage*(page: JsonNode): Family =
|
|
let primaryAddressIds = page.getRelationIds("Primary Address")
|
|
result = Family(
|
|
id: page["id"].getStr,
|
|
name: page.getTitle("Name"),
|
|
headsOfHousehold: page.getRolledupRecordTitles("Head(s) of Household (display)"),
|
|
headOfHouseholdIds: page.getRelationIds("Head(s) of Household"),
|
|
primaryAddress: if primaryAddressIds.len == 0: ""
|
|
else: page.getRolledupRecordTitles("Primary Address (display)")[0],
|
|
primaryAddressId: if primaryAddressIds.len == 0: ""
|
|
else: primaryAddressIds[0],
|
|
members: page.getRolledupRecordTitles("Members (display)"),
|
|
memberIds: page.getRelationIds("Members"),
|
|
createdAt: some(parseIso8601(page["created_time"].getStr)),
|
|
lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)))
|
|
|
|
proc personFromPage*(page: JsonNode): Person =
|
|
let marriedToIds = page.getRelationIds("Married To")
|
|
|
|
result = Person(
|
|
id: page["id"].getStr,
|
|
preferredName: page.getTitle("Preferred Name"),
|
|
firstName: page.getText("First Name"),
|
|
middleNames: page.getText("Middle Names"),
|
|
lastName: page.getText("Last Name"),
|
|
birthDate: page.getDateTime("Birth Date"),
|
|
gender: page.getSelect("Gender"),
|
|
primaryPhoneNumber: page.getPhone("Primary Phone Number"),
|
|
primaryEmailAddress: page.getEmail("Email Address"),
|
|
relationshipToHff: page.getMultiSelect("Relationship to HFF"),
|
|
addresses: page.getRollupArrayValues("Full Address").mapIt(it{"formula", "string"}.getStr),
|
|
addressIds: page.getRelationIds("Address"),
|
|
marriedTo: if marriedToIds.len == 0: ""
|
|
else: page.getRolledupRecordTitles("Married To (display)")[0],
|
|
marriedToId: if marriedToIds.len == 0: ""
|
|
else: marriedToIds[0],
|
|
anniversary: page.getDateTime("Anniversary"),
|
|
parents: page.getRolledupRecordTitles("Parents (display)"),
|
|
parentIds: page.getRelationIds("Parents"),
|
|
children: page.getRolledupRecordTitles("Children (display)"),
|
|
childIds: page.getRelationIds("Children"),
|
|
createdAt: some(parseIso8601(page["created_time"].getStr)),
|
|
lastUpdatedAt: some(parseIso8601(page["last_edited_time"].getStr)),
|
|
apiPermissions: page.getMultiSelect("System: API Permissions"))
|
|
|
|
func syncRecordFromPage*(page: JsonNode): SyncRecord =
|
|
result = SyncRecord(
|
|
id: page["id"].getStr,
|
|
notionId: page.getTitle("Notion Rec Id"),
|
|
pcoId: page.getText("PCO Rec Id"),
|
|
knownIds: toHashSet(page.getText("Alternate IDs").split(";")))
|
|
|
|
case page.getSelect("Record Type")
|
|
of "Address": result.recType = rtAddress
|
|
of "Family": result.recType = rtFamily
|
|
of "Person": result.recType = rtPerson
|