Skip to content

Data model

sandramchung edited this page Jul 31, 2017 · 14 revisions

assignment

  • id: type.string(),
  • user_id: requiredString(),
  • campaign_id: requiredString(),
  • created_at: timestamp()

campaign

  • id: type.string(),
  • organization_id: requiredString(),
  • title: optionalString(),
  • description: optionalString(),
  • is_started: type.boolean().required(),
  • due_by: type.date().required().default(null),
  • created_at: timestamp(),
  • is_archived: type.boolean().required()

campaign-contact

  • id: type.string(),
  • campaign_id: requiredString(),
  • assignment_id: optionalString(),
  • first_name: optionalString(),
  • last_name: optionalString(),
  • cell: requiredString(),
  • zip: optionalString(),
  • custom_fields: type.object().required().allowNull(false).default({}),
  • created_at: timestamp(),
  • message_status: requiredString().enum(['needsMessage','needsResponse','messaged','closed']).default('needsMessage'),
  • is_opted_out: type.boolean().default(false),
  • timezone_offset: type.string().default('').required()

canned-response

  • id: type.string(),
  • campaign_id: requiredString(),
  • text: requiredString(),
  • title: requiredString(),
  • user_id: optionalString(),
  • created_at: timestamp()

interaction-step

  • id: type.string(),
  • campaign_id: requiredString(),
  • parent_interaction_id: optionalString(),
  • question: optionalString(),
  • script: optionalString(),
  • answer_option: optionalString(),
  • created_at: timestamp()

There is one script per campaign. All of the content of a script is contained within instances of interaction-step. Answer_options for a question step are encoded as separate steps with parent_interaction_id joining to the question step id.

invite

  • id: type.string(),
  • is_valid: type.boolean().required().allowNull(false),
  • created_at: timestamp()

job-request

  • id: type.string(),
  • payload: type.object().required(),
  • queue_name: requiredString(),
  • job_type: requiredString(),
  • locks_queue: type.boolean().required().default(false),
  • assigned: type.boolean().required().default(false),
  • status: type.number().integer().required().default(0),
  • updated_at: timestamp(),
  • created_at: timestamp()

message

  • id: type.string(),
  • user_number: optionalString(),
  • contact_number: requiredString(),
  • is_from_contact: type.boolean().required().allowNull(false),
  • text: optionalString(),
  • assignment_id: requiredString(),
  • service: optionalString(),
  • send_status: requiredString().enum('QUEUED', 'SENT', 'DELIVERED', 'ERROR', 'PAUSED', 'NOT_ATTEMPTED'),
  • service_message_ids: type.array().schema(type.string()).required().default([]),
  • service_messages: type.array().schema(type.object()).required().default([]),
  • created_at: timestamp()

opt-out

  • id: type.string(),
  • cell: requiredString(),
  • assignment_id: requiredString(),
  • organization_id: requiredString(),
  • created_at: timestamp()

organization (flattened)

  • id: type.string(),
  • name: requiredString(),
  • created_at: timestamp(),
  • features: type.string().required().default(''), //should be restricted by FEATURES
  • texting_hours_enforced: type.boolean().required().default(false),
  • texting_hours_start: type.number().integer().required().min(0).max(24).default(9),
  • texting_hours_end: type.number().integer().required().min(0).max(24).default(21)

pending-message-part

  • id: type.string(),
  • service: requiredString(),
  • parent_id: optionalString(),
  • service_message: type.object().required(),
  • user_number: requiredString(),
  • contact_number: requiredString(),
  • created_at: timestamp()

question-response

  • id: type.string(),
  • campaign_contact_id: requiredString(),
  • interaction_step_id: requiredString(),
  • value: requiredString(),
  • created_at: timestamp() interaction_step_id is the interaction_step ID of the corresponding question step.

user

  • id: type.string(),
  • auth0_id: requiredString(),
  • first_name: requiredString(),
  • last_name: requiredString(),
  • cell: requiredString(),
  • email: requiredString(),
  • created_at: timestamp(),
  • assigned_cell: type.string(),
  • is_superadmin: type.boolean()

user-cell

  • id: type.string(),
  • cell: requiredString(),
  • user_id: requiredString(),
  • service: type.string().required().enum('nexmo', 'twilio'),
  • is_primary: type.boolean().required()

user-organization

  • id: type.string(),
  • user_id: requiredString(),
  • organization_id: requiredString(),
  • role: requiredString().enum('OWNER', 'ADMIN', 'TEXTER')

zip-code

In case you are curious, yes there are zip codes that each map to multiple cities (100 or so) and timezones.

  • zip: requiredString(),
  • city: requiredString(),
  • state: requiredString(),
  • location: type.point().required().allowNull(false),
  • timezone_offset: type.number().required().allowNull(false),
  • has_dst: type.boolean().required().allowNull(false)

Changes to questions:

Before migration:

{
    "left": {
        "answer_option":  "" ,
        "answer_options": [
        {
        "interaction_step_id":  "d48489e3-14a0-57ad-a3fd-e60cf7479215" ,
        "value":  "Yes"
        } ,
        {
        "interaction_step_id":  "569a1035-af4f-5d22-84c9-63a630596169" ,
        "value":  "No"
        } ,
        {
        "interaction_step_id":  "6a74aecc-cffe-545b-a0a2-dae38ca7fd0f" ,
        "value":  "No but I'd like to hear more about cat events"
        }
        ] ,
        "campaign_id":  "69f6205f-0f59-49ac-a58c-7bfcba9ad80e" ,
        "created_at": Sat Jul 01 2017 01:41:51 GMT+00:00 ,
        "id":  "aa237c45-cca4-5f03-91a4-5b6042afeb02" ,
        "parent_interaction_id":  "" ,
        "question":  "Can you attend this cat event?" ,
        "script":  "Hello {firstName}. I'm {texterFirstName}."
    }
}


{
    "left": {
        "answer_option":  "" ,
        "answer_options": [ ],
        "campaign_id":  "69f6205f-0f59-49ac-a58c-7bfcba9ad80e" ,
        "created_at": Sat Jul 01 2017 01:41:51 GMT+00:00 ,
        "id":  "d48489e3-14a0-57ad-a3fd-e60cf7479215" ,
        "parent_interaction_id":  "" ,
        "question":  "" ,
        "script":  "Great {firstName}! Please bring {catName}."
    }
}

{
    "left": {
    "answer_option":  "" ,
    "answer_options": [ ],
    "campaign_id":  "69f6205f-0f59-49ac-a58c-7bfcba9ad80e" ,
    "created_at": Sat Jul 01 2017 01:41:51 GMT+00:00 ,
    "id":  "569a1035-af4f-5d22-84c9-63a630596169" ,
    "parent_interaction_id":  "" ,
    "question":  "" ,
    "script":  "Sorry to hear that. Have a nice day {firstName}!"
    }
}

{
    "left": {
    "answer_option":  "" ,
    "answer_options": [ ],
    "campaign_id":  "69f6205f-0f59-49ac-a58c-7bfcba9ad80e" ,
    "created_at": Sat Jul 01 2017 01:41:51 GMT+00:00 ,
    "id":  "6a74aecc-cffe-545b-a0a2-dae38ca7fd0f" ,
    "parent_interaction_id":  "" ,
    "question":  "" ,
    "script": "Great {firstName}! You and {catName} can attend any of our Sunday catnip crawls. Tell me your email address and I'll send you more details."
    }
}

After migration:

{
    "left": {
        "answer_option":  "" ,
        "answer_options": [ ],
        "campaign_id":  "69f6205f-0f59-49ac-a58c-7bfcba9ad80e" ,
        "created_at": Sat Jul 01 2017 01:41:51 GMT+00:00 ,
        "id":  "aa237c45-cca4-5f03-91a4-5b6042afeb02" ,
        "parent_interaction_id":  "" ,
        "question":  "Can you attend this cat event?" ,
        "script":  "Hello {firstName}. I'm {texterFirstName}."
    }
}

{
    "left": {
        "answer_option":  "Yes" ,
        "answer_options": [ ],
        "campaign_id":  "69f6205f-0f59-49ac-a58c-7bfcba9ad80e" ,
        "created_at": Sat Jul 01 2017 01:41:51 GMT+00:00 ,
        "id":  "d48489e3-14a0-57ad-a3fd-e60cf7479215" ,
        "parent_interaction_id":  "aa237c45-cca4-5f03-91a4-5b6042afeb02" ,
        "question":  "" ,
        "script":  "Great {firstName}! Please bring {catName}."
    }
}

{
    "left": {
    "answer_option":  "No" ,
    "answer_options": [ ],
    "campaign_id":  "69f6205f-0f59-49ac-a58c-7bfcba9ad80e" ,
    "created_at": Sat Jul 01 2017 01:41:51 GMT+00:00 ,
    "id":  "569a1035-af4f-5d22-84c9-63a630596169" ,
    "parent_interaction_id":  "aa237c45-cca4-5f03-91a4-5b6042afeb02" ,
    "question":  "" ,
    "script":  "Sorry to hear that. Have a nice day {firstName}!"
    }
}

{
    "left": {
    "answer_option":  "No but I'd like to hear more about cat events" ,
    "answer_options": [ ],
    "campaign_id":  "69f6205f-0f59-49ac-a58c-7bfcba9ad80e" ,
    "created_at": Sat Jul 01 2017 01:41:51 GMT+00:00 ,
    "id":  "6a74aecc-cffe-545b-a0a2-dae38ca7fd0f" ,
    "parent_interaction_id":  "aa237c45-cca4-5f03-91a4-5b6042afeb02" ,
    "question":  "" ,
    "script": "Great {firstName}! You and {catName} can attend any of our Sunday catnip crawls. Tell me your email address and I'll send you more details."
    }
}