Skip to content
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions app/jobs/contract/operations_update_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

class Contract
# Nudges HCB's party when an agreement they're the point of contact for is
# still unsigned. Unlike Contract::Party::ReminderJob this doesn't care
# whether HCB is the one holding things up (or maybe they forgot to sign...).
class OperationsUpdateJob < ApplicationJob
queue_as :low
discard_on ActiveJob::DeserializationError

def perform(contract)
return unless contract.sent?

party = contract.party(:hcb)
return if party.nil?

Contract::PartyMailer.with(party:).operations_update.deliver_later
end

end

end
6 changes: 6 additions & 0 deletions app/mailers/contract/party_mailer.rb

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would actually separate this from the concept of a contract party. I would have this live in the contract itself. This is because contract parties are intended to be generic and work for all types of parties, including the organizer, co-signer, and HCB operations. Instead, what we're looking for here is stale contracts, and I would say that it's more of a contract-level concept rather than per party. My recommendation is that you move this to the contract mailer.

Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ def reminder
template_name: "remind_#{@party.role}"
end

def operations_update
mail to: @party.email,
subject: @party.operations_update_email_subject,
template_name: "operations_update_#{@party.role}"
end
Comment thread
mattsoh marked this conversation as resolved.
Outdated

private

def set_party
Expand Down
7 changes: 7 additions & 0 deletions app/models/contract/fiscal_sponsorship.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@

class Contract
class FiscalSponsorship < Contract
OPERATIONS_UPDATE_AFTER = 1.month

after_update_commit :create_document!, if: ->{ event.present? && sent_with_docuseal? && aasm_state_previously_changed?(to: "signed") }
after_update_commit :schedule_operations_update, if: ->{ aasm_state_previously_changed?(to: "sent") }

def payload
signee = party :signee
Expand Down Expand Up @@ -125,6 +128,10 @@ def agreement_name
"fiscal sponsorship agreement"
end

def schedule_operations_update
Contract::OperationsUpdateJob.set(wait: OPERATIONS_UPDATE_AFTER).perform_later(self)
end

def required_roles
["hcb", "signee"]
end
Expand Down
4 changes: 4 additions & 0 deletions app/models/contract/party.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,10 @@ def reminder_email_subject
"[Action Needed] Sign the #{contract.agreement_name} for #{contract.event_name} on HCB 📝"
end

def operations_update_email_subject
"[Update] #{contract.event_name}'s #{contract.agreement_name} still isn't signed 📝"
end

# We may miss a webhook or load a page before we've received the webhook,
# so we can manually sync the party with this method!
def sync_with_docuseal
Expand Down
20 changes: 20 additions & 0 deletions app/tasks/maintenance/schedule_contract_operations_updates_task.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

module Maintenance
class ScheduleContractOperationsUpdatesTask < MaintenanceTasks::Task
def collection
Contract::FiscalSponsorship.where(aasm_state: :sent)
end

def process(contract)
due_at = contract.created_at + Contract::FiscalSponsorship::OPERATIONS_UPDATE_AFTER

if due_at.future?
Contract::OperationsUpdateJob.set(wait_until: due_at).perform_later(contract)
else
Contract::OperationsUpdateJob.perform_later(contract)
end
end
Comment thread
mattsoh marked this conversation as resolved.

end
end
46 changes: 46 additions & 0 deletions app/views/contract/party_mailer/operations_update_hcb.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<p>Hi there! 👋</p>

<p>
The <%= @contract.agreement_name %> for
<% if @contract.contractable.is_a?(Event::Application) %>
<%= link_to "#{@contract.event_name}'s application", submission_application_url(@contract.contractable) %>
<% elsif @contract.contractable.is_a?(OrganizerPositionInvite) %>
<%= link_to "an invitation to #{@contract.event_name}", organizer_position_invite_url(@contract.contractable) %>
<% else %>
<%= @contract.event_name %>
<% end %>
was sent <%= time_ago_in_words @contract.created_at %> ago and still hasn't been signed by everyone.
You're the HCB point of contact on it, so we wanted to give you an update.
</p>

<p>Still waiting on:</p>

<ul>
<% @contract.parties.reject(&:signed?).each do |pending_party| %>
<li>
<%= pending_party.hcb? ? "You (HCB Operations)" : pending_party.role.humanize %> &mdash;
<%= pending_party.email %>
</li>
<% end %>
</ul>

<% if @party.pending? %>
<p>
<%= link_to "Click here", contract_party_url(@party) %> to sign your part of the agreement.
</p>
<% end %>

<% if @contract.external_id.present? %>
<p>
<%= link_to "View the submission on DocuSeal", @contract.docuseal_submission_url %> to see where it's stuck.
</p>
<% end %>

<p>
If this agreement is no longer needed, you can void it so it stops chasing everyone for signatures.
</p>

<p>
Thanks!<br>
Here's a cookie 🍪
</p>