Compare commits

...

9 Commits

Author SHA1 Message Date
bilal
13084cc4a3 fix MR comments 2020-06-18 09:47:40 +02:00
bilal
fd2b33039c fix MR comments 2020-06-18 09:39:38 +02:00
bilal
0c669ab3f3 rebase master 2020-06-17 15:06:30 +02:00
bilal
f2b6bf8351 use guardian_address_street1 for old guardian_address 2020-06-17 15:00:59 +02:00
bilal
50d8ea158e destructure guardian address field for appearance release 2020-06-17 15:00:22 +02:00
Senad Uka
a7b90c223b Upstream sync 2020-06-17 14:39:10 +02:00
Senad Uka
9a540efc74 Upstream sync 2020-06-16 17:11:04 +02:00
Senad Uka
028e946fcf Upstream sync 2020-06-15 08:33:23 +02:00
Senad Uka
fbf3173747 Upstream sync 2020-06-12 16:38:59 +02:00
50 changed files with 892 additions and 185 deletions

View File

@@ -95,14 +95,28 @@ rake i18n:sort
```
## Zoom.us integration
DirectMe app offers live broadcasting. Users are offered to paralelly connect to the Zoom meeting to have a video conference while the streaming happens. In order to use the Zoom functionality, the app needs to have the API keys provided. You need Zoom PRO account for this feature.
DirectMe app offers live broadcasting feature. Users are offered to paralelly connect to the Zoom meeting to have a video conference while the streaming happens. In order to use the Zoom functionality, the app needs to have the API and verification token keys provided along with the account number that is available after login into the Zoom account. You need to have Zoom PRO subscription in order to use this feature.
#### Zoom.us api keys
1. Log in to you zoom.us account
2. Go to https://marketplace.zoom.us/develop/create
3. Choose JWT application
4. Copy API Key and API Secret
5. Set up ZOOM_API_KEY and ZOOM_API_SECRET environment variables
#### Setup
There is some configuration that has to be done through the API on the Zoom account so that you can use the feature. Run `rails zoom:setup` rake task to do it.
#### Zoom.us webhooks
To ensure integrity in between different Zoom environments, the app uses Zoom webhooks. To set them up, go to https://marketplace.czoom.us -> Develop -> JWT app -> Feature -> Event Subscriptions and enable following hooks:
* Start Meeting
* End Meeting
* All Recordings have completed
* User has been created
* User had been deleted
#### Syncing app with Zoom account configuration
If you are setting up the app to use Zoom account that has been previously used with DirectME, it is a good idea to make sure that the db state reflects the account situation. To do that, run `rails zoom:sync` rake task.
## Working Locally

View File

@@ -8,11 +8,16 @@ $(document).on "turbolinks:load", ->
# Called when the subscription has been terminated by the server
received: (data) ->
return unless document.querySelector("meta[name=broadcast-token][content='#{broadcastToken}']")
switch data.event
when "broadcast_stream_update" then @refreshBroadcastVideo(data)
when "stream_recording_ready" then @showBroadcastRecordings(data)
when "file_upload_update" then @refreshBroadcastFilesTab(data)
when "broadcast_stream_update"
return unless document.querySelector("meta[name=broadcast-token][current=true][content='#{broadcastToken}']")
@refreshBroadcastVideo(data)
when "stream_recording_ready"
return unless document.querySelector("meta[name=broadcast-token][current=true][content='#{broadcastToken}']")
@showBroadcastRecordings(data)
when "file_upload_update"
return unless document.querySelector("meta[name=broadcast-token][content='#{broadcastToken}']")
@refreshBroadcastFilesTab(data)
refreshBroadcastVideo: (data) ->
$("#broadcast_updates").html data.status_content

View File

@@ -1,11 +1,16 @@
$(document).on("change", "[data-toggle=collapse-select]", function(event) {
const select = event.target;
const target = select.dataset.target;
const showValues = JSON.parse(select.dataset.showValues);
if (showValues.indexOf(select.value) > -1) {
$(target).show("fast");
} else {
$(target).hide("fast");
}
const mappings = JSON.parse(select.dataset.targetShowValuesMapping);
$.each(mappings, function( key, value ) {
if (value.indexOf(select.value) > -1) {
$(key).show("fast");
} else {
$(key).hide("fast");
}
});
});
$(document).on("turbolinks:load", function() {
$("[data-toggle=collapse-select]").trigger("change");
});

View File

@@ -31,7 +31,7 @@ u {
}
.page {
page-break-before: always;
page-break-before: always;
}
.logo {
@@ -44,6 +44,14 @@ u {
text-align: right;
}
.qr-code {
margin-right: -30px;
}
.do-not-copy-warning {
padding-right: 15px;
}
.heading-table td {
width: 50%;
}

View File

@@ -0,0 +1,50 @@
# Duplicated from ActiveStorage::DirectUploadsController
# https://github.com/rails/rails/blob/v6.0.0/activestorage/app/controllers/active_storage/direct_uploads_controller.rb
class Api::DirectUploadsController < Api::ApiController
include ActiveStorage::SetCurrent
deserializable_resource :direct_upload, only: [:create]
def create
blob = ActiveStorage::Blob.create_before_direct_upload!(blob_params)
render jsonapi: DirectUpload.new(blob)
end
private
def blob_params
params.
require(:direct_upload).
permit(:type, :filename, :byte_size, :checksum, :content_type, :metadata).
except(:type).
to_h.symbolize_keys
end
class DeserializableDirectUpload < JSONAPI::Deserializable::Resource
attributes :filename, :byte_size, :checksum, :content_type, :metadata
end
class SerializableDirectUpload < JSONAPI::Serializable::Resource
type 'direct_upload'
attributes :id, :key, :signed_id, :url, :headers
end
class DirectUpload
delegate :id, :key, :signed_id, to: :blob
attr_reader :blob
def initialize(blob)
@blob = blob
end
def url
blob.service_url_for_direct_upload
end
def headers
blob.service_headers_for_direct_upload
end
end
end

View File

@@ -3,7 +3,6 @@
class AppearanceReleaseImportsController < ApplicationController
include AppearanceReleaseContext
include ProjectContext
include CreateReleasableJobs
before_action :set_project, only: [:create]
@@ -11,24 +10,16 @@ class AppearanceReleaseImportsController < ApplicationController
def create
authorize AppearanceRelease
@failed_files = []
attachments = appearance_release_params
if attachments.nil?
alert_message = t 'appearance_releases.create.no_attachments'
redirect_to [@project, :appearance_releases], alert: alert_message
else
attachments.each do |attachment|
create_imported_appearance_release attachment
end
MatchAppearanceReleasesJob.perform_later(@project, attachments)
notice_message = t 'appearance_releases.create.matching_started'
redirect_to [@project, :appearance_releases], notice: notice_message
end
unless @failed_files.empty?
alert_message = t 'appearance_releases.create.failed_import'
alert_message += '<br><ul>'
@failed_files.each { |file_name| alert_message += "<li>#{file_name}</li>" }
alert_message += '</ul>'
end
redirect_to [@project, :appearance_releases], alert: alert_message
end
private
@@ -45,45 +36,7 @@ class AppearanceReleaseImportsController < ApplicationController
params.require(:attachments)
end
def build_appearance_release(params = {})
authorize appearance_releases.build(params)
end
def log_create_analytics
TrackAnalyticsJob.perform_later(Current.user, Current.account, :track_create_non_native_release, release_type: AppearanceRelease.to_s, user_agent: request.user_agent, user_ip: request.remote_ip)
end
def create_imported_appearance_release(attachment)
blob = ActiveStorage::Blob.find_signed(attachment)
return if blob.nil?
extension = blob.filename.extension_with_delimiter
unless AppearanceRelease.acceptable_import_file_extensions.include? extension
blob.purge
@failed_files << blob.filename
return
end
random_contract_no = AppearanceRelease.random_contract_number.to_s
appearance_release_params = {
person_last_name: random_contract_no
}
if blob.image?
appearance_release_params[:person_photo] = attachment
appearance_release_params[:person_first_name] = I18n.t('appearance_releases.shared.imported_appearance_release_headshot_name')
elsif extension == '.pdf'
appearance_release_params[:contract] = attachment
appearance_release_params[:person_first_name] = I18n.t('appearance_releases.shared.imported_appearance_release_contract_name')
end
appearance_release = build_appearance_release(appearance_release_params)
if appearance_release.save(context: :non_native)
log_create_analytics
after_create appearance_release
else
@failed_files << blob.filename
end
def acceptable_extensions
AppearanceRelease.acceptable_import_file_extensions
end
end

View File

@@ -78,7 +78,7 @@ class AppearanceReleasesController < ApplicationController
end
def appearance_release_params
params.require(:appearance_release).permit(:contract, :guardian_address, :guardian_first_name, :guardian_last_name, :guardian_phone, :guardian_photo, :minor,
params.require(:appearance_release).permit(:contract, :guardian_address_street1, :guardian_first_name, :guardian_last_name, :guardian_phone, :guardian_photo, :guardian_email, :minor,
:person_address, :person_first_name, :person_last_name, :person_phone, :person_email, :person_photo,
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,

View File

@@ -61,7 +61,12 @@ class ContractTemplatesController < ApplicationController
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
:term_id, :term_text,
:restriction_id, :restriction_text)
:restriction_id, :restriction_text,
:question_1_text, :question_2_text,
:question_3_text, :question_4_text,
:question_5_text, :question_6_text,
:question_7_text, :question_8_text,
:question_9_text, :question_10_text)
end
def download_attributes

View File

@@ -39,9 +39,25 @@ class Public::AppearanceReleasesController < Public::BaseController
authorize appearance_releases.build(params)
end
def guardian_params
%i[
guardian_first_name
guardian_last_name
guardian_phone
guardian_email
guardian_photo
guardian_address_street1
guardian_address_street2
guardian_address_city
guardian_address_state
guardian_address_zip
guardian_address_country
]
end
def appearance_release_params
params.require(:appearance_release).permit(:person_address, :person_first_name, :person_last_name, :person_phone, :person_email, :person_photo,
:guardian_address, :guardian_first_name, :guardian_last_name, :guardian_phone, :guardian_photo, :minor,
guardian_params, :minor,
:signature_base64, :person_date_of_birth,
:locale, :contract_template,)
end

View File

@@ -48,6 +48,11 @@ class Public::MedicalReleasesController < Public::BaseController
:signature_base64,
:locale,
:contract_template,
:question_1_answer, :question_2_answer,
:question_3_answer, :question_4_answer,
:question_5_answer, :question_6_answer,
:question_7_answer, :question_8_answer,
:question_9_answer, :question_10_answer,
photos: [],
)
end

View File

@@ -0,0 +1,100 @@
# frozen_string_literal: true
class MatchAppearanceReleasesJob < ApplicationJob
queue_as :default
def perform(project, attachments)
filtered_attachments_object = filter_attachments attachments
return if filtered_attachments_object[:keys].blank?
matching_request = MatchingRequest.create project: project, attachments: filtered_attachments_object[:signed_ids]
payload = { request_id: matching_request.id, bucket: aws_bucket_name, files: filtered_attachments_object[:keys]}
response = BrayniacAI::QrMatching.create! payload
matches = response.matches || []
key_signed_id_hash = Hash[filtered_attachments_object[:keys].zip(filtered_attachments_object[:signed_ids])]
handle_matches matches, project, key_signed_id_hash
matching_request.destroy
end
private
def handle_matches(matches, project, key_signed_id_hash)
matches.each do |match|
contract_key = Array.wrap(match.contracts).first
headshot_key = Array.wrap(match.headshots).first
identifier = match.identifier
contract = key_signed_id_hash[contract_key]
headshot = key_signed_id_hash[headshot_key]
next if contract.nil? && headshot.nil?
identified_release = identifier.blank? ? nil : AppearanceRelease.find_by(identifier: identifier)
if identified_release.nil?
create_release project, contract, headshot, identifier
else
update_release identified_release, contract, headshot
end
end
end
def create_release(project, contract, headshot, identifier)
random_contract_no = AppearanceRelease.random_contract_number.to_s
is_incomplete = contract.nil? || headshot.nil?
params = {
project: project,
person_first_name: appearance_first_name(is_incomplete),
person_last_name: random_contract_no
}
params[:person_photo] = headshot unless headshot.nil?
params[:contract] = contract unless contract.nil?
params[:identifier] = identifier unless blank?
return if AppearanceRelease.create(params)
logger.error "Failed to create AppearanceRelease with params : \r\n#{params}"
end
def update_release(release, contract, headshot)
release.contract = contract unless contract.nil?
release.person_photo = headshot unless headshot.nil?
release.save
end
def appearance_first_name(incomplete)
if incomplete
I18n.t('appearance_releases.shared.incomplete_match')
else
I18n.t('appearance_releases.shared.matched_import')
end
end
def aws_bucket_name
ENV.fetch 'AWS_BUCKET'
end
def filter_attachments(attachments)
filtered_attachments_keys = []
filtered_attachments_signed_ids = []
attachments.each do |attachment|
blob = ActiveStorage::Blob.find_signed attachment
next if blob.nil?
extension = blob.filename.extension
next unless blob.image? || extension == 'pdf'
filtered_attachments_keys << blob.key
filtered_attachments_signed_ids << attachment
end
{
keys: filtered_attachments_keys,
signed_ids: filtered_attachments_signed_ids
}
end
end

View File

@@ -56,6 +56,7 @@ class Account < ApplicationRecord
Broadcast.where(project: projects),
ZoomMeeting.where(project: projects),
MedicalRelease.where(project: projects),
MatchingRequest.where(project: projects),
self
])).sum(:byte_size).to_f
end

View File

@@ -16,6 +16,18 @@ class AppearanceRelease < ApplicationRecord
has_one_attached :person_photo
composed_of :guardian_address,
class_name: 'Address',
mapping: [
%w[guardian_address_street1 street1],
%w[guardian_address_street2 street2],
%w[guardian_address_city city],
%w[guardian_address_state state],
%w[guardian_address_zip zip],
%w[guardian_address_country country]
]
# These validations apply to all releases
validates :person_email, email: true, allow_blank: true
validates :person_first_name, :person_last_name, presence: true
@@ -39,6 +51,7 @@ class AppearanceRelease < ApplicationRecord
# These validations apply to releases being signed by a minor
with_options if: :minor? do
validates :guardian_first_name, :guardian_last_name, presence: true
validates :guardian_email, email: true, allow_blank: true
end
validates :person_photo, content_type: face_photo_acceptable_content_types

View File

@@ -8,7 +8,7 @@ class BlankContract
end
def to_pdf
kit = PDFKit.new(as_html)
kit = PDFKit.new(as_html, margin_right: 1, margin_left: 1, margin_top: 10, margin_bottom: 1)
kit.to_file("tmp/#{filename}")
end

View File

@@ -0,0 +1,9 @@
# frozen_string_literal: true
module Attachable
extend ActiveSupport::Concern
included do
has_many_attached :attachments
end
end

View File

@@ -23,7 +23,7 @@ class HeadshotCollection
collection_uid: collection_uid.to_s,
bucket_name: aws_bucket_name,
ids_to_images: map_ids_to_images,
}.reject { |_, v| v.blank? }
}.reject { |k, v| v.blank? && k != :ids_to_images }
end
private

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
class MatchingRequest < ApplicationRecord
include Attachable
belongs_to :project
end

View File

@@ -24,7 +24,7 @@ class QrCode
end
end
def to_base64_png(width = 100, height = 100)
def to_base64_png(width = 200, height = 200)
_qr_code.as_png.resize(width, height).to_data_url
end

View File

@@ -23,7 +23,7 @@
<%= form.phone_field :guardian_phone, wrapper_class: "col-sm-6" %>
</div>
<div class="form-row">
<%= form.text_field :guardian_address, wrapper_class: "col-sm-6" %>
<%= form.text_field :guardian_address_street1, wrapper_class: "col-sm-6" %>
</div>
</div>
<% end %>

View File

@@ -2,6 +2,10 @@
<div class="page">
<% has_logo = local_assigns[:logo] %>
<table class="heading-table">
<tr>
<td>&nbsp;</td>
<td class="do-not-copy-warning"><strong><%= t '.do_not_copy_warning' %></strong></td>
</tr>
<tr>
<td>
<% if has_logo %>
@@ -11,17 +15,9 @@
<% end %>
</td>
<td>
<img src="<%= qr_codes[copy_index] %>" />
<img class="qr-code" src="<%= qr_codes[copy_index] %>" />
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td class="serial-number"><%= serial_numbers[copy_index] %></td>
</tr>
<tr>
<td>&nbsp;</td>
<td><strong><%= t '.do_not_copy_warning' %></strong></td>
</tr>
</table>
<hr>
<% if contract_template.body.present? %>

View File

@@ -3,12 +3,12 @@
<meta name="project-id" content="<%= @project.id %>">
<% end %>
<% if @broadcast %>
<meta name="broadcast-token" content="<%= @broadcast.token %>">
<meta name="broadcast-token" current="true" content="<%= @broadcast.token %>">
<% end %>
<% # Subscribe to Action Cable for every broadcast including those in multi-view %>
<% @multi_view_broadcasts.each do |multi_view_broadcast| %>
<% if multi_view_broadcast.token != @broadcast.token %>
<meta name="broadcast-token" content="<%= multi_view_broadcast.token %>">
<meta name="broadcast-token" current="false" content="<%= multi_view_broadcast.token %>">
<% end %>
<% end %>
<% end %>

View File

@@ -2,21 +2,20 @@
<%= field_set_tag content_tag(:span, t(".release_info.heading"), class: "h6 text-muted text-uppercase") do %>
<div class="form-row">
<%= form.text_field :name, wrapper_class: "col-sm-6" %>
<%= form.select :release_type, options_for_release_type_select(project, @release_type), { wrapper_class: "col-sm-6" }, data: { toggle: "collapse-select", target: "#guardian_clause", show_values: %w(appearance talent) }, class: "form-control custom-select" %>
<%= form.select :release_type, options_for_release_type_select(project, @release_type), { wrapper_class: "col-sm-6" }, data: { toggle: "collapse-select", target_show_values_mapping: { "#guardian_clause": %w(appearance talent), "#fee_field": %w(appearance talent location material acquired_media), "#exploitable_rights_fields": %w(appearance talent location material acquired_media), "#custom_fields": %w(medical) } }, class: "form-control custom-select" %>
</div>
<div class="form-row">
<div class="form-row" id="fee_field">
<%= form.number_field :fee, min:"0", max:"99999999", step: "0.01", prepend: "$", help: "Leave at $0.00 for no-fee", wrapper_class: "col-sm-6" %>
</div>
<% end %>
<hr>
<%= field_set_tag content_tag(:span, t(".exploitable_rights.heading"), class: "h6 text-muted text-uppercase")do %>
<%= field_set_tag content_tag(:span, t(".exploitable_rights.heading"), class: "h6 text-muted text-uppercase"), id: "exploitable_rights_fields" do %>
<%= render "shared/exploitable_rights_fields", form: form %>
<hr>
<% end %>
<hr>
<%= field_set_tag content_tag(:span, t(".legal.heading"), class: "h6 text-muted text-uppercase") do %>
<%= form.form_group do %>
<%= form.rich_text_area :body %>
@@ -28,6 +27,12 @@
</div>
<% end %>
<%= field_set_tag content_tag(:span, t(".custom_fields.heading"), class: "h6 text-muted text-uppercase"), id: "custom_fields", style: "display: none;" do %>
<p class="alert alert-info"><%= fa_icon("info-circle", text: t(".custom_fields.instructions")) %></p>
<%= render "shared/custom_fields", form: form %>
<hr>
<% end %>
<div class="row align-items-center text-center mt-4">
<%= link_to t("shared.cancel"), [project, :contract_templates], class: "col-3 text-reset" %>
<div class="col-3">

View File

@@ -39,6 +39,15 @@
<% end %>
</dl>
<% if releasable.model_name == "MedicalRelease" %>
<% (1..10).each do |n| %>
<% if contract_template.public_send("question_#{n}_text").present? %>
<p><strong><%= contract_template.public_send("question_#{n}_text") %></strong></p>
<p><%= releasable.public_send("question_#{n}_answer") %></p>
<% end %>
<% end %>
<% end %>
<% if releasable.minor? %>
<br/>
<p class="text-left"><strong>Guardian Information</strong></p>
@@ -56,6 +65,7 @@
<%= description_list_pair_for releasable, :guardian_name, append: ":" %>
<%= description_list_pair_for releasable, :guardian_address, append: ":" %>
<%= description_list_pair_for releasable, :guardian_phone, append: ":" %>
<%= description_list_pair_for releasable, :guardian_email, append: ":" %>
<%= description_list_pair_for releasable, :signed_on, append: ":" %>
</dl>

View File

@@ -1,6 +1,6 @@
<%= bootstrap_form_with model: project, local: true do |form| %>
<%= form.text_field :name %>
<%= form.select :predefined_client_name, options_for_select(options_for_predefined_client_name_select, selected_project_client_value(project)), {}, data: { toggle: "collapse-select", target: "#other_client", show_values: [:other] }, class: "form-control custom-select" %>
<%= form.select :predefined_client_name, options_for_select(options_for_predefined_client_name_select, selected_project_client_value(project)), {}, data: { toggle: "collapse-select", target_show_values_mapping: { "#other_client": [:other] } }, class: "form-control custom-select" %>
<div id="other_client" style="<%='display: none' if selected_project_client_value(project) != 'other'%>">
<%= form.text_field :client_name, placeholder: true %>
<%= form.form_group do %>

View File

@@ -77,8 +77,9 @@
<%= form.phone_field :guardian_phone, wrapper_class: "col-sm-6" %>
</div>
<div class="form-row">
<%= form.text_field :guardian_address, wrapper_class: "col-sm-6" %>
<%= form.text_field :guardian_email, wrapper_class: "col-sm-6" %>
</div>
<%= render "shared/address_fields", form: form, subject: "guardian" %>
<% end %>
<hr>

View File

@@ -13,6 +13,19 @@
<% end %>
<hr>
<% if (1..10).map {|n| @contract_template.public_send("question_#{n}_text").presence }.compact.any? %>
<%= card_field_set_tag t(".questionnaire.heading") do %>
<% (1..10).each do |n| %>
<% if @contract_template.public_send("question_#{n}_text").present? %>
<div class="form-row">
<%= form.text_area "question_#{n}_answer", wrapper_class: "col-sm-12", label: @contract_template.public_send("question_#{n}_text") %>
</div>
<% end %>
<% end %>
<% end %>
<hr>
<% end %>
<%= card_field_set_tag t(".personal_info.heading") do %>
<div class="alert alert-warning font-weight-bold"><%= t ".personal_info.instructions" %></div>
@@ -36,7 +49,7 @@
<% end %>
<div class="mt-5">
<%= form.button t("shared.submit_release_long"), class: "btn btn-block btn-lg btn-success", data: { disable_with: t("shared.disable_with") } %>
<%= form.button t("shared.submit_release_short"), class: "btn btn-block btn-lg btn-success", data: { disable_with: t("shared.disable_with") } %>
</div>
<% end %>
</div>

View File

@@ -0,0 +1,5 @@
<% (1..10).each do |n| %>
<div class="form-row">
<%= form.text_area "question_#{n}_text", wrapper_class: "col-sm-12" %>
</div>
<% end%>

View File

@@ -112,6 +112,7 @@ en:
no_photos: Needs Photo
create:
failed_import: Failed to create appearance release for files listed below
matching_started: Matching started
no_attachments: Failed to import - no attachments
edit:
heading: Edit Appearance Release
@@ -141,6 +142,8 @@ en:
shared:
imported_appearance_release_contract_name: Imported Contract
imported_appearance_release_headshot_name: Imported Headshot
incomplete_match: Incomplete Match
matched_import: Complete Match
type_filter_actions:
all_releases: All Releases
complete_releases: Complete Releases
@@ -212,12 +215,15 @@ en:
archived_failure: Failed to archive the release template
archived_notice: The release template has been archived
form:
custom_fields:
heading: Medical Questionnaire
instructions: Please list the questions you wish the signer to answer. Any unused question fields will be hidden.
exploitable_rights:
heading: 2 of 3 Exploitable Rights
heading: Exploitable Rights
legal:
heading: 3 of 3 Legal
heading: Legal
release_info:
heading: 1 of 3 Release Info
heading: Release Info
index:
actions:
import: Import Release Template
@@ -324,9 +330,18 @@ en:
appearance_release:
minor: Is the person a minor?
person_address: Address
person_date_of_birth: Date of birth
person_email: Email address
person_first_name: First name
person_last_name: Last name
person_name: Name
person_phone: Phone number
guardian_address_city: Guardian city
guardian_address_country: Guardian country
guardian_address_state: Guardian state
guardian_address_street1: Guardian address
guardian_address_street2: Guardian address (Line 2)
guardian_address_zip: Guardian zip code
location_release:
address_city: City
address_country: Country
@@ -789,17 +804,17 @@ en:
instructions: >
Lastly, it's time for guardian to take a selfie photo! Please remove your hat and sunglasses (regular eyewear is ok), make sure that you are the only person in the photo, look straight into the camera, and say Cheese!
instructions_html: >
Congrats in appearing on <em>%{name}</em>. Below is the appearance release form. After scrolling down and reading the appearance release form, please enter your personal information, take a selfie photo, and press the "Submit Release" button.
Congrats on appearing in <em>%{name}</em>. After scrolling down and reading the appearance release form, please enter your personal information, take a selfie photo and press the "Submit Release" button. If the person appearing on camera is a minor, you will enter their personal information first, select the button noting this person is a minor, and then enter your own personal info under "Guardian Information" at the bottom.
legal:
heading: Legal
personal_info:
heading: Personal Information
instructions: Now, enter your personal information.
instructions: Enter the personal information for the person appearing on camera.
photo:
camera_instructions_html: Click <em>Take Photo</em> to Turn ON Camera
heading: Take a Photo
heading: Photo of Person Appearing on Camera
instructions: >
Lastly, it's time for you to take a selfie photo! Please remove your hat and sunglasses (regular eyewear is ok), make sure that you are the only person in the photo, look straight into the camera, and say Cheese!
'Before you take your selfie photo, remove your hat and sunglasses (regular eyewear is okay). Make sure you are the only person in the frame, look straight at the camera and snap the photo. NOTE: If you are a Guardian, you must take the photo of the minor. Minor photo is required only for record keeping purposes to maintain proof of parental consent and to identify minor within the Program.'
no_photo: No photo yet
take_photo: Take Photo
warning: If your photo appears sideways, it will be autocorrected when you submit your release.
@@ -851,6 +866,8 @@ en:
instructions: Now, enter your personal information.
photo:
heading: Photos
questionnaire:
heading: Questionnaire
signature:
heading: Signature
talent_releases:
@@ -940,6 +957,7 @@ en:
search: Search
submit_release: Submit Release
submit_release_long: I have read and agree to the above
submit_release_short: Submit
suite: Suite
tag_multiple_releases: Add Tag
tag_multiple_releases_form:

View File

@@ -25,6 +25,7 @@ es:
appearance_releases:
create:
failed_import: Failed to create appearance release for files listed below (ES)
matching_started: Matching started (ES)
no_attachments: Failed to import - no attachments (ES)
form:
photos:
@@ -37,6 +38,8 @@ es:
shared:
imported_appearance_release_contract_name: Contrato Importado
imported_appearance_release_headshot_name: Retrato Importado
incomplete_match: Incomplete Match (ES)
matched_import: Complete Match (ES)
type_filter_actions:
all_releases: All Releases (ES)
complete_releases: Complete Releases (ES)
@@ -52,6 +55,15 @@ es:
blank_contracts:
create:
number_of_copies_invalid_notice: Please enter valid number greater than 0 (ES)
form:
custom_fields:
heading: Medical Questionnaire (ES)
exploitable_rights:
heading: Exploitable Rights (ES)
legal:
heading: Legal (ES)
release_info:
heading: Release Info (ES)
contracts:
photos:
guardian_photo_heading: Guardian photo (ES)
@@ -103,7 +115,6 @@ es:
helpers:
label:
appearance_release:
guardian_address: Dirección del tutor legal
guardian_name: Nómbre del tutor legal
guardian_phone: Número de teléfono del tutor legal
minor: El firmante es un menor
@@ -111,6 +122,12 @@ es:
person_email: Dirección de correo electrónico
person_name: Nómbre
person_phone: Número de teléfono
guardian_address_city: Guardian city (ES)
guardian_address_country: Guardian country (ES)
guardian_address_state: Guardian state (ES)
guardian_address_street1: Dirección del tutor legal
guardian_address_street2: Dirección del tutor legal (Línea 2)
guardian_address_zip: Guardian zip code (ES)
project:
client_name: Nómbre del cliente del proyecto
description: Descripción del proyecto

View File

@@ -163,6 +163,7 @@ Rails.application.routes.draw do
resources :appearance_releases, only: [:show] do
resources :notes, controller: "notes", only: [:create, :index]
end
resources :direct_uploads, only: [:create]
end
end

View File

@@ -0,0 +1,9 @@
class CreateMatchingRequests < ActiveRecord::Migration[6.0]
def change
create_table :matching_requests do |t|
t.belongs_to :project, foreign_key: true
t.timestamps
end
end
end

View File

@@ -0,0 +1,5 @@
class AddIdentifierToAppearanceReleases < ActiveRecord::Migration[6.0]
def change
add_column :appearance_releases, :identifier, :string, default: nil
end
end

View File

@@ -0,0 +1,14 @@
class AddQuestionFieldsToContractTemplates < ActiveRecord::Migration[6.0]
def change
add_column :contract_templates, :question_1_text, :text
add_column :contract_templates, :question_2_text, :text
add_column :contract_templates, :question_3_text, :text
add_column :contract_templates, :question_4_text, :text
add_column :contract_templates, :question_5_text, :text
add_column :contract_templates, :question_6_text, :text
add_column :contract_templates, :question_7_text, :text
add_column :contract_templates, :question_8_text, :text
add_column :contract_templates, :question_9_text, :text
add_column :contract_templates, :question_10_text, :text
end
end

View File

@@ -0,0 +1,14 @@
class AddAnswerFieldsToMedicalReleases < ActiveRecord::Migration[6.0]
def change
add_column :medical_releases, :question_1_answer, :text
add_column :medical_releases, :question_2_answer, :text
add_column :medical_releases, :question_3_answer, :text
add_column :medical_releases, :question_4_answer, :text
add_column :medical_releases, :question_5_answer, :text
add_column :medical_releases, :question_6_answer, :text
add_column :medical_releases, :question_7_answer, :text
add_column :medical_releases, :question_8_answer, :text
add_column :medical_releases, :question_9_answer, :text
add_column :medical_releases, :question_10_answer, :text
end
end

View File

@@ -0,0 +1,5 @@
class AddGuardianEmailToAppearanceReleases < ActiveRecord::Migration[6.0]
def change
add_column :appearance_releases, :guardian_email, :string
end
end

View File

@@ -0,0 +1,5 @@
class RemoveBroadcastIdFromZoomMeetings < ActiveRecord::Migration[6.0]
def change
remove_column :zoom_meetings, :broadcast_id
end
end

View File

@@ -0,0 +1,10 @@
class DestructureGuardianAddressColumnInAppearanceReleases < ActiveRecord::Migration[6.0]
def change
rename_column :appearance_releases, :guardian_address, :guardian_address_street1
add_column :appearance_releases, :guardian_address_street2, :string
add_column :appearance_releases, :guardian_address_city, :string
add_column :appearance_releases, :guardian_address_state, :string
add_column :appearance_releases, :guardian_address_zip, :string
add_column :appearance_releases, :guardian_address_country, :string
end
end

View File

@@ -9,20 +9,6 @@ SET xmloption = content;
SET client_min_messages = warning;
SET row_security = off;
--
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -
--
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
--
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: -
--
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
--
-- Name: fuzzystrmatch; Type: EXTENSION; Schema: -; Owner: -
--
@@ -310,7 +296,7 @@ CREATE TABLE public.appearance_releases (
created_at timestamp without time zone NOT NULL,
updated_at timestamp without time zone NOT NULL,
minor boolean DEFAULT false,
guardian_address character varying,
guardian_address_street1 character varying,
guardian_name_old character varying,
guardian_phone character varying,
person_email character varying,
@@ -330,7 +316,14 @@ CREATE TABLE public.appearance_releases (
person_first_name character varying,
person_last_name character varying,
guardian_first_name character varying,
guardian_last_name character varying
guardian_last_name character varying,
identifier character varying,
guardian_email character varying,
guardian_address_street2 character varying,
guardian_address_city character varying,
guardian_address_state character varying,
guardian_address_zip character varying,
guardian_address_country character varying
);
@@ -606,7 +599,17 @@ CREATE TABLE public.contract_templates (
term_text character varying,
restriction_id bigint,
restriction_text character varying,
archived_at timestamp without time zone
archived_at timestamp without time zone,
question_1_text text,
question_2_text text,
question_3_text text,
question_4_text text,
question_5_text text,
question_6_text text,
question_7_text text,
question_8_text text,
question_9_text text,
question_10_text text
);
@@ -875,6 +878,37 @@ CREATE SEQUENCE public.location_releases_id_seq
ALTER SEQUENCE public.location_releases_id_seq OWNED BY public.location_releases.id;
--
-- Name: matching_requests; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public.matching_requests (
id bigint NOT NULL,
project_id bigint,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL
);
--
-- Name: matching_requests_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public.matching_requests_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
--
-- Name: matching_requests_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--
ALTER SEQUENCE public.matching_requests_id_seq OWNED BY public.matching_requests.id;
--
-- Name: material_releases; Type: TABLE; Schema: public; Owner: -
--
@@ -955,7 +989,17 @@ CREATE TABLE public.medical_releases (
notes text,
signed_at timestamp without time zone,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL
updated_at timestamp(6) without time zone NOT NULL,
question_1_answer text,
question_2_answer text,
question_3_answer text,
question_4_answer text,
question_5_answer text,
question_6_answer text,
question_7_answer text,
question_8_answer text,
question_9_answer text,
question_10_answer text
);
@@ -1612,7 +1656,6 @@ CREATE TABLE public.zoom_meetings (
api_meeting_id character varying,
created_at timestamp(6) without time zone NOT NULL,
updated_at timestamp(6) without time zone NOT NULL,
broadcast_id bigint,
zoom_user_id bigint,
project_id bigint,
status integer DEFAULT 0
@@ -1811,6 +1854,13 @@ ALTER TABLE ONLY public.imports ALTER COLUMN id SET DEFAULT nextval('public.impo
ALTER TABLE ONLY public.location_releases ALTER COLUMN id SET DEFAULT nextval('public.location_releases_id_seq'::regclass);
--
-- Name: matching_requests id; Type: DEFAULT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.matching_requests ALTER COLUMN id SET DEFAULT nextval('public.matching_requests_id_seq'::regclass);
--
-- Name: material_releases id; Type: DEFAULT; Schema: public; Owner: -
--
@@ -2119,6 +2169,14 @@ ALTER TABLE ONLY public.location_releases
ADD CONSTRAINT location_releases_pkey PRIMARY KEY (id);
--
-- Name: matching_requests matching_requests_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.matching_requests
ADD CONSTRAINT matching_requests_pkey PRIMARY KEY (id);
--
-- Name: material_releases material_releases_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@@ -2588,6 +2646,13 @@ CREATE INDEX index_location_releases_on_term_id ON public.location_releases USIN
CREATE INDEX index_location_releases_on_territory_id ON public.location_releases USING btree (territory_id);
--
-- Name: index_matching_requests_on_project_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_matching_requests_on_project_id ON public.matching_requests USING btree (project_id);
--
-- Name: index_material_releases_on_applicable_medium_id; Type: INDEX; Schema: public; Owner: -
--
@@ -2917,13 +2982,6 @@ CREATE INDEX index_videos_on_audio_analysis_uid ON public.videos USING btree (au
CREATE INDEX index_videos_on_project_id ON public.videos USING btree (project_id);
--
-- Name: index_zoom_meetings_on_broadcast_id; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX index_zoom_meetings_on_broadcast_id ON public.zoom_meetings USING btree (broadcast_id);
--
-- Name: index_zoom_meetings_on_project_id; Type: INDEX; Schema: public; Owner: -
--
@@ -3232,6 +3290,14 @@ ALTER TABLE ONLY public.material_releases
ADD CONSTRAINT fk_rails_6b945b36b9 FOREIGN KEY (contract_template_id) REFERENCES public.contract_templates(id);
--
-- Name: matching_requests fk_rails_71d16e64c8; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.matching_requests
ADD CONSTRAINT fk_rails_71d16e64c8 FOREIGN KEY (project_id) REFERENCES public.projects(id);
--
-- Name: appearance_releases fk_rails_7a58302526; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@@ -3264,14 +3330,6 @@ ALTER TABLE ONLY public.music_releases
ADD CONSTRAINT fk_rails_890d967673 FOREIGN KEY (territory_id) REFERENCES public.territories(id);
--
-- Name: zoom_meetings fk_rails_8d814ea729; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public.zoom_meetings
ADD CONSTRAINT fk_rails_8d814ea729 FOREIGN KEY (broadcast_id) REFERENCES public.broadcasts(id);
--
-- Name: medical_releases fk_rails_98aa92daa9; Type: FK CONSTRAINT; Schema: public; Owner: -
--
@@ -3591,10 +3649,17 @@ INSERT INTO "schema_migrations" (version) VALUES
('20200424161117'),
('20200427073429'),
('20200428091105'),
('20200430151828'),
('20200430190412'),
('20200507110804'),
('20200512161738'),
('20200526113516'),
('20200603090419'),
('20200606044747');
('20200606044747'),
('20200610085411'),
('20200610140459'),
('20200612121539'),
('20200615131722'),
('20200616124214');

View File

@@ -10,5 +10,6 @@ require_relative "./brayniac_ai/edl_parse"
require_relative "./brayniac_ai/edl_parse_result"
require_relative "./brayniac_ai/facial_recognition"
require_relative "./brayniac_ai/facial_recognition_result"
require_relative "./brayniac_ai/qr_matching"
require_relative "./brayniac_ai/tag"
require_relative "./brayniac_ai/validation"

View File

@@ -0,0 +1,4 @@
module BrayniacAI
class QrMatching < Base
end
end

View File

@@ -0,0 +1,36 @@
require 'rails_helper'
RSpec.describe Api::DirectUploadsController, type: :controller do
let(:current_user) { create(:user) }
let(:project) { create(:project, account: current_user.primary_account) }
before do
sign_in_to_api(current_user)
end
describe '#create' do
it 'returns data for a direct upload' do
post :create, params: { direct_upload: direct_upload_params }
expect(response).to be_successful
expect(response_body_data_attributes).to include('id', 'key', 'signed_id', 'url', 'headers')
end
end
private
def direct_upload_params
file = file_fixture("video_file.mp4")
checksum = Digest::MD5.base64digest(StringIO.new(file.read).to_s)
{ filename: file.basename.to_s, content_type: "video/mp4", byte_size: file.size, checksum: checksum }
end
def response_body_data
JSON.parse(response.body).dig('data')
end
def response_body_data_attributes
response_body_data.dig('attributes')
end
end

View File

@@ -263,7 +263,12 @@ RSpec.describe AppearanceReleasesController, tye: :controller do
end
def minor_appearance_release_params
attributes_for(:appearance_release, :non_native, :minor_with_guardian_photo).except(:contract).merge(contract_param, exploitable_rights_params)
attributes_for(:appearance_release, :non_native, :minor_with_guardian_photo)
.except(:contract)
.except(:guardian_address_street2).except(:guardian_address_city)
.except(:guardian_address_state).except(:guardian_address_zip)
.except(:guardian_address_country)
.merge(contract_param, exploitable_rights_params)
end
def exploitable_rights_params

View File

@@ -120,7 +120,19 @@ describe Public::AppearanceReleasesController do
def minor_appearance_release_params(with_guardian_photo = true)
minor_type = with_guardian_photo ? :minor_with_guardian_photo : :minor
attributes_for(:appearance_release, minor_type).merge(signature_param)
attributes_for(:appearance_release, minor_type)
.merge(signature_param, guardian_address_params)
end
def guardian_address_params
{
guardian_address_street1: "St1",
guardian_address_street2: "St2",
guardian_address_city: "City",
guardian_address_state: "State",
guardian_address_zip: "ZIP",
guardian_address_country: "Country"
}
end
def signature_param

View File

@@ -31,16 +31,28 @@ FactoryBot.define do
minor true
guardian_first_name "Jamie"
guardian_last_name "Doe"
guardian_address "100 Test Lane, New York, 10001"
guardian_address_street1 "St1"
guardian_address_street2 "St2"
guardian_address_city "City"
guardian_address_state "State"
guardian_address_zip "ZIP"
guardian_address_country "Country"
guardian_phone "123-555-1234"
guardian_email "guardian@galaxy.all"
end
trait :minor_with_guardian_photo do
minor true
guardian_first_name "Jamie"
guardian_last_name "Doe"
guardian_address "100 Test Lane, New York, 10001"
guardian_phone "123-555-1234"
guardian_email "guardian@galaxy.all"
guardian_address_street1 "St1"
guardian_address_street2 "St2"
guardian_address_city "City"
guardian_address_state "State"
guardian_address_zip "ZIP"
guardian_address_country "Country"
guardian_photo do
path = Rails.root.join("spec", "fixtures", "files", "pratt.jpg")
Rack::Test::UploadedFile.new(path, "image/jpeg")
@@ -65,5 +77,24 @@ FactoryBot.define do
appearance_release.contract_template = build(:appearance_release_contract_template)
end
end
factory :appearance_release_import do
person_photo nil
trait :with_headshot do
person_photo do
path = Rails.root.join("spec", "fixtures", "files", "person_photo.png")
Rack::Test::UploadedFile.new(path, "image/png")
end
end
trait :with_contract do
contract do
path = Rails.root.join("spec", "fixtures", "files", "AppearanceRelease.pdf")
Rack::Test::UploadedFile.new(path, "application/pdf")
end
end
end
end
end

View File

@@ -25,7 +25,7 @@ feature 'User managing appearance releases' do
fill_in person_date_of_birth, with: '01/01/1999'
attach_file person_photo_field, file_fixture('person_photo.png'), visible: :all
draw_signature file_fixture('signature.png'), 'appearance_release_signature_base64'
click_button 'I have read and agree to the above'
click_button submit_release_button
expect(page).to have_content(successful_submission_message)
end
@@ -45,6 +45,7 @@ feature 'User managing appearance releases' do
page.check person_is_minor_checkbox
expect(page).to have_content('GUARDIAN INFORMATION')
expect(page).to have_content('GUARDIAN PHOTO')
expect(page).to have_content 'Guardian Email'
fill_in guardian_first_name_field, with: 'Guardian'
fill_in guardian_last_name_field, with: 'Name'
@@ -58,7 +59,14 @@ feature 'User managing appearance releases' do
attach_file person_photo_field, file_fixture('person_photo.png'), visible: :all
attach_file guardian_photo_field, file_fixture('hemsworth.jpeg'), visible: :all
draw_signature file_fixture('signature.png'), 'appearance_release_signature_base64'
click_button 'I have read and agree to the above'
fill_in guardian_email_field, with: 'invalid@email'
click_button submit_release_button
expect(page).to have_content('Guardian email is not an email')
fill_in guardian_email_field, with: 'valid@email.com'
draw_signature file_fixture('signature.png'), 'appearance_release_signature_base64'
click_button submit_release_button
expect(page).to have_content(successful_submission_message)
end
@@ -130,48 +138,25 @@ feature 'User managing appearance releases' do
end
scenario 'progress bar shows when user imports a release', js: true do
skip "TODO"
visit project_appearance_releases_path(project)
expect(page).not_to have_css('#upload-progress-container')
large_pdf_file = build_large_pdf_file
attach_file import_appearance_release_field, Rails.root.join(large_pdf_file.path), visible: false
expect(page).to have_css('#upload-progress-container')
expect(page).to have_content submit_create_button, wait: 30
click_button submit_create_button
expect(page).to have_content matching_started
end
scenario 'MatchAppearanceReleasesJob is started when import is finished', js: true do
visit project_appearance_releases_path(project)
attach_file import_appearance_release_field, Rails.root.join(file_fixture('person_photo.png')), visible: false
expect(page).to have_content importing_label
allow(MatchAppearanceReleasesJob).to receive(:perform_later).with(project, anything)
click_button submit_create_button
expect(page).to have_css('.progress')
end
scenario 'importing a releases works when image is selected', js: true do
expect(page).to have_content matching_started
visit project_appearance_releases_path(project)
expect(page).to have_content submit_create_button
expect(page).to have_content no_appearance_releases
attach_file import_appearance_release_field, Rails.root.join(file_fixture('person_photo.png')), visible: false
expect(page).to have_content importing_label
click_button submit_create_button
expect(page).not_to have_content no_appearance_releases
expect(page).to have_content /Imported Headshot\s+\d{7}/
end
scenario 'importing a releases works when pdf is selected', js: true do
visit project_appearance_releases_path(project)
expect(page).to have_content submit_create_button
expect(page).to have_content no_appearance_releases
attach_file import_appearance_release_field, Rails.root.join(file_fixture('contract.pdf')), visible: false
expect(page).to have_content importing_label
click_button submit_create_button
expect(page).not_to have_content no_appearance_releases
expect(page).to have_content /Imported Contract\s+\d{7}/
end
scenario 'importing a releases fails when file other than image or pdf is selected', js: true do
visit project_appearance_releases_path(project)
expect(page).to have_content submit_create_button
expect(page).to have_content no_appearance_releases
attach_file import_appearance_release_field, Rails.root.join(file_fixture('audio.mp3')), visible: false
expect(page).to have_content importing_label
click_button submit_create_button
expect(page).to have_content failed_to_import_notice
expect(page).to have_content no_appearance_releases
end
@@ -249,6 +234,7 @@ feature 'User managing appearance releases' do
expect(pdf_body).to have_content('TAGS')
expect(pdf_body).to have_content('Woman')
expect(pdf_body).to have_content('Brunette')
expect(pdf_body).not_to have_content('Guardian Email')
end
scenario 'viewing contract PDF for a minor without guardian photo' do
@@ -262,8 +248,10 @@ feature 'User managing appearance releases' do
expect(pdf_filename).to include(appearance_release.filename_suffix.parameterize)
expect(pdf_body).to have_content(appearance_release.name)
expect(pdf_body).to have_content(appearance_release.guardian_name)
expect(pdf_body).to have_content(appearance_release.guardian_email)
expect(pdf_body).to have_content photos_heading.upcase
expect(pdf_body).to have_content(appearance_release.photo.filename.to_s)
expect(pdf_body).to have_content('Guardian Email')
end
scenario 'viewing contract PDF for a minor with guardian photo' do
@@ -277,9 +265,11 @@ feature 'User managing appearance releases' do
expect(pdf_filename).to include(appearance_release.filename_suffix.parameterize)
expect(pdf_body).to have_content(appearance_release.name)
expect(pdf_body).to have_content(appearance_release.guardian_name)
expect(pdf_body).to have_content(appearance_release.guardian_email)
expect(pdf_body).to have_content photos_heading(2).upcase
expect(pdf_body).to have_content(appearance_release.photo.filename.to_s)
expect(pdf_body).to have_content(appearance_release.guardian_photo.filename.to_s)
expect(pdf_body).to have_content('Guardian Email')
end
scenario 'deleting a release', js: true do
@@ -422,6 +412,10 @@ feature 'User managing appearance releases' do
tempfile
end
def matching_started
t 'appearance_releases.create.matching_started'
end
def filter_type_all
t 'appearance_releases.type_filter_actions.all_releases'
end
@@ -470,6 +464,10 @@ feature 'User managing appearance releases' do
'Guardian phone'
end
def guardian_email_field
'Guardian email'
end
def guardian_photo_field
'appearance_release[guardian_photo]'
end
@@ -479,11 +477,11 @@ feature 'User managing appearance releases' do
end
def person_first_name_field
'Person first name'
t('helpers.label.appearance_release.person_first_name')
end
def person_last_name_field
'Person last name'
t('helpers.label.appearance_release.person_last_name')
end
def person_address_field
@@ -518,6 +516,10 @@ feature 'User managing appearance releases' do
'Import Release'
end
def submit_release_button
'I have read and agree to the above'
end
def submit_update_button
'Save Changes'
end

View File

@@ -0,0 +1,216 @@
require "rails_helper"
describe MatchAppearanceReleasesJob do
let(:project) { create(:project) }
let(:dummy_appearance_release) { create(:appearance_release_import, :with_headshot, :with_contract) }
let(:dummy_matching_request) { instance_double(MatchingRequest, id: 999) }
before :all do
ENV["AWS_BUCKET"] = ""
end
describe ".perform_now" do
it "returns if no attachment is sent" do
expect(MatchingRequest).not_to receive(:create)
attachments = []
MatchAppearanceReleasesJob.perform_now project, attachments
end
it "returns if no valid attachment is sent" do
expect(MatchingRequest).not_to receive(:create)
dummy_video = create(:video)
attachments = [dummy_video.file.blob.signed_id]
MatchAppearanceReleasesJob.perform_now project, attachments
end
it "does not create new appearance release if BrayniacAI returns empty matches array" do
signed_ids = [dummy_appearance_release.person_photo.blob.signed_id]
keys = [dummy_appearance_release.person_photo.key]
payload = {
project: project,
attachments: signed_ids
}
qr_matching_payload = {
bucket: '',
files: keys,
request_id: dummy_matching_request.id
}
qr_matching_mock_response = double(
request_id: dummy_matching_request.id,
matches: []
)
expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
expect(dummy_matching_request).to receive(:destroy)
MatchAppearanceReleasesJob.perform_now project, signed_ids
expect(AppearanceRelease.last).to eq dummy_appearance_release
end
it "creates new incomplete appearance release if BrayniacAI returns single headshot match" do
signed_ids = [dummy_appearance_release.person_photo.blob.signed_id]
keys = [dummy_appearance_release.person_photo.key]
payload = {
project: project,
attachments: signed_ids
}
qr_matching_payload = {
bucket: '',
files: keys,
request_id: dummy_matching_request.id
}
mock_match = double(
headshots: keys,
contracts: [],
unknowns: [],
identifier: 'some/identifier/123'
)
matches = [mock_match]
qr_matching_mock_response = double(
request_id: dummy_matching_request.id,
matches: matches
)
expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
expect(dummy_matching_request).to receive(:destroy)
MatchAppearanceReleasesJob.perform_now project, signed_ids
expect(AppearanceRelease.last.identifier).to eq mock_match.identifier
expect(AppearanceRelease.last.person_photo).to be_attached
expect(AppearanceRelease.last.contract).not_to be_attached
end
it "creates new incomplete appearance release if BrayniacAI returns single contract match" do
signed_ids = [dummy_appearance_release.contract.blob.signed_id]
keys = [dummy_appearance_release.contract.key]
payload = {
project: project,
attachments: signed_ids
}
qr_matching_payload = {
bucket: '',
files: keys,
request_id: dummy_matching_request.id
}
mock_match = double(
headshots: [],
contracts: keys,
unknowns: [],
identifier: 'some/identifier/123'
)
matches = [mock_match]
qr_matching_mock_response = double(
request_id: dummy_matching_request.id,
matches: matches
)
expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
expect(dummy_matching_request).to receive(:destroy)
MatchAppearanceReleasesJob.perform_now project, signed_ids
expect(AppearanceRelease.last.identifier).to eq mock_match.identifier
expect(AppearanceRelease.last.person_photo.attached?).to eq false
expect(AppearanceRelease.last.contract.attached?).to eq true
end
it "creates new complete appearance release if BrayniacAI returns match for headshot and contract" do
signed_ids = [
dummy_appearance_release.person_photo.blob.signed_id,
dummy_appearance_release.contract.blob.signed_id
]
keys = [
dummy_appearance_release.person_photo.key,
dummy_appearance_release.contract.key
]
payload = {
project: project,
attachments: signed_ids
}
qr_matching_payload = {
bucket: '',
files: keys,
request_id: dummy_matching_request.id
}
mock_match = double(
headshots: [keys[0]],
contracts: [keys[1]],
unknowns: [],
identifier: 'some/identifier/123'
)
matches = [mock_match]
qr_matching_mock_response = double(
request_id: dummy_matching_request.id,
matches: matches
)
expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
expect(dummy_matching_request).to receive(:destroy)
MatchAppearanceReleasesJob.perform_now project, signed_ids
expect(AppearanceRelease.last.identifier).to eq mock_match.identifier
expect(AppearanceRelease.last.person_photo.attached?).to eq true
expect(AppearanceRelease.last.contract.attached?).to eq true
end
it "creates two new incomplete appearance releases if BrayniacAI returns two matches for headshot and contract" do
signed_ids = [
dummy_appearance_release.person_photo.blob.signed_id,
dummy_appearance_release.contract.blob.signed_id
]
keys = [
dummy_appearance_release.person_photo.key,
dummy_appearance_release.contract.key
]
payload = {
project: project,
attachments: signed_ids
}
qr_matching_payload = {
bucket: '',
files: keys,
request_id: dummy_matching_request.id
}
mock_match1 = double(
headshots: [keys[0]],
contracts: [],
unknowns: [],
identifier: 'some/identifier/123'
)
mock_match2 = double(
headshots: [],
contracts: [keys[1]],
unknowns: [],
identifier: 'some/identifier/789'
)
matches = [mock_match1, mock_match2]
qr_matching_mock_response = double(
request_id: dummy_matching_request.id,
matches: matches
)
expect(MatchingRequest).to receive(:create).with(payload).and_return(dummy_matching_request)
expect(BrayniacAI::QrMatching).to receive(:create!).with(qr_matching_payload).and_return(qr_matching_mock_response)
expect(dummy_matching_request).to receive(:destroy)
MatchAppearanceReleasesJob.perform_now project, signed_ids
releases = AppearanceRelease.last(2)
expect(releases[0].identifier).to eq mock_match1.identifier
expect(releases[0].person_photo.attached?).to eq true
expect(releases[0].contract.attached?).to eq false
expect(releases[1].identifier).to eq mock_match2.identifier
expect(releases[1].person_photo.attached?).to eq false
expect(releases[1].contract.attached?).to eq true
end
end
end

View File

@@ -131,7 +131,8 @@ RSpec.describe Account do
Broadcast,
Account,
ZoomMeeting,
MedicalRelease
MedicalRelease,
MatchingRequest
]
Rails.application.eager_load!
ActiveRecord::Base.descendants.each do |model|

View File

@@ -42,7 +42,6 @@ describe BlankContract do
material_release = create(:material_release_with_contract_template, project: project, person_name: 'Jane Doe')
result = render_contract_html_for(material_release)
expect(result).to include 'serial-number'
expect(result).to include 'DO NOT COPY'
end
end

View File

@@ -54,7 +54,11 @@ describe ContractTemplatePreview do
'person_phone' => '00 111 222 333 4444',
'updated_at' => nil,
'minor' => true,
'guardian_address' => 'Street 3, Street 4, City-2, State-2 112233, Country-2',
'guardian_address_street1' => 'Street 3',
'guardian_address_street2' => 'Street 4',
'guardian_address_city' => 'City-2',
'guardian_address_state' => 'State-2',
'guardian_address_zip' => '112233',
"guardian_first_name" => nil,
"guardian_last_name" => nil,
"guardian_name_old" => nil,

View File

@@ -97,6 +97,18 @@ describe HeadshotCollection do
expect(hash.keys).not_to include(:collection_uid)
end
end
context "when there are no releasables" do
it "includes a blank hash value for the ids_to_images key" do
releases = []
collection = HeadshotCollection.new(nil, releases)
hash = collection.to_hash
expect(hash.keys).to include(:ids_to_images)
expect(hash[:ids_to_images]).to eq(Hash.new)
end
end
end
private