Upstream sync
This commit is contained in:
@@ -66,7 +66,7 @@ class ContractTemplatesController < ApplicationController
|
|||||||
:signature_legal_text, :fee,
|
:signature_legal_text, :fee,
|
||||||
:applicable_medium_id, :applicable_medium_text,
|
:applicable_medium_id, :applicable_medium_text,
|
||||||
:territory_id, :territory_text,
|
:territory_id, :territory_text,
|
||||||
:term_id, :term_text,
|
:term_id, :term_text, :accessibility,
|
||||||
:restriction_id, :restriction_text,
|
:restriction_id, :restriction_text,
|
||||||
:question_1_text, :question_2_text,
|
:question_1_text, :question_2_text,
|
||||||
:question_3_text, :question_4_text,
|
:question_3_text, :question_4_text,
|
||||||
|
|||||||
@@ -28,8 +28,9 @@ class StreamNotificationsController < ApplicationController
|
|||||||
asset_uid = notification.dig(:object, :id)
|
asset_uid = notification.dig(:object, :id)
|
||||||
playback_uid = notification.dig(:data, :playback_ids, 0, :id)
|
playback_uid = notification.dig(:data, :playback_ids, 0, :id)
|
||||||
file_name = notification.dig(:data, :static_renditions, :files, -1, :name)
|
file_name = notification.dig(:data, :static_renditions, :files, -1, :name)
|
||||||
|
duration = notification.dig(:data, :duration)
|
||||||
|
|
||||||
recording = @broadcast.broadcast_recordings.create!(asset_uid: asset_uid, asset_playback_uid: playback_uid, file_name: file_name)
|
recording = @broadcast.broadcast_recordings.create!(asset_uid: asset_uid, asset_playback_uid: playback_uid, file_name: file_name, duration: duration)
|
||||||
recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page])
|
recordings = @broadcast.broadcast_recordings.order_by_recent.paginate(page: params[:page])
|
||||||
|
|
||||||
link = helpers.link_to(recording.broadcast_name.titleize, recording.download_url, target: "_blank")
|
link = helpers.link_to(recording.broadcast_name.titleize, recording.download_url, target: "_blank")
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ class GenerateContractsZipJob < ApplicationJob
|
|||||||
before_perform do |job|
|
before_perform do |job|
|
||||||
@project = job.arguments.first
|
@project = job.arguments.first
|
||||||
@download = job.arguments.second
|
@download = job.arguments.second
|
||||||
release_type = job.arguments.third
|
@release_type = job.arguments.third
|
||||||
@folder_name = "#{@project.name.parameterize}_#{get_release_name(release_type).gsub('_', '-')}"
|
@folder_name = "#{@project.name.parameterize}_#{get_release_name(@release_type).gsub('_', '-')}"
|
||||||
@download.update!(name: @folder_name, status: :pending)
|
@download.update!(name: @folder_name, status: :pending)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -20,6 +20,11 @@ class GenerateContractsZipJob < ApplicationJob
|
|||||||
files.each do |attachment|
|
files.each do |attachment|
|
||||||
zipfile.add(attachment, File.join("#{dir}/", attachment))
|
zipfile.add(attachment, File.join("#{dir}/", attachment))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if @release_type.constantize.include?(CsvExportable)
|
||||||
|
csv_file = generate_csv releases
|
||||||
|
zipfile.get_output_stream("#{@folder_name}.csv") { |f| f.puts(csv_file) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@download.file.attach(io: File.open(zipfile_name), filename: "#{@folder_name}.zip")
|
@download.file.attach(io: File.open(zipfile_name), filename: "#{@folder_name}.zip")
|
||||||
@@ -43,6 +48,19 @@ class GenerateContractsZipJob < ApplicationJob
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def generate_csv(releases)
|
||||||
|
release_class = @release_type.constantize
|
||||||
|
headers = release_class.csv_headers
|
||||||
|
|
||||||
|
CSV.generate(headers: true) do |csv|
|
||||||
|
csv << headers
|
||||||
|
releases.each do |release|
|
||||||
|
csv_row_data = release.to_csv_row
|
||||||
|
csv << csv_row_data
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def get_release_name(release_type)
|
def get_release_name(release_type)
|
||||||
release_type.constantize.model_name.plural
|
release_type.constantize.model_name.plural
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ class AcquiredMediaRelease < ApplicationRecord
|
|||||||
include Signable
|
include Signable
|
||||||
include Syncable
|
include Syncable
|
||||||
include PersonName
|
include PersonName
|
||||||
|
include CsvExportable
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def custom_csv_exportable_headers
|
||||||
|
%i[name file_infos_count]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
has_many :file_infos, as: :releasable, dependent: :destroy
|
has_many :file_infos, as: :releasable, dependent: :destroy
|
||||||
|
|
||||||
@@ -57,4 +64,8 @@ class AcquiredMediaRelease < ApplicationRecord
|
|||||||
def uses_edl?
|
def uses_edl?
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def file_infos_count
|
||||||
|
file_infos.any? ? file_infos.size : I18n.t('acquired_media_releases.acquired_media_release.no_media')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,6 +15,13 @@ class AppearanceRelease < ApplicationRecord
|
|||||||
include SecondGuardianPhotoable
|
include SecondGuardianPhotoable
|
||||||
include GuardianName
|
include GuardianName
|
||||||
include SecondGuardianName
|
include SecondGuardianName
|
||||||
|
include CsvExportable
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def custom_csv_exportable_headers
|
||||||
|
%i[name contact_info]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
has_one_attached :person_photo
|
has_one_attached :person_photo
|
||||||
|
|
||||||
|
|||||||
56
app/models/concerns/csv_exportable.rb
Normal file
56
app/models/concerns/csv_exportable.rb
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module CsvExportable
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
COMMON_HEADERS = %i[notes tags signed_at].freeze
|
||||||
|
COMMON_VALUES = %w[clean_notes clean_tags signed_on].freeze
|
||||||
|
|
||||||
|
included do
|
||||||
|
class << self
|
||||||
|
def custom_csv_exportable_headers
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
|
||||||
|
def csv_headers
|
||||||
|
headers = custom_csv_exportable_headers + COMMON_HEADERS
|
||||||
|
|
||||||
|
headers.map do |header|
|
||||||
|
I18n.t("#{model_name.plural}.index.table_headers.#{header}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_csv_row
|
||||||
|
(self.class.custom_csv_exportable_headers + COMMON_VALUES).map do |function|
|
||||||
|
send(function)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def contact_info
|
||||||
|
contact_info = ''
|
||||||
|
contact_info += "#{person_address}; " if person_address.present?
|
||||||
|
contact_info += "P: #{person_phone}; " if person_phone.present?
|
||||||
|
contact_info += "E: #{person_email}" if person_email.present?
|
||||||
|
contact_info.delete_suffix '; '
|
||||||
|
end
|
||||||
|
|
||||||
|
def clean_notes
|
||||||
|
notes = ''
|
||||||
|
self.notes.order_by_recent.each do |note|
|
||||||
|
notes += "#{note.content}(#{note.email}), "
|
||||||
|
end
|
||||||
|
notes.delete_suffix ', '
|
||||||
|
end
|
||||||
|
|
||||||
|
def clean_tags
|
||||||
|
tags = ''
|
||||||
|
self.tags.each do |tag|
|
||||||
|
tags += "#{tag.name}, "
|
||||||
|
end
|
||||||
|
tags.delete_suffix ', '
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -43,6 +43,8 @@ class ContractTemplate < ApplicationRecord
|
|||||||
scope :non_archived, -> { where(archived_at: nil) }
|
scope :non_archived, -> { where(archived_at: nil) }
|
||||||
scope :order_by_name, -> { order(:name) }
|
scope :order_by_name, -> { order(:name) }
|
||||||
|
|
||||||
|
enum accessibility: [:public_template, :private_template]
|
||||||
|
|
||||||
def fee?
|
def fee?
|
||||||
!fee.zero?
|
!fee.zero?
|
||||||
end
|
end
|
||||||
@@ -66,4 +68,10 @@ class ContractTemplate < ApplicationRecord
|
|||||||
def has_questionnaire?
|
def has_questionnaire?
|
||||||
(1..NUMBER_OF_CUSTOM_FIELDS).any? { |n| public_send("question_#{n}_text").presence }
|
(1..NUMBER_OF_CUSTOM_FIELDS).any? { |n| public_send("question_#{n}_text").presence }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def attributes
|
||||||
|
result = super()
|
||||||
|
result[:signature_legal_text] = signature_legal_text.as_json
|
||||||
|
result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,6 +10,13 @@ class LocationRelease < ApplicationRecord
|
|||||||
include Syncable
|
include Syncable
|
||||||
include Taggable
|
include Taggable
|
||||||
include PersonName
|
include PersonName
|
||||||
|
include CsvExportable
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def custom_csv_exportable_headers
|
||||||
|
%i[name address]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
composed_of :address,
|
composed_of :address,
|
||||||
mapping: [
|
mapping: [
|
||||||
|
|||||||
@@ -10,8 +10,15 @@ class MaterialRelease < ApplicationRecord
|
|||||||
include Syncable
|
include Syncable
|
||||||
include Taggable
|
include Taggable
|
||||||
include PersonName
|
include PersonName
|
||||||
|
include CsvExportable
|
||||||
composed_of :person_address,
|
|
||||||
|
class << self
|
||||||
|
def custom_csv_exportable_headers
|
||||||
|
%i[name]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
composed_of :person_address,
|
||||||
class_name: "Address",
|
class_name: "Address",
|
||||||
mapping: [
|
mapping: [
|
||||||
%w(person_address_street1 street1),
|
%w(person_address_street1 street1),
|
||||||
@@ -30,15 +37,15 @@ class MaterialRelease < ApplicationRecord
|
|||||||
validates :signature, attached: true
|
validates :signature, attached: true
|
||||||
end
|
end
|
||||||
|
|
||||||
searchable_on %i[
|
searchable_on %i[
|
||||||
name
|
name
|
||||||
person_address_street1 person_address_street2 person_address_city person_address_state person_address_zip person_address_country
|
person_address_street1 person_address_street2 person_address_city person_address_state person_address_zip person_address_country
|
||||||
]
|
]
|
||||||
|
|
||||||
def contact_person
|
def contact_person
|
||||||
@contact_person ||= Contact.new(person_name, person_address, person_email, person_phone)
|
@contact_person ||= Contact.new(person_name, person_address, person_email, person_phone)
|
||||||
end
|
end
|
||||||
|
|
||||||
def minor?
|
def minor?
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -11,6 +11,13 @@ class MedicalRelease < ApplicationRecord
|
|||||||
include SecondGuardianPhotoable
|
include SecondGuardianPhotoable
|
||||||
include GuardianName
|
include GuardianName
|
||||||
include SecondGuardianName
|
include SecondGuardianName
|
||||||
|
include CsvExportable
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def custom_csv_exportable_headers
|
||||||
|
%i[approved? name contact_info]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
NUMBER_OF_CUSTOM_FIELDS = 15
|
NUMBER_OF_CUSTOM_FIELDS = 15
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ class MiscRelease < ApplicationRecord
|
|||||||
include PersonName
|
include PersonName
|
||||||
include GuardianName
|
include GuardianName
|
||||||
include GuardianPhotoable
|
include GuardianPhotoable
|
||||||
|
include CsvExportable
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def custom_csv_exportable_headers
|
||||||
|
%i[name contact_info]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
NUMBER_OF_CUSTOM_FIELDS = 15
|
NUMBER_OF_CUSTOM_FIELDS = 15
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,14 @@ class MusicRelease < ApplicationRecord
|
|||||||
include Searchable
|
include Searchable
|
||||||
include Taggable
|
include Taggable
|
||||||
include PersonName
|
include PersonName
|
||||||
|
include CsvExportable
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def custom_csv_exportable_headers
|
||||||
|
%i[name file_infos_count composers_count publishers_count]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
has_many :file_infos, as: :releasable, dependent: :destroy
|
has_many :file_infos, as: :releasable, dependent: :destroy
|
||||||
has_many :composers, dependent: :destroy
|
has_many :composers, dependent: :destroy
|
||||||
has_many :publishers, dependent: :destroy
|
has_many :publishers, dependent: :destroy
|
||||||
@@ -72,6 +79,18 @@ class MusicRelease < ApplicationRecord
|
|||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def file_infos_count
|
||||||
|
file_infos.size
|
||||||
|
end
|
||||||
|
|
||||||
|
def composers_count
|
||||||
|
composers.size
|
||||||
|
end
|
||||||
|
|
||||||
|
def publishers_count
|
||||||
|
publishers.size
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def publisher_percentages_add_up_to_100
|
def publisher_percentages_add_up_to_100
|
||||||
|
|||||||
@@ -14,6 +14,13 @@ class TalentRelease < ApplicationRecord
|
|||||||
include SecondGuardianPhotoable
|
include SecondGuardianPhotoable
|
||||||
include GuardianName
|
include GuardianName
|
||||||
include SecondGuardianName
|
include SecondGuardianName
|
||||||
|
include CsvExportable
|
||||||
|
|
||||||
|
class << self
|
||||||
|
def custom_csv_exportable_headers
|
||||||
|
%i[name phone email]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
composed_of :person_address,
|
composed_of :person_address,
|
||||||
class_name: "Address",
|
class_name: "Address",
|
||||||
@@ -86,6 +93,14 @@ class TalentRelease < ApplicationRecord
|
|||||||
person_name
|
person_name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def phone
|
||||||
|
person_phone
|
||||||
|
end
|
||||||
|
|
||||||
|
def email
|
||||||
|
person_email
|
||||||
|
end
|
||||||
|
|
||||||
def filename_suffix
|
def filename_suffix
|
||||||
"#{person_last_name} #{person_first_name}"
|
"#{person_last_name} #{person_first_name}"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ class ContractTemplatePolicy < ApplicationPolicy
|
|||||||
def resolve
|
def resolve
|
||||||
if user.account_manager?
|
if user.account_manager?
|
||||||
scope.left_outer_joins(:project).where(projects: {account: user.account})
|
scope.left_outer_joins(:project).where(projects: {account: user.account})
|
||||||
else
|
elsif user.manager?
|
||||||
scope.left_outer_joins(project: :project_memberships).where(project_memberships: { user_id: user.id })
|
scope.left_outer_joins(project: :project_memberships).where(project_memberships: { user_id: user.id })
|
||||||
|
else
|
||||||
|
scope.public_template.left_outer_joins(project: :project_memberships).where(project_memberships: { user_id: user.id })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
<%= form.text_field :name, wrapper_class: "col-sm-6" %>
|
<%= 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_show_values_mapping: { "#guardian_clause": %w(appearance talent misc medical), "#fee_field": %w(appearance talent location material acquired_media), "#exploitable_rights_fields": %w(appearance talent location material acquired_media), "#custom_fields": %w(medical misc) } }, 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 misc medical), "#fee_field": %w(appearance talent location material acquired_media), "#exploitable_rights_fields": %w(appearance talent location material acquired_media), "#custom_fields": %w(medical misc) } }, class: "form-control custom-select" %>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-row mb-3">
|
||||||
|
<%= form.radio_button :accessibility, :public_template, label: "Public", wrapper_class: "mr-3" %>
|
||||||
|
<%= form.radio_button :accessibility, :private_template, label: "Private" %>
|
||||||
|
</div>
|
||||||
<div class="form-row" id="fee_field">
|
<div class="form-row" id="fee_field">
|
||||||
<%= form.number_field :fee, min:"0", max:"99999999", step: "0.01", prepend: "$", wrapper_class: "col-sm-6" %>
|
<%= form.number_field :fee, min:"0", max:"99999999", step: "0.01", prepend: "$", wrapper_class: "col-sm-6" %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ en:
|
|||||||
empty: Acquired Media Releases will appear here
|
empty: Acquired Media Releases will appear here
|
||||||
table_headers:
|
table_headers:
|
||||||
file_infos_count: No. Files
|
file_infos_count: No. Files
|
||||||
|
name: Name
|
||||||
notes: Notes
|
notes: Notes
|
||||||
signed_at: Date Signed
|
signed_at: Date Signed
|
||||||
tags: Tags
|
tags: Tags
|
||||||
@@ -151,6 +152,8 @@ en:
|
|||||||
empty: Appearance Releases will appear here
|
empty: Appearance Releases will appear here
|
||||||
imported_appearance_release_missing_attachment: Person photo or contract missing for imported appearance release
|
imported_appearance_release_missing_attachment: Person photo or contract missing for imported appearance release
|
||||||
table_headers:
|
table_headers:
|
||||||
|
contact_info: Contact info
|
||||||
|
name: Name
|
||||||
notes: Notes
|
notes: Notes
|
||||||
signed_at: Date Signed
|
signed_at: Date Signed
|
||||||
tags: Tags
|
tags: Tags
|
||||||
@@ -742,6 +745,7 @@ en:
|
|||||||
empty: Location Releases will appear here
|
empty: Location Releases will appear here
|
||||||
table_headers:
|
table_headers:
|
||||||
address: Address
|
address: Address
|
||||||
|
name: Name
|
||||||
notes: Notes
|
notes: Notes
|
||||||
signed_at: Date Signed
|
signed_at: Date Signed
|
||||||
tags: Tags
|
tags: Tags
|
||||||
@@ -776,6 +780,7 @@ en:
|
|||||||
search: Search
|
search: Search
|
||||||
empty: Material Releases will appear here
|
empty: Material Releases will appear here
|
||||||
table_headers:
|
table_headers:
|
||||||
|
name: Name
|
||||||
notes: Notes
|
notes: Notes
|
||||||
signed_at: Date Signed
|
signed_at: Date Signed
|
||||||
tags: Tags
|
tags: Tags
|
||||||
@@ -798,6 +803,9 @@ en:
|
|||||||
empty: Medical releases will appear here
|
empty: Medical releases will appear here
|
||||||
table_headers:
|
table_headers:
|
||||||
approved: Approved
|
approved: Approved
|
||||||
|
approved?: Approved
|
||||||
|
contact_info: Contact info
|
||||||
|
name: Person name
|
||||||
notes: Notes
|
notes: Notes
|
||||||
signed_at: Date Signed
|
signed_at: Date Signed
|
||||||
tags: Tags
|
tags: Tags
|
||||||
@@ -815,6 +823,8 @@ en:
|
|||||||
search: Search
|
search: Search
|
||||||
empty: Misc Releases will appear here
|
empty: Misc Releases will appear here
|
||||||
table_headers:
|
table_headers:
|
||||||
|
contact_info: Contact info
|
||||||
|
name: Person name
|
||||||
notes: Notes
|
notes: Notes
|
||||||
signed_at: Date Signed
|
signed_at: Date Signed
|
||||||
tags: Tags
|
tags: Tags
|
||||||
@@ -849,6 +859,7 @@ en:
|
|||||||
table_headers:
|
table_headers:
|
||||||
composers_count: No. Composers
|
composers_count: No. Composers
|
||||||
file_infos_count: No. Files
|
file_infos_count: No. Files
|
||||||
|
name: Name
|
||||||
notes: Notes
|
notes: Notes
|
||||||
publishers_count: No. Publishers
|
publishers_count: No. Publishers
|
||||||
signed_at: Date Signed
|
signed_at: Date Signed
|
||||||
@@ -1245,7 +1256,10 @@ en:
|
|||||||
search: Search
|
search: Search
|
||||||
empty: Talent Releases will appear here
|
empty: Talent Releases will appear here
|
||||||
table_headers:
|
table_headers:
|
||||||
|
email: Email
|
||||||
|
name: Name
|
||||||
notes: Notes
|
notes: Notes
|
||||||
|
phone: Phone
|
||||||
signed_at: Date Signed
|
signed_at: Date Signed
|
||||||
tags: Tags
|
tags: Tags
|
||||||
new:
|
new:
|
||||||
|
|||||||
@@ -1,4 +1,14 @@
|
|||||||
es:
|
es:
|
||||||
|
acquired_media_releases:
|
||||||
|
acquired_media_release:
|
||||||
|
no_media: No Media (ES)
|
||||||
|
index:
|
||||||
|
table_headers:
|
||||||
|
file_infos_count: No. Files (ES)
|
||||||
|
name: Name (ES)
|
||||||
|
notes: Notes (ES)
|
||||||
|
signed_at: Date Signed (ES)
|
||||||
|
tags: Tags (ES)
|
||||||
activerecord:
|
activerecord:
|
||||||
attributes:
|
attributes:
|
||||||
appearance_release:
|
appearance_release:
|
||||||
@@ -41,6 +51,12 @@ es:
|
|||||||
heading: Person Photo (ES)
|
heading: Person Photo (ES)
|
||||||
index:
|
index:
|
||||||
imported_appearance_release_missing_attachment: Person photo or contract missing for imported appearance release (ES)
|
imported_appearance_release_missing_attachment: Person photo or contract missing for imported appearance release (ES)
|
||||||
|
table_headers:
|
||||||
|
contact_info: ""
|
||||||
|
name: ""
|
||||||
|
notes: ""
|
||||||
|
signed_at: ""
|
||||||
|
tags: ""
|
||||||
shared:
|
shared:
|
||||||
imported_appearance_release_contract_name: Contrato Importado
|
imported_appearance_release_contract_name: Contrato Importado
|
||||||
imported_appearance_release_headshot_name: Retrato Importado
|
imported_appearance_release_headshot_name: Retrato Importado
|
||||||
@@ -296,21 +312,57 @@ es:
|
|||||||
form:
|
form:
|
||||||
photos:
|
photos:
|
||||||
dropzone_label: Tap to take a photo of the Property (optional) (ES)
|
dropzone_label: Tap to take a photo of the Property (optional) (ES)
|
||||||
|
index:
|
||||||
|
table_headers:
|
||||||
|
address: Address (ES)
|
||||||
|
notes: Notes (ES)
|
||||||
|
signed_at: Date Signed (ES)
|
||||||
|
tags: Tags (ES)
|
||||||
material_releases:
|
material_releases:
|
||||||
form:
|
form:
|
||||||
photos:
|
photos:
|
||||||
dropzone_label: Tap to take a photo of Licensed Material (optional) (ES)
|
dropzone_label: Tap to take a photo of Licensed Material (optional) (ES)
|
||||||
|
index:
|
||||||
|
table_headers:
|
||||||
|
name: Name (ES)
|
||||||
|
notes: Notes (ES)
|
||||||
|
signed_at: Date Signed (ES)
|
||||||
|
tags: Tags (ES)
|
||||||
medical_releases:
|
medical_releases:
|
||||||
custom_validation_errors:
|
custom_validation_errors:
|
||||||
question_answer_is_required: answer is required (ES)
|
question_answer_is_required: answer is required (ES)
|
||||||
index:
|
index:
|
||||||
table_headers:
|
table_headers:
|
||||||
approved: Approved (ES)
|
approved: Approved (ES)
|
||||||
|
approved?: Approved (ES)
|
||||||
|
contact_info: Contact info (ES)
|
||||||
|
name: Person name (ES)
|
||||||
|
notes: Notes (ES)
|
||||||
|
signed_at: Date Signed (ES)
|
||||||
|
tags: Tags (ES)
|
||||||
medical_release:
|
medical_release:
|
||||||
actions:
|
actions:
|
||||||
review: Review (ES)
|
review: Review (ES)
|
||||||
messages:
|
messages:
|
||||||
approved_tooltip: ""
|
approved_tooltip: ""
|
||||||
|
misc_releases:
|
||||||
|
index:
|
||||||
|
table_headers:
|
||||||
|
contact_info: Contact info (ES)
|
||||||
|
name: Person name (ES)
|
||||||
|
notes: Notes (ES)
|
||||||
|
signed_at: Date Signed (ES)
|
||||||
|
tags: Tags (ES)
|
||||||
|
music_releases:
|
||||||
|
index:
|
||||||
|
table_headers:
|
||||||
|
composers_count: No. Composers (ES)
|
||||||
|
file_infos_count: No. Files (ES)
|
||||||
|
name: Name (ES)
|
||||||
|
notes: Notes (ES)
|
||||||
|
publishers_count: No. Publishers (ES)
|
||||||
|
signed_at: Date Signed (ES)
|
||||||
|
tags: Tags (ES)
|
||||||
public:
|
public:
|
||||||
appearance_releases:
|
appearance_releases:
|
||||||
create:
|
create:
|
||||||
@@ -415,6 +467,14 @@ es:
|
|||||||
heading: Second Guardian Photo (ES)
|
heading: Second Guardian Photo (ES)
|
||||||
guardian_photo:
|
guardian_photo:
|
||||||
heading: Guardian Photo (ES)
|
heading: Guardian Photo (ES)
|
||||||
|
index:
|
||||||
|
table_headers:
|
||||||
|
email: Email (ES)
|
||||||
|
name: Name (ES)
|
||||||
|
notes: Notes (ES)
|
||||||
|
phone: Phone (ES)
|
||||||
|
signed_at: Date Signed (ES)
|
||||||
|
tags: Tags (ES)
|
||||||
task_requests:
|
task_requests:
|
||||||
create:
|
create:
|
||||||
success_message: Your task request was successfully submitted. Thank you. A chat window will pop up on the lower right in a few seconds. (ES)
|
success_message: Your task request was successfully submitted. Thank you. A chat window will pop up on the lower right in a few seconds. (ES)
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
class AddDurationToBroadcastRecordings < ActiveRecord::DataMigration
|
||||||
|
def up
|
||||||
|
recordings = BroadcastRecording.where(duration: nil)
|
||||||
|
client = MuxRuby::AssetsApi.new
|
||||||
|
|
||||||
|
recordings.each do |recording|
|
||||||
|
begin
|
||||||
|
response = client.get_asset(recording.asset_uid)
|
||||||
|
duration = response.data.duration
|
||||||
|
recording.update(duration: duration)
|
||||||
|
rescue MuxRuby::ApiError => e
|
||||||
|
Rails.logger.error("Failed to update duration for broadcast recording with id #{recording.id}\n" + e.message)
|
||||||
|
end
|
||||||
|
|
||||||
|
sleep(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class AddAccessibilityToContractTemplates < ActiveRecord::Migration[6.0]
|
||||||
|
def change
|
||||||
|
add_column :contract_templates, :accessibility, :integer, default: 0
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class AddDurationToBroadcastRecordings < ActiveRecord::Migration[6.0]
|
||||||
|
def change
|
||||||
|
add_column :broadcast_recordings, :duration, :float
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -9,6 +9,20 @@ SET xmloption = content;
|
|||||||
SET client_min_messages = warning;
|
SET client_min_messages = warning;
|
||||||
SET row_security = off;
|
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: -
|
-- Name: fuzzystrmatch; Type: EXTENSION; Schema: -; Owner: -
|
||||||
--
|
--
|
||||||
@@ -494,7 +508,8 @@ CREATE TABLE public.broadcast_recordings (
|
|||||||
asset_playback_uid character varying NOT NULL,
|
asset_playback_uid character varying NOT NULL,
|
||||||
file_name character varying NOT NULL,
|
file_name character varying NOT NULL,
|
||||||
created_at timestamp(6) without time zone NOT NULL,
|
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,
|
||||||
|
duration double precision
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -629,7 +644,8 @@ CREATE TABLE public.contract_templates (
|
|||||||
question_12_text text,
|
question_12_text text,
|
||||||
question_13_text text,
|
question_13_text text,
|
||||||
question_14_text text,
|
question_14_text text,
|
||||||
question_15_text text
|
question_15_text text,
|
||||||
|
accessibility integer DEFAULT 0
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -3906,6 +3922,8 @@ INSERT INTO "schema_migrations" (version) VALUES
|
|||||||
('20200622180507'),
|
('20200622180507'),
|
||||||
('20200625144713'),
|
('20200625144713'),
|
||||||
('20200702152130'),
|
('20200702152130'),
|
||||||
('20200707155717');
|
('20200707155717'),
|
||||||
|
('20200709120630'),
|
||||||
|
('20200712181139');
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,21 @@ RSpec.describe Api::ContractTemplatesController, type: :controller do
|
|||||||
|
|
||||||
expect(response).to be_successful
|
expect(response).to be_successful
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'returns electronic signature legal text when present' do
|
||||||
|
ct = create(:contract_template, name: 'ct1', project_id: project.id)
|
||||||
|
ct.signature_legal_text = "some electronic signature legal text"
|
||||||
|
ct.save
|
||||||
|
|
||||||
|
sign_in_to_api(current_user)
|
||||||
|
get :show, params: { id: ct.id }
|
||||||
|
|
||||||
|
expect(response).to be_successful
|
||||||
|
|
||||||
|
expect(response.body).to include("signature_legal_text")
|
||||||
|
expect(response.body).to include(ct.signature_legal_text.body.as_json)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -127,9 +127,16 @@ RSpec.describe Api::SyncController, type: :controller do
|
|||||||
get :index
|
get :index
|
||||||
|
|
||||||
medical_releases = attributes_for_type('medical_releases')
|
medical_releases = attributes_for_type('medical_releases')
|
||||||
|
|
||||||
expect(medical_releases.first).to include('id')
|
expect(medical_releases.first).to include('id')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'contains signature legal text for contract templates' do
|
||||||
|
create_default_data_with_signature_legal_text
|
||||||
|
get :index
|
||||||
|
contract_templates = attributes_for_type('contract_templates')
|
||||||
|
expect(contract_templates.first).to include('signature_legal_text')
|
||||||
|
expect(contract_templates.first['signature_legal_text']).to eq ContractTemplate.first.signature_legal_text.as_json
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@@ -149,6 +156,13 @@ RSpec.describe Api::SyncController, type: :controller do
|
|||||||
create(:appearance_release, :minor_with_guardian_photo, project: project)
|
create(:appearance_release, :minor_with_guardian_photo, project: project)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create_default_data_with_signature_legal_text
|
||||||
|
create_default_data
|
||||||
|
ct = create(:contract_template, name: "with signature legal text", project: Project.first)
|
||||||
|
ct.signature_legal_text = "legal text example"
|
||||||
|
ct.save
|
||||||
|
end
|
||||||
|
|
||||||
def response_body_json
|
def response_body_json
|
||||||
JSON.parse(response.body)
|
JSON.parse(response.body)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ FactoryBot.define do
|
|||||||
body "This is a test contract template."
|
body "This is a test contract template."
|
||||||
guardian_clause "Is the signer a minor?"
|
guardian_clause "Is the signer a minor?"
|
||||||
fee "$0.00"
|
fee "$0.00"
|
||||||
|
accessibility "public_template"
|
||||||
|
|
||||||
trait :archived do
|
trait :archived do
|
||||||
archived_at Time.zone.now
|
archived_at Time.zone.now
|
||||||
|
|||||||
@@ -49,12 +49,18 @@ FactoryBot.define do
|
|||||||
predefined_client_name "nat_geo"
|
predefined_client_name "nat_geo"
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :project_with_contract_template do
|
factory :project_with_contract_template_public do
|
||||||
after(:build) do |project, _|
|
after(:build) do |project, _|
|
||||||
project.contract_templates << build(:contract_template, project: nil)
|
project.contract_templates << build(:contract_template, project: nil)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :project_with_contract_template_private do
|
||||||
|
after(:build) do |project, _|
|
||||||
|
project.contract_templates << build(:contract_template, project: nil, accessibility: "private_template")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
factory :project_with_directories do
|
factory :project_with_directories do
|
||||||
after(:build) do |project, _|
|
after(:build) do |project, _|
|
||||||
project.directories << build(:directory, project: nil, name: "Shared")
|
project.directories << build(:directory, project: nil, name: "Shared")
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ describe GenerateContractsZipJob do
|
|||||||
dir = Rails.root.join("spec", "fixtures", "files")
|
dir = Rails.root.join("spec", "fixtures", "files")
|
||||||
files = ["contract.pdf", "AppearanceRelease.pdf"]
|
files = ["contract.pdf", "AppearanceRelease.pdf"]
|
||||||
# Attachments in the test environment do not persist to cloud storage
|
# Attachments in the test environment do not persist to cloud storage
|
||||||
# Therefore we want to stub calls to `open` with a cloud storage URL
|
# Therefore we want to stub calls to `open` with a cloud storage URL
|
||||||
allow_any_instance_of(ReleaseContractCollectionService).to receive(:open).and_return(StringIO.new("file data"))
|
allow_any_instance_of(ReleaseContractCollectionService).to receive(:open).and_return(StringIO.new("file data"))
|
||||||
allow_any_instance_of(ReleaseContractCollectionService).to receive(:build).and_yield(dir, files)
|
allow_any_instance_of(ReleaseContractCollectionService).to receive(:build).and_yield(dir, files)
|
||||||
end
|
end
|
||||||
@@ -35,6 +35,38 @@ describe GenerateContractsZipJob do
|
|||||||
expect(download.file).to be_attached
|
expect(download.file).to be_attached
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "generates ZIP containing CSV file with all releases data for all release types" do
|
||||||
|
release_types = %w[AcquiredMediaRelease AppearanceRelease LocationRelease MaterialRelease MedicalRelease MiscRelease MusicRelease TalentRelease]
|
||||||
|
create_releases_for_all_types
|
||||||
|
|
||||||
|
release_types.each do |type|
|
||||||
|
lowercase_plural = type.constantize.model_name.plural
|
||||||
|
GenerateContractsZipJob.perform_now(project, download, type, project.public_send(lowercase_plural).ids)
|
||||||
|
|
||||||
|
generated_zip = download.file.blob.download
|
||||||
|
csv_file_name = "#{project.name.parameterize}_#{lowercase_plural.gsub('_', '-')}.csv"
|
||||||
|
Zip::InputStream.open(StringIO.new(generated_zip)) do |io|
|
||||||
|
while entry = io.get_next_entry
|
||||||
|
next unless entry.name == csv_file_name
|
||||||
|
|
||||||
|
csv_file = entry.get_input_stream.read
|
||||||
|
|
||||||
|
release_class = Object.const_get type
|
||||||
|
release_headers = release_class.csv_headers
|
||||||
|
|
||||||
|
release_headers.each do |header|
|
||||||
|
expect(csv_file).to match header
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
dummy_zip_file_name = "#{project.name.parameterize}_#{lowercase_plural.gsub('_', '-')}.zip"
|
||||||
|
if File.exist?(file_fixture(dummy_zip_file_name))
|
||||||
|
File.delete(file_fixture(dummy_zip_file_name))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "When there are errors" do
|
context "When there are errors" do
|
||||||
let(:error) { StandardError.new("Contracts or contract templates not found.") }
|
let(:error) { StandardError.new("Contracts or contract templates not found.") }
|
||||||
|
|
||||||
@@ -42,10 +74,10 @@ describe GenerateContractsZipJob do
|
|||||||
allow(ProjectsChannel).to receive(:broadcast_download_generation_update).with(download, I18n.t("contract_downloads.download.failure"))
|
allow(ProjectsChannel).to receive(:broadcast_download_generation_update).with(download, I18n.t("contract_downloads.download.failure"))
|
||||||
allow_any_instance_of(ReleaseContractCollectionService).to receive(:build).and_raise(StandardError, "Contracts or contract templates not found")
|
allow_any_instance_of(ReleaseContractCollectionService).to receive(:build).and_raise(StandardError, "Contracts or contract templates not found")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "updates status to 'failure' and sends user a notification" do
|
it "updates status to 'failure' and sends user a notification" do
|
||||||
GenerateContractsZipJob.perform_now(project, download, "AppearanceRelease", project.appearance_releases.ids)
|
GenerateContractsZipJob.perform_now(project, download, "AppearanceRelease", project.appearance_releases.ids)
|
||||||
|
|
||||||
expect(download.status).to eq "failure"
|
expect(download.status).to eq "failure"
|
||||||
expect(ProjectsChannel).to have_received(:broadcast_download_generation_update).with(download, I18n.t("contract_downloads.download.failure"))
|
expect(ProjectsChannel).to have_received(:broadcast_download_generation_update).with(download, I18n.t("contract_downloads.download.failure"))
|
||||||
end
|
end
|
||||||
@@ -56,6 +88,21 @@ describe GenerateContractsZipJob do
|
|||||||
# Delete the file created in fixture.
|
# Delete the file created in fixture.
|
||||||
# Or the tests will fail on next run due to already existing files in existing zip.
|
# Or the tests will fail on next run due to already existing files in existing zip.
|
||||||
path = Rails.root.join("spec", "fixtures", "files")
|
path = Rails.root.join("spec", "fixtures", "files")
|
||||||
File.delete("#{path}/my-video-project_appearance-releases.zip") if File.exists? "#{path}/my-video-project_appearance-releases.zip"
|
if File.exists? "#{path}/my-video-project_appearance-releases.zip"
|
||||||
|
File.delete("#{path}/my-video-project_appearance-releases.zip")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def create_releases_for_all_types
|
||||||
|
create(:acquired_media_release_with_contract_template, :native, project: project)
|
||||||
|
create(:appearance_release_with_contract_template, :native, project: project, person_name: "John Doe")
|
||||||
|
create(:location_release_with_contract_template, :native, project: project)
|
||||||
|
create(:material_release_with_contract_template, :native, project: project)
|
||||||
|
create(:medical_release_with_contract_template, :native, project: project)
|
||||||
|
create(:misc_release_with_contract_template, :native, project: project)
|
||||||
|
create(:music_release_with_contract_template, project: project)
|
||||||
|
create(:talent_release_with_contract_template, :native, project: project)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ RSpec.describe Project, type: :model do
|
|||||||
|
|
||||||
describe "#import_contract_templates" do
|
describe "#import_contract_templates" do
|
||||||
it "imports contract templates from other projects within the account" do
|
it "imports contract templates from other projects within the account" do
|
||||||
existing_project = create(:project_with_contract_template)
|
existing_project = create(:project_with_contract_template_public)
|
||||||
new_project = create(:project, name: "New Project", account: existing_project.account)
|
new_project = create(:project, name: "New Project", account: existing_project.account)
|
||||||
|
|
||||||
expect {
|
expect {
|
||||||
|
|||||||
@@ -75,14 +75,17 @@ describe ContractTemplatePolicy do
|
|||||||
end
|
end
|
||||||
|
|
||||||
permissions ".scope" do
|
permissions ".scope" do
|
||||||
let!(:member_project) do
|
let!(:member_project_public_template) do
|
||||||
create(:project_with_contract_template, name: "Member Project", members: user, account: account)
|
create(:project_with_contract_template_public, name: "Member Project Public Template", members: user, account: account)
|
||||||
|
end
|
||||||
|
let!(:member_project_private_template) do
|
||||||
|
create(:project_with_contract_template_private, name: "Member Project Private Template", members: user, account: account)
|
||||||
end
|
end
|
||||||
let!(:non_member_project) do
|
let!(:non_member_project) do
|
||||||
create(:project_with_contract_template, name: "Non-Member Project", account: account)
|
create(:project_with_contract_template_public, name: "Non-Member Project", account: account)
|
||||||
end
|
end
|
||||||
let!(:outside_project) do
|
let!(:outside_project) do
|
||||||
create(:project_with_contract_template, name: "Outside Project", account: build(:account))
|
create(:project_with_contract_template_public, name: "Outside Project", account: build(:account))
|
||||||
end
|
end
|
||||||
|
|
||||||
let(:account) { build(:account) }
|
let(:account) { build(:account) }
|
||||||
@@ -93,7 +96,8 @@ describe ContractTemplatePolicy do
|
|||||||
context "for an account manager" do
|
context "for an account manager" do
|
||||||
let(:user) { create(:user, :account_manager, primary_account: account)}
|
let(:user) { create(:user, :account_manager, primary_account: account)}
|
||||||
|
|
||||||
it { is_expected.to include(member_project.contract_templates.first) }
|
it { is_expected.to include(member_project_public_template.contract_templates.first) }
|
||||||
|
it { is_expected.to include(member_project_private_template.contract_templates.first) }
|
||||||
it { is_expected.to include(non_member_project.contract_templates.first) }
|
it { is_expected.to include(non_member_project.contract_templates.first) }
|
||||||
it { is_expected.not_to include(outside_project.contract_templates.first) }
|
it { is_expected.not_to include(outside_project.contract_templates.first) }
|
||||||
end
|
end
|
||||||
@@ -101,15 +105,17 @@ describe ContractTemplatePolicy do
|
|||||||
context "for manager" do
|
context "for manager" do
|
||||||
let(:user) { create(:user, :manager, primary_account: account) }
|
let(:user) { create(:user, :manager, primary_account: account) }
|
||||||
|
|
||||||
it { is_expected.to include(member_project.contract_templates.first) }
|
it { is_expected.to include(member_project_public_template.contract_templates.first) }
|
||||||
|
it { is_expected.to include(member_project_private_template.contract_templates.first) }
|
||||||
it { is_expected.not_to include(non_member_project.contract_templates.first) }
|
it { is_expected.not_to include(non_member_project.contract_templates.first) }
|
||||||
it { is_expected.not_to include(outside_project.contract_templates.first) }
|
it { is_expected.not_to include(outside_project.contract_templates.first) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context "for associate" do
|
context "for associate" do
|
||||||
let(:user) { create(:user, :associate, primary_account: account) }
|
let(:user) { create(:user, :associate, primary_account: account) }
|
||||||
|
|
||||||
it { is_expected.to include(member_project.contract_templates.first) }
|
it { is_expected.to include(member_project_public_template.contract_templates.first) }
|
||||||
|
it { is_expected.not_to include(member_project_private_template.contract_templates.first) }
|
||||||
it { is_expected.not_to include(non_member_project.contract_templates.first) }
|
it { is_expected.not_to include(non_member_project.contract_templates.first) }
|
||||||
it { is_expected.not_to include(outside_project.contract_templates.first) }
|
it { is_expected.not_to include(outside_project.contract_templates.first) }
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user