diff --git a/app/jobs/contract/human_follow_up_job.rb b/app/jobs/contract/human_follow_up_job.rb new file mode 100644 index 0000000000..4dc005af5e --- /dev/null +++ b/app/jobs/contract/human_follow_up_job.rb @@ -0,0 +1,19 @@ +# 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 HumanFollowUpJob < ApplicationJob + queue_as :low + discard_on ActiveJob::DeserializationError + + def perform(contract) + return unless contract.sent? + + ContractMailer.with(contract:).human_follow_up.deliver_later + end + + end + +end diff --git a/app/mailers/contract_mailer.rb b/app/mailers/contract_mailer.rb new file mode 100644 index 0000000000..ef7be8dec5 --- /dev/null +++ b/app/mailers/contract_mailer.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class ContractMailer < ApplicationMailer + before_action { @contract = params[:contract] } + + def human_follow_up + @party = @contract.party(:hcb) + return if @party.nil? + + mail to: @party.email, subject: @contract.human_follow_up_email_subject + end + +end diff --git a/app/models/contract.rb b/app/models/contract.rb index db1eddea0d..8c7526e20a 100644 --- a/app/models/contract.rb +++ b/app/models/contract.rb @@ -185,6 +185,10 @@ def agreement_name "agreement" end + def human_follow_up_email_subject + "[Update] #{event_name}'s #{agreement_name} still isn't signed 📝" + end + def redirect_path contractable.contract_redirect_path end diff --git a/app/models/contract/fiscal_sponsorship.rb b/app/models/contract/fiscal_sponsorship.rb index a0f6d59a99..4434e72a35 100644 --- a/app/models/contract/fiscal_sponsorship.rb +++ b/app/models/contract/fiscal_sponsorship.rb @@ -36,7 +36,10 @@ class Contract class FiscalSponsorship < Contract + HUMAN_FOLLOW_UP_AFTER = 1.month + after_update_commit :create_document!, if: ->{ event.present? && sent_with_docuseal? && aasm_state_previously_changed?(to: "signed") } + after_update_commit :schedule_human_follow_up, if: ->{ aasm_state_previously_changed?(to: "sent") } def payload signee = party :signee @@ -138,6 +141,10 @@ def agreement_name "fiscal sponsorship agreement" end + def schedule_human_follow_up + Contract::HumanFollowUpJob.set(wait: HUMAN_FOLLOW_UP_AFTER).perform_later(self) + end + def required_roles ["hcb", "signee"] end diff --git a/app/tasks/maintenance/schedule_contract_human_follow_ups_task.rb b/app/tasks/maintenance/schedule_contract_human_follow_ups_task.rb new file mode 100644 index 0000000000..06c0f1cda6 --- /dev/null +++ b/app/tasks/maintenance/schedule_contract_human_follow_ups_task.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Maintenance + class ScheduleContractHumanFollowUpsTask < MaintenanceTasks::Task + def collection + Contract::FiscalSponsorship.where(aasm_state: :sent) + end + + def process(contract) + due_at = contract.created_at + Contract::FiscalSponsorship::HUMAN_FOLLOW_UP_AFTER + + if due_at.future? + Contract::HumanFollowUpJob.set(wait_until: due_at).perform_later(contract) + else + Contract::HumanFollowUpJob.perform_later(contract) + end + end + + end +end diff --git a/app/views/contract_mailer/human_follow_up.html.erb b/app/views/contract_mailer/human_follow_up.html.erb new file mode 100644 index 0000000000..ed05a478fb --- /dev/null +++ b/app/views/contract_mailer/human_follow_up.html.erb @@ -0,0 +1,46 @@ +
Hi there! 👋
+ ++ 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. +
+ +Still waiting on:
+ ++ <%= link_to "Click here", contract_party_url(@party) %> to sign your part of the agreement. +
+<% end %> + +<% if @contract.external_id.present? %> ++ <%= link_to "View the submission on DocuSeal", @contract.docuseal_submission_url %> to see where it's stuck. +
+<% end %> + ++ If this agreement is no longer needed, you can void it so it stops chasing everyone for signatures. +
+ +
+ Thanks!
+ Here's a cookie 🍪
+