Skip to content

Instantly share code, notes, and snippets.

@bengolder
Last active April 27, 2017 22:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save bengolder/c4b376f2f70a5a21cd62c7e34ce77e33 to your computer and use it in GitHub Desktop.
Save bengolder/c4b376f2f70a5a21cd62c7e34ce77e33 to your computer and use it in GitHub Desktop.

Event Refactor

Reasons

  • ApplicationEvents are hyper focused on applicants. We need events focused on visitors
  • We Also need org user events
  • we want full funnel metrics (from visitor to applicants to followups and on)
  • We will need auditable events
  • types and uses of events are conflated
  • hard to know if where we send PII to mixpanel

Goals:

  • useful distinctions between types of events

  • make it easy to tie events to different models

  • make it easy to get a consistent, unique individual identifier for analytics

  • UUIDs for mixpanel are always people

  • events between people:

    • fire event on each person involved, other people can & should identified in metadata
    • if we can fire one event and get funnels for all involved, we should (don't think this is possible)

Goals:

  • Route applications based on things that happen to them (for example, followups)
    • itemize existing logic uses
    • itemize types to identify which are valuable
  • Log more events to mixpanel in a consistent way that excludes PII
  • Don't break existing functionality
  • Same or greater clarity about what has happened to someone's case (including existing data)
  • Just enough state-event architecture to capture existing data and history about applications

------ longer term (consider, don't build)

  • Create a consistent way to add things to app history
  • Create audit events for auditabilty
  • Add state to applications
class Event(models.Model):
    time = models.DateTimeField()

    def log_to_mixpanel(self):
        cleaned_data = self.remove_pii()
        mixpanel.delay(self.get_uuid(), cleaned_data)


class VisitorEvent(models.Model):
    visitor = models.ForeignKey(
        'intake.Visitor', related_name='visitor_events')
    event = models.OneToOneField(Event, primary_key=True)



class ApplicantEvent(models.Model):
    applicant = models.ForeignKey(
        'intake.Applicant', related_name='applicant_events')
    event = models.OneToOneField(Event, primary_key=True)


class UserEvent(models.Model):
    user = models.ForeignKey(
        'auth.User', related_name='user_events')
    event = models.OneToOneField(Event, primary_key=True)

---- 


class VisitorEvent(Event):
    visitor = models.ForeignKey(
        'intake.Visitor', related_name='visitor_events')


class ApplicantEvent(Event):
    applicant = models.ForeignKey(
        'intake.Applicant', related_name='applicant_events')


class ApplicationEvent(Event):
    application = models.ForeignKey(
        'intake.Application', related_name='application_events')


class UserEvent(Event):
    user = models.ForeignKey(
        'auth.User', related_name='user_events')

Two key uses: - logic stuff, in this case we are querying in a very targeted way (does this exist) - mixpanel, in which case we are not querying them - craft items that can be rolled up into history - initial application history base (queryable)

Both of these should make use of a one-to-one relationship - audit log

Example:

# application event type
# status update created
# tied to application id


@classmethod
def log_status_updated(cls, application_id, applicant_id, org_user, data):
    new = ApplicationEvent(type='status_updated', **kwargs)
    # so we can then query it.
    self.log_to_mixpanel()

class ApplicationHistoryEvent(models.Model):
    time = models.DateTimeField()
    applicaton = ForeignKey
    actor = ForeignKey(null=True) # null implies automated

    def log_to_mixpanel()
        pass

    def remove_pii():
        pass


class NoteAdded(models.Model):
    event = models.OneToOneField(ApplicationHistoryEvent, primary_key=True)
    notification = models.ForeignKey('intake.Note')

    def log_to_mixpanel():
        # get uuid for applicant
        # get uuid for user
        # remove PII
        # log both to mixpanel.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment