Skip to content

Instantly share code, notes, and snippets.

@adamrobbie
Created January 10, 2016 05:21
Show Gist options
  • Save adamrobbie/f821f3c95e4a3185c4c2 to your computer and use it in GitHub Desktop.
Save adamrobbie/f821f3c95e4a3185c4c2 to your computer and use it in GitHub Desktop.
HRFlow discussion
My current understanding of the process..
- 1 upload excell
- 2 hrflow creates form collector and a set or participant flows
- 3 form collector sends emails to participants with a link to the appropriate HRFORM
- upon completion of the partiicpant form, HRForms uses the completionURL to let us know
- if they have a spouse (unsure from the weird payload how this is deteremined, marriage status etc), we should send an email
to the spouse with another HRForm url
- upon that completion we'll recieve another post to our submitform endpoint and fetch the data again and send the event along to the
participant form.
- eventually we want the participant fsm to complete with a signed boolean, unsure when this is determined as from the code this is assumed to happen
I get the rest of it though, upon completion post to GtGo etc...
1) Where is the appropriate place to send the spouse email.
- in the participant FSM or a new FSM for the spouse ( but i don’t think thats right)
- i'm guessing we can use the same HRForms access token for the spouse form as we did with the partiicpant form
- to generate the token for our app we need the id of the flow which is not accessible from within the participant FSM so maybe we add the flow id like we do with the parent flow
- Or we do it in the controller with access to the spouse data after retrieving said data from HRForms.get_form_data/3
- but if we do it in the controller how do we not sent it twice (use a different completionURL endpoint for the spouse form maybe?
2) Upon completion of the spouse form and HRForms posts to our completion webhook
I've included the relavant code below for reference and commenting purposes
```
# FIXME: Not committing this because presently we get name: nil for the spouse email form field
# spouse = data |> Enum.find(fn(field) -> field["name"] == "spouse" end)
# if(spouse) do
# HRFlows.Flow.handle_event(flow, {:receive_signature_and_spouse_information, %{signed: true, spouse: %{first_name: spouse["first"], last_name: spouse["last"]}})
# else
# HRFlows.Flow.handle_event(flow, {:receive_signature_and_spouse_information, %{signed: true, spouse: nil}})
# end
HRFlows.Flow.handle_event(flow, {:receive_signature_and_spouse_information, %{signed: true, spouse: nil}})
```
```
defmodule HRFlows.GenFlowTypes.GrantThornton.FormsCollection.ParticipantCollector do
require Logger
defmodule Participant do
defstruct [:first_name, :last_name, :email, :employer_name, :agreement_date, :due_date, :member_firm_name, :spouse, :signed, :spouse_signed]
end
defmodule Data do
defstruct participant: %Participant{}, token: nil, parent_flow_id: nil
end
use HRFlows.GenFlowTypes.FSM, initial_state: :waiting_for_token, initial_data: %Data{}
@twenty_minutes 20 * 60 * 1_000
defgstate waiting_for_token, timeout: @twenty_minutes do
defgevent receive_token(token), transitions_to: [:waiting_for_signature_and_spouse_information], data: data do
next_state(:waiting_for_signature_and_spouse_information, %Data{ data | token: token })
end
end
defgstate waiting_for_signature_and_spouse_information, timeout: @twenty_minutes do
defgevent receive_signature_and_spouse_information(%{signed: signed, spouse: spouse = %{first_name: _spouse_first_name, last_name: _spouse_last_name, email: _spouse_email}}), transitions_to: [:waiting_for_spouse_signature], data: data do
next_state(:waiting_for_spouse_signature, %Data{data | participant: %Participant{data.participant | spouse: spouse, signed: signed}})
end
defgevent receive_signature_and_spouse_information(%{signed: signed, spouse: nil}), transitions_to: [:complete], data: data do
{:ok, parent_flow} = HRFlows.Store.get(HRFlows.Flow, data.parent_flow_id)
data = %Data{data | participant: %Participant{data.participant | signed: signed}}
HRFlows.Flow.handle_event(parent_flow, {:receive_data, data.participant})
:ok = GTGO.complete(data.participant.email)
next_state(:complete, data)
end
end
defgstate waiting_for_spouse_signature, timeout: @twenty_minutes do
defgevent receive_spouse_signature(%{signed: signed}), transitions_to: [:complete], data: data do
{:ok, parent_flow} = HRFlows.Store.get(HRFlows.Flow, data.parent_flow_id)
HRFlows.Flow.handle_event(parent_flow, {:receive_data, data.participant})
:ok = GTGO.complete(data.participant.email)
next_state(:complete, %Data{ data | participant: %Participant{data.participant | spouse_signed: signed}})
end
end
defgstate complete, timeout: @twenty_minutes
end
```
@adamrobbie
Copy link
Author

Updated. what i have so far for comments

defmodule HRFlows.GenFlowTypes.GrantThornton.FormsCollection.ParticipantCollector do
  require Logger

  defmodule Participant do
    defstruct [:first_name, :last_name, :email, :employer_name, :agreement_date, :due_date, :member_firm_name, :spouse, :signed, :spouse_signed]
  end

  defmodule Data do
    defstruct participant: %Participant{}, token: nil, parent_flow_id: nil, flow_id: nil, spouse_token: nil
  end

  use HRFlows.GenFlowTypes.FSM, initial_state: :waiting_for_token, initial_data: %Data{}

  @twenty_minutes 20 * 60 * 1_000

  defgstate waiting_for_token, timeout: @twenty_minutes do
    defgevent receive_token(token), transitions_to: [:waiting_for_signature_and_spouse_information], data: data do
      next_state(:waiting_for_signature_and_spouse_information, %Data{ data | token: token })
    end
  end

  defgstate waiting_for_signature_and_spouse_information, timeout: @twenty_minutes do
    defgevent receive_flow_id(flow_id), transitions_to: [:waiting_for_signature_and_spouse_information], data: data do
      next_state(:waiting_for_signature_and_spouse_information, %Data{data | flow_id: flow_id})
    end

    # THIS WORKS FOR ME WHEN I TRIGGER MANUALLY
    defgevent receive_signature_and_spouse_information(%{signed: signed, spouse: spouse = %{first_name: spouse_first_name, last_name: spouse_last_name, email: spouse_email}}), transitions_to: [:waiting_for_spouse_signature], data: data do
      if data.flow_id do
        Logger.warn "get the link from HRForms to email to the spouse"
        form_id = Application.get_env(:h_r_flows, :grant_thornton_forms_collection_spouse_form_id)
        secret = Application.get_env(:h_r_flows, HRFlows.Flow)[:signing_secret]

        my_token =
          %{
            flow_id: data.flow_id,
            flow_state: "waiting_for_signature_and_spouse_information"
          }
          |> Joken.token
          |> Joken.sign(Joken.hs256(secret))

        host = Application.get_env(:h_r_flows, HRFlows.Endpoint)[:url][:host]

        #maybe use a different endpoint becuase of the spouse_token
        completion_url = "http://#{host}/api/flow/#{data.flow_id}/submit_hrform?event=receive_data&token=#{my_token.token}"
        Logger.warn completion_url

        # hopefully we can use the structure to get the proper form link
        form_data = %{
          user: %{
            firstName: spouse_first_name,
            lastName: spouse_last_name,
            spouseName: "",
            company: data.participant.employer_name,
            email: spouse_email
          },
          completionURL: completion_url
        }
        {:ok, {link, token}} = HRForms.get_form_link_and_token(form_id, form_data)
        {:ok, flow} = HRFlows.Store.get(HRFlows.Flow, data.flow_id)
        mailer = Application.get_env(:h_r_flows, HRFlows.Flow)[:mailer]
        apply(mailer, :send, [:link_to_flow_form, %{:flow => flow, email: spouse_email, flow_state: "waiting_for_signature_and_spouse_information", body: "Please fill out <a href='#{link}'>this form</a> to confirm your information for Grant Thornton."}])
      end
      next_state(:waiting_for_spouse_signature, %Data{data | participant: %Participant{data.participant | spouse: spouse, signed: signed}, spouse_token: token})
    end

    defgevent receive_signature_and_spouse_information(%{signed: signed, spouse: nil}), transitions_to: [:complete], data: data do
      {:ok, parent_flow} = HRFlows.Store.get(HRFlows.Flow, data.parent_flow_id)
      data = %Data{data | participant: %Participant{data.participant | signed: signed}}
      HRFlows.Flow.handle_event(parent_flow, {:receive_data, data.participant})
      :ok = GTGO.complete(data.participant.email)
      next_state(:complete, data)
    end
  end

  defgstate waiting_for_spouse_signature, timeout: @twenty_minutes do
    defgevent receive_spouse_signature(%{signed: signed}), transitions_to: [:complete], data: data do
      {:ok, parent_flow} = HRFlows.Store.get(HRFlows.Flow, data.parent_flow_id)
      HRFlows.Flow.handle_event(parent_flow, {:receive_data, data.participant})
      :ok = GTGO.complete(data.participant.email)
      next_state(:complete, %Data{ data | participant: %Participant{data.participant | spouse_signed: signed}})
    end
  end

  defgstate complete, timeout: @twenty_minutes
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment