Skip to content
Louis Roehrs edited this page Feb 6, 2023 · 9 revisions

We have a few collections.

Users

Organizations

Campaigns

This schema uses a collection for each type of object and links between objects are embedded in the objects.

A different approach would be to put all objects in one collection keyed by UUID and call that collection 'nodes.' One other collection called 'edges' would contain a bucket of one-way links keyed by the source object and the type of link. The value would be a timestamp and a destination link. Graph traversal would then be from a node via the edges to other nodes. All relations could be represented in a consistent, scalable, and shardable manner should we scale to petabytes. In the short term, we would hit GCP a bit more often with our current, simple topology.

Users

We are using Google Cloud Platform's Firebase Authentication service to manage authentication and login flow.

Firebase Auth will give us a UID which we use as a key to the users collection in our Firestore Database collection.

The schema for the users collection:

User

  • id: String //Produced by Firebase Auth and saved by our app |
  • email: String
  • enteredLocation: String // user entered location
  • favorites: String[] // Array of organizationids favorited by the user
  • firstname: String
  • lastname: String
  • phone: String // no validation yet
  • registered: String // ISO-8601 UTC produced by Firebase Store
  • registeredAs: String // "donor", "donee" how user has registered, does not limit being the other role in the app.
  • searchFilter: String[] // Array of catalog filters selected on the search or keyword screens.

... more to come ...

Organization

These are the fields for an organization. We used existing data labels where provided from the data source to keep the model consistent.

Organization

  • See JSON example below from Guidestar Candid. Will provide proper description later. We will extend this for our needs.
  • The first extension will be for campaigns. Each organization will have a default campaign that will be setup to accept donations automatically. Donations that go to an organization without having provided a selection for a campaign will go to the default campaign. The idea is that if an organization decides to create separate campaigns, they will already be setup to distinguish the new ones from the default campaign.

Example: (do we need all of these?)

       "organization": {
         "organization_id": "7578046",  
         "ein": "39-1731296",  
         "organization_name": "Candid",  
         "also_known_as": "Foundation Center, Guidestar",  
         "mission": "Get you the information to do good",  
         "website_url": "candid.org",
         "logo_url": "candid.org",
         "profile_level": "Platinum",
         "profile_year": 2020,
         "profile_link": "https://www.guidestar.org/profile/82-4267025",
         "profile_logo": "https://www.guidestar.org/App_Themes/MainSite2/images/ProfilePageSvgs/profile-PLATINUM2021-seal.svg",
         "leader_name": "Ann Mei Chang",
         "leader_title": "CEO",
         "contact_name": "John smith",
         "contact_email": "[email protected]",
         "contact_phone": "(555) 111-5555",
         "contact_title": "Support lead",
         "number_of_employees": 55,
         "ruling_year": 2019
       },
       "properties": {
         "bmf_status": false,
         "pub78_verified": false,
         "allow_online_giving": true,
         "dei_submitted": false,
        "revoked": false,
         "defuncted_or_merged": false,
         "relationship_type": {
           "parent": true,
           "subordinate": false,
           "independent": false,
           "headquarters": true
         },
         "relationship_details": {
           "relationship_type": "parent",
           "organization_name": "Candid 2",
           "ein": "12-4566789"
         }
       },
       "geography": {
         "address_line_1": "1 Financial Sq",
         "address_line_2": "Floor 24",
         "city": "New York",
         "state": "NY",
         "zip": 10005,
         "msa": "IL - Peoria-Pekin",
         "county": "Peoria, IL",
         "latitude": 40.9052,
         "longitude": -89.5866
       },
       "taxonomies": {
         "subject_codes": [
           {
             "subject_code": "SP030000",
             "subject_code_description": "SP030000"
           }
         ],
         "population_served_codes": [
           {
             "population_served_code": "PG030000",
             "population_served_description": "People with Physical Disabilities  "
           }
         ],
         "ntee_codes": [
           {
             "ntee_code": "A00",
             "ntee_code_description": "Humanities"
           }
         ],
         "subsection_code": {
           "subsection_code": "03",
           "subsection_code_description": "501(c)(3) Public Charity"
         },
         "foundation_code": {
           "foundation_code": "15",
           "foundation_code_description": "50% tax deductible"
         }
       },
       "financials": {
         "most_recent_year": {
           "form_types": "990",
           "fiscal_year": 2020,
           "total_revenue": 2349999,
           "total_expenses": 22224499,
           "total_assets": 57426592
         },
         "bmf_gross_receipts": 2349999,
         "bmf_assets": 1849900,
         "required_to_file_990t": false,
         "a_133_audit_performed": false
       },
       "dates": {
         "seal_last_modified": "2020-01-01T01:01:01:01.000Z",
         "profile_last_modified": "2020-01-01T01:01:01:01.000Z",
         "dei_last_modified": "2020-01-01T01:01:01:01.000Z",
         "financials_last_modified": "2020-01-01T01:01:01:01.000Z",
         "last_published": "2020-01-01T01:01:01:01.000Z"
       }
     }

Clone this wiki locally