defmodule Glific.BigQuery.Schema do
@moduledoc """
Schema for tables to be created for a dataset
"""
@doc """
Schema for contacts table
"""
# codebeat:disable[LOC]
@spec contact_schema :: list()
def contact_schema do
[
%{
description: "Unique ID for the contact",
name: "id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "Unique UUID for the row (allows us to delete duplicates)",
name: "bq_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was made on bigquery",
name: "bq_inserted_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "User name",
name: "name",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Phone number of the user; primary point of identification",
name: "phone",
type: "STRING",
mode: "REQUIRED"
},
%{
description:
"Whatsapp connection status; current options are : processing, valid, invalid & failed",
name: "provider_status",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Provider status; current options are :valid, invalid or blocked",
name: "status",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Opted language of the user for templates and other communications",
name: "language",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "The source from the contact got optin into Glific",
name: "contact_optin_method",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when we recorded an opt-in from the user",
name: "optin_time",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Time when we recorded an opt-out from the user",
name: "optout_time",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description:
"Timestamp of most recent message sent by the user to ensure we can send a valid message to the user (< 24hr)",
name: "last_message_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was first made",
name: "inserted_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was last updated",
name: "updated_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "If contact is a user and their respective user name",
name: "user_name",
type: "string",
mode: "NULLABLE"
},
%{
description: "If contact is a user and their respective role",
name: "user_role",
type: "string",
mode: "NULLABLE"
},
%{
description: "NGO generated fields for the user generated as a map",
name: "fields",
type: "RECORD",
mode: "REPEATED",
fields: [
%{
description: "Labels for NGO generated fields for the user",
name: "label",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Values of the NGO generated fields (mapped for each user and label)",
name: "value",
type: "string",
mode: "NULLABLE"
},
%{
description: "Type of the generated fields; example - string",
name: "type",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time of entry of the recorded field",
name: "inserted_at",
type: "DATETIME",
mode: "NULLABLE"
}
]
},
%{
description: "Store the settings of the user as a map (which is a jsonb object in psql).
Preferences is one field in the settings (for now). The NGO can use this field to target
the user with messages based on their preferences",
name: "settings",
type: "RECORD",
mode: "NULLABLE",
fields: [
%{
description: "Labels for the settings generated for the user",
name: "label",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Values of the generated user settings (mapped for each label)",
name: "values",
type: "RECORD",
mode: "REPEATED",
fields: [
%{
name: "key",
type: "STRING",
mode: "NULLABLE"
},
%{
name: "value",
type: "STRING",
mode: "NULLABLE"
}
]
}
]
},
%{
description: "Groups that the contact belongs to",
name: "groups",
type: "RECORD",
mode: "REPEATED",
fields: [
%{
description: "Label of the group that the contact belongs to",
name: "label",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Description of the group that the contact belongs to",
name: "description",
type: "STRING",
mode: "NULLABLE"
}
]
},
%{
description: "Tags associated with the contact",
name: "tags",
type: "RECORD",
mode: "REPEATED",
fields: [
%{
description: "Labels for the associated tags",
name: "label",
type: "STRING",
mode: "REQUIRED"
}
]
},
%{
description: "JSON object for storing the contact fields",
name: "raw_fields",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Label of all the groups that the contact belongs to",
name: "group_labels",
type: "STRING",
mode: "NULLABLE"
}
]
end
@doc """
Schema for messages table
"""
@spec message_schema :: list()
def message_schema do
[
%{
description: "Unique ID generated for each message",
name: "id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "Unique UUID for the row (allows us to delete duplicates)",
name: "bq_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was made on bigquery",
name: "bq_inserted_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description:
"Uniquely generated message UUID, in case of flow it's id of that particular node which have the message.",
name: "uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Body of the message",
name: "body",
type: "STRING",
mode: "NULLABLE"
},
%{
description:
"Type of the message; options are - text, audio, video, image, location, contact, file, sticker",
name: "type",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Whether an inbound or an outbound message",
name: "flow",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Delivery status of the message",
name: "status",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Message status as per the BSP. Options : Sent, Delivered or Read",
name: "bsp_status",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Errors if any while sending the message",
name: "errors",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Contact number of the sender of the message",
name: "sender_phone",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Contact number of the receiver of the message",
name: "receiver_phone",
type: "STRING",
mode: "REQUIRED"
},
%{
description:
"Either sender contact number or receiver contact number; created to quickly let us know who the beneficiary is",
name: "contact_phone",
type: "STRING",
mode: "REQUIRED"
},
%{
description:
"Either sender contact name or receiver contact name; created to quickly let us know who the beneficiary is",
name: "contact_name",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "User ID; this will be null for automated messages and messages received",
name: "user_phone",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "User contact name",
name: "user_name",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Message media ID",
name: "media_url",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Timestamp when message was sent from queue worker",
name: "sent_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was first made",
name: "inserted_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Tags assigned to the messages, if any",
name: "tags_label",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Flow label associated with the message",
name: "flow_label",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Flow associated with the message",
name: "flow_name",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Flow UUID for joining with flow/flow_results",
name: "flow_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Flow ID for joining with flow/flow_results",
name: "flow_id",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Longitude from where the message was sent",
name: "longitude",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Latitude from where the message was sent",
name: "latitude",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was last updated",
name: "updated_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "URL of media file stored in GCS",
name: "gcs_url",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Status if the message was an HSM",
name: "is_hsm",
type: "BOOLEAN",
mode: "NULLABLE"
},
%{
description: "reference ID for an HSM",
name: "template_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "reference ID for an interactive template",
name: "interactive_template_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "context message id for an template response",
name: "context_message_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "group message id when a flow started for a group",
name: "group_message_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "flow broadcast id when a flow started for a group",
name: "flow_broadcast_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "message broadcast id when a flow or message started for a group",
name: "message_broadcast_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "ID of the message media table reference to the message media table",
name: "media_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "ID of the profile table reference to the profile table",
name: "profile_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "ID of group reference to the group table",
name: "group_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "label of the group referenced to in group table",
name: "group_name",
type: "STRING",
mode: "NULLABLE"
}
]
end
@doc """
Schema for messages media table
"""
@spec messages_media_schema :: list()
def messages_media_schema do
[
%{
description: "Unique ID generated for each message",
name: "id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "Unique UUID for the row (allows us to delete duplicates)",
name: "bq_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was made on bigquery",
name: "bq_inserted_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "caption we received with the message",
name: "caption",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "URL of media file stored in provider",
name: "url",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "URL of media file stored in provider",
name: "source_url",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "URL of media file stored in GCS",
name: "gcs_url",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was first made",
name: "inserted_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was last updated",
name: "updated_at",
type: "DATETIME",
mode: "NULLABLE"
}
]
end
@doc """
Schema for flows table
"""
@spec flow_schema :: list()
def flow_schema do
[
%{
description: "Flow ID; key",
name: "id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "Unique UUID for the row (allows us to delete duplicates)",
name: "bq_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was made on bigquery",
name: "bq_inserted_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Name of the created flow",
name: "name",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Unique ID generated for each flow",
name: "uuid",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Time when the flow was first created",
name: "inserted_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Time when the flow was last updated",
name: "updated_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "List of keywords to trigger the flow",
name: "keywords",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Status of flow revision draft or done",
name: "status",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Revision number for the flow, if any revisions/modifications were made",
name: "revision",
type: "STRING",
mode: "REQUIRED"
}
]
end
@doc """
Schema for flow context schema
"""
@spec flow_context_schema :: list()
def flow_context_schema do
[
%{
description: "Flow Context ID; key",
name: "id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "Unique UUID for the row (allows us to delete duplicates)",
name: "bq_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was made on bigquery",
name: "bq_inserted_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Name of the current node uuid flow",
name: "node_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Unique ID generated for each flow",
name: "flow_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Unique ID generated for each flow in the glific db",
name: "flow_id",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "contact id references to the contact table",
name: "contact_id",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "contact phone references to the contact table",
name: "contact_phone",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "local result of a particular flow context",
name: "results",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Few latest messages received by the contact",
name: "recent_inbound",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Few latest messages sent to the contact",
name: "recent_outbound",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Status of the flow context is it for draft or published only",
name: "status",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Parent flow context id references to the flow context table",
name: "parent_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description:
"flow broadcast id references to the flow broadcast table, this is an old one. We will remove it in the future",
name: "flow_broadcast_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "message broadcast id references to the flow broadcast table",
name: "message_broadcast_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Check to see if the flow context is for a background or foreground flow",
name: "is_background_flow",
type: "BOOLEAN",
mode: "NULLABLE"
},
%{
description:
"Check in case we killed the flow for a contact. Not when contact finished the flow",
name: "is_killed",
type: "BOOLEAN",
mode: "NULLABLE"
},
%{
description: "Check for a flow results node",
name: "is_await_result",
type: "BOOLEAN",
mode: "NULLABLE"
},
%{
description: "Check if the flow is waiting for a action or time to resume.",
name: "wakeup_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Time when the flow was killed or completed",
name: "completed_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Time when the flow was first created",
name: "inserted_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Time when the flow was last updated",
name: "updated_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "ID of the profile table reference to the profile table",
name: "profile_id",
type: "INTEGER",
mode: "NULLABLE"
}
]
end
@doc """
Schema for flow results table
"""
@spec flow_result_schema :: list()
def flow_result_schema do
[
%{
description: "Flow Result ID",
name: "id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "Unique UUID for the row (allows us to delete duplicates)",
name: "bq_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was made on bigquery",
name: "bq_inserted_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Name of the workflow",
name: "name",
type: "STRING",
mode: "REQUIRED"
},
%{
description:
"Unique ID of the flow; we store flows with both id and uuid, since flow editor always refers to a flow by its uuid ",
name: "uuid",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Time when the flow results entry was first created for a user",
name: "inserted_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Time when the flow results entry was last updated for a user",
name: "updated_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "JSON object for storing the user responses",
name: "results",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Which specific published version of the flow is being referred to",
name: "flow_version",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Phone number of the contact interacting with the flow",
name: "contact_phone",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Name of the contact interacting with the flow",
name: "contact_name",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "ID of the flow context with which the user is associated to in the flow",
name: "flow_context_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "ID of the profile table reference to the profile table",
name: "profile_id",
type: "INTEGER",
mode: "NULLABLE"
}
]
end
@doc """
Schema for flow count table
"""
@spec flow_count_schema :: list()
def flow_count_schema do
[
%{
description: "Flow Count ID",
name: "id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "Unique UUID for the row (allows us to delete duplicates)",
name: "bq_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was made on bigquery",
name: "bq_inserted_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "UUID of the source node",
name: "source_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "UUID of the destination node",
name: "destination_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Name of the workflow",
name: "flow_name",
type: "STRING",
mode: "REQUIRED"
},
%{
description:
"Unique ID of the flow; we store flows with both id and uuid, since flow editor always refers to a flow by its uuid ",
name: "flow_uuid",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Type of the node",
name: "type",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Travel count for a node",
name: "count",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "JSON object for storing the recent messages",
name: "recent_messages",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the flow results entry was first created for a user",
name: "inserted_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Time when the flow results entry was last updated for a user",
name: "updated_at",
type: "DATETIME",
mode: "REQUIRED"
}
]
end
@doc """
Schema for the stats_global_schema table
"""
@spec stats_all_schema :: list()
def stats_all_schema do
stats_schema() ++
[
%{
description: "Organization ID",
name: "organization_id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "Organization Name",
name: "organization_name",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Organization Status",
name: "organization_status",
type: "STRING",
mode: "NULLABLE"
}
]
end
@doc """
Schema for stats_schema table
"""
@spec stats_schema :: list()
def stats_schema do
[
%{
description: "Stats ID",
name: "id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "Total number of contacts",
name: "contacts",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Total number of active contacts",
name: "active",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Number of opted in contacts",
name: "optin",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Number of opted out contacts",
name: "optout",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Total number of messages",
name: "messages",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Total number of inbound messages",
name: "inbound",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Total number of outbound messages",
name: "outbound",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Total number of HSM messages (outbound only)",
name: "hsm",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Total number of flows started today",
name: "flows_started",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Total number of flows completed today",
name: "flows_completed",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Total number of users active",
name: "users",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "The period for this record: hour, day, week, month, summary",
name: "period",
type: "STRING",
mode: "NULLABLE"
},
%{
description:
"All stats are measured with respect to UTC time, to keep things timezone agnostic.",
name: "date",
type: "DATE",
mode: "NULLABLE"
},
%{
description: "The hour that this record represents, 0..23, only for PERIOD: hour",
name: "hour",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Time when the stats entry was first created for a user",
name: "inserted_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Time when the stats results entry was last updated for a user",
name: "updated_at",
type: "DATETIME",
mode: "REQUIRED"
}
]
end
@doc """
Schema for profile table
"""
@spec profile_schema :: list()
def profile_schema do
[
%{
description: "Unique ID for the profile",
name: "id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "Unique UUID for the row (allows us to delete duplicates)",
name: "bq_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was made on bigquery",
name: "bq_inserted_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Profile Name",
name: "name",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Profile Type",
name: "type",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the stats entry was first created for a user",
name: "inserted_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Time when the stats results entry was last updated for a user",
name: "updated_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "This is a field to sync contact with profile fields",
name: "fields",
type: "RECORD",
mode: "REPEATED",
fields: [
%{
description: "Labels for NGO generated fields for the user",
name: "label",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Values of the NGO generated fields (mapped for each user and label)",
name: "value",
type: "string",
mode: "NULLABLE"
},
%{
description: "Type of the generated fields; example - string",
name: "type",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time of entry of the recorded field",
name: "inserted_at",
type: "DATETIME",
mode: "NULLABLE"
}
]
},
%{
description: "Phone number of the user; primary point of identification",
name: "phone",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Opted language of the user for templates and other communications",
name: "language",
type: "STRING",
mode: "NULLABLE"
}
]
end
@doc """
Schema for contact history table
"""
@spec contact_history_schema :: list()
def contact_history_schema do
[
%{
description: "Unique ID for the contact history",
name: "id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "event type for the contact history",
name: "event_type",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "event label for the contact history",
name: "event_label",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "event datetime for the contact history",
name: "event_datetime",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Time when the stats entry was first created for a user",
name: "inserted_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Time when the stats results entry was last updated for a user",
name: "updated_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Phone number of the user; primary point of identification",
name: "phone",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Unique UUID for the row (allows us to delete duplicates)",
name: "bq_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was made on bigquery",
name: "bq_inserted_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "ID of the profile table reference to the profile table",
name: "profile_id",
type: "INTEGER",
mode: "NULLABLE"
}
]
end
@doc """
Schema for message conversation table
"""
@spec message_conversation_schema :: list()
def message_conversation_schema do
[
%{
description: "Unique ID for the message conversation",
name: "id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "Conversation ID for the message",
name: "conversation_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Conversation ID for the message",
name: "conversation_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Deduction type for the message conversation",
name: "deduction_type",
type: "STRING",
mode: "REQUIRED"
},
%{
description: "Status if the message conversation was billed",
name: "is_billable",
type: "BOOLEAN",
mode: "NULLABLE"
},
%{
description: "Time when the message conversation was first created",
name: "inserted_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Time when the message conversation was last updated",
name: "updated_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Unique UUID for the row (allows us to delete duplicates)",
name: "bq_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was made on bigquery",
name: "bq_inserted_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Reference for the message",
name: "message_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Message conversation payload received from Gupshup",
name: "payload",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Phone number of the contact",
name: "phone",
type: "STRING",
mode: "NULLABLE"
}
]
end
@doc """
Schema for message broadcast contacts table
"""
@spec message_broadcast_contacts_schema :: list()
def message_broadcast_contacts_schema do
[
%{
description: "Unique ID for the message broadcast contacts",
name: "id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "Reference for the message broadcast",
name: "message_broadcast_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Phone number of the contact",
name: "phone",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Status of Broadcast",
name: "status",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the message broadcast contact was processed",
name: "processed_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Time when the message broadcast contact was first created",
name: "inserted_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Time when the message broadcast contact was last updated",
name: "updated_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Unique UUID for the row (allows us to delete duplicates)",
name: "bq_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was made on bigquery",
name: "bq_inserted_at",
type: "DATETIME",
mode: "NULLABLE"
}
]
end
@doc """
Schema for message broadcasts table
"""
@spec message_broadcasts_schema :: list()
def message_broadcasts_schema do
[
%{
description: "Unique ID for the message broadcast contacts",
name: "id",
type: "INTEGER",
mode: "REQUIRED"
},
%{
description: "Reference for the flow",
name: "flow_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Name of the Flow",
name: "flow_name",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Reference for the collection",
name: "group_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Name of the collection",
name: "group_name",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Status of Broadcast",
name: "status",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Reference for the message",
name: "message_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Reference for the user",
name: "user_id",
type: "INTEGER",
mode: "NULLABLE"
},
%{
description: "Phone number of the user",
name: "user_phone",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Type of broadcast",
name: "broadcast_type",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Message Params",
name: "message_params",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the message broadcast was started",
name: "started_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Time when the message broadcast was completed",
name: "completed_at",
type: "DATETIME",
mode: "NULLABLE"
},
%{
description: "Time when the message broadcast was first created",
name: "inserted_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Time when the message broadcast was last updated",
name: "updated_at",
type: "DATETIME",
mode: "REQUIRED"
},
%{
description: "Unique UUID for the row (allows us to delete duplicates)",
name: "bq_uuid",
type: "STRING",
mode: "NULLABLE"
},
%{
description: "Time when the record entry was made on bigquery",
name: "bq_inserted_at",
type: "DATETIME",
mode: "NULLABLE"
}
]
end
@doc """
Procedure for flat fields
"""
@spec flat_fields_procedure(String.t(), String.t()) :: String.t()
def flat_fields_procedure(project_id, dataset_id) do
"""
BEGIN
EXECUTE IMMEDIATE
'''
CREATE OR REPLACE VIEW `#{project_id}.#{dataset_id}.flat_fields` AS SELECT id, (SELECT STRING_AGG(DISTINCT label) from UNNEST(`groups`)) AS group_category,
'''
|| (
SELECT STRING_AGG(DISTINCT "(SELECT value FROM UNNEST(fields) WHERE label = '" || label || "') AS " || REPLACE(label, ' ', '_')
)
FROM `#{project_id}.#{dataset_id}.contacts`, UNNEST(fields)
) || '''
,(SELECT MIN(inserted_at) FROM UNNEST(fields)) AS inserted_at,
(SELECT MAX(inserted_at) FROM UNNEST(fields)) AS last_updated_at
FROM `#{project_id}.#{dataset_id}.contacts`''';
END;
"""
end
end