diff --git a/app/controllers/contract_templates_controller.rb b/app/controllers/contract_templates_controller.rb
index 60d65d2..8e70811 100644
--- a/app/controllers/contract_templates_controller.rb
+++ b/app/controllers/contract_templates_controller.rb
@@ -66,7 +66,7 @@ class ContractTemplatesController < ApplicationController
:signature_legal_text, :fee,
:applicable_medium_id, :applicable_medium_text,
:territory_id, :territory_text,
- :term_id, :term_text,
+ :term_id, :term_text, :accessibility,
:restriction_id, :restriction_text,
:question_1_text, :question_2_text,
:question_3_text, :question_4_text,
diff --git a/app/controllers/stream_notifications_controller.rb b/app/controllers/stream_notifications_controller.rb
index 12b8ee2..ce76ff6 100644
--- a/app/controllers/stream_notifications_controller.rb
+++ b/app/controllers/stream_notifications_controller.rb
@@ -28,8 +28,9 @@ class StreamNotificationsController < ApplicationController
asset_uid = notification.dig(:object, :id)
playback_uid = notification.dig(:data, :playback_ids, 0, :id)
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])
link = helpers.link_to(recording.broadcast_name.titleize, recording.download_url, target: "_blank")
diff --git a/app/jobs/generate_contracts_zip_job.rb b/app/jobs/generate_contracts_zip_job.rb
index 865a5ea..65bc376 100644
--- a/app/jobs/generate_contracts_zip_job.rb
+++ b/app/jobs/generate_contracts_zip_job.rb
@@ -6,8 +6,8 @@ class GenerateContractsZipJob < ApplicationJob
before_perform do |job|
@project = job.arguments.first
@download = job.arguments.second
- release_type = job.arguments.third
- @folder_name = "#{@project.name.parameterize}_#{get_release_name(release_type).gsub('_', '-')}"
+ @release_type = job.arguments.third
+ @folder_name = "#{@project.name.parameterize}_#{get_release_name(@release_type).gsub('_', '-')}"
@download.update!(name: @folder_name, status: :pending)
end
@@ -20,6 +20,11 @@ class GenerateContractsZipJob < ApplicationJob
files.each do |attachment|
zipfile.add(attachment, File.join("#{dir}/", attachment))
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
@download.file.attach(io: File.open(zipfile_name), filename: "#{@folder_name}.zip")
@@ -43,6 +48,19 @@ class GenerateContractsZipJob < ApplicationJob
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)
release_type.constantize.model_name.plural
end
diff --git a/app/models/acquired_media_release.rb b/app/models/acquired_media_release.rb
index 6a12d35..8b7a7b0 100644
--- a/app/models/acquired_media_release.rb
+++ b/app/models/acquired_media_release.rb
@@ -9,6 +9,13 @@ class AcquiredMediaRelease < ApplicationRecord
include Signable
include Syncable
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
@@ -57,4 +64,8 @@ class AcquiredMediaRelease < ApplicationRecord
def uses_edl?
true
end
+
+ def file_infos_count
+ file_infos.any? ? file_infos.size : I18n.t('acquired_media_releases.acquired_media_release.no_media')
+ end
end
diff --git a/app/models/appearance_release.rb b/app/models/appearance_release.rb
index 9a750a7..c9bb4c0 100644
--- a/app/models/appearance_release.rb
+++ b/app/models/appearance_release.rb
@@ -15,6 +15,13 @@ class AppearanceRelease < ApplicationRecord
include SecondGuardianPhotoable
include GuardianName
include SecondGuardianName
+ include CsvExportable
+
+ class << self
+ def custom_csv_exportable_headers
+ %i[name contact_info]
+ end
+ end
has_one_attached :person_photo
diff --git a/app/models/concerns/csv_exportable.rb b/app/models/concerns/csv_exportable.rb
new file mode 100644
index 0000000..4619e86
--- /dev/null
+++ b/app/models/concerns/csv_exportable.rb
@@ -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
diff --git a/app/models/contract_template.rb b/app/models/contract_template.rb
index 8922bde..ba2ce3d 100644
--- a/app/models/contract_template.rb
+++ b/app/models/contract_template.rb
@@ -43,6 +43,8 @@ class ContractTemplate < ApplicationRecord
scope :non_archived, -> { where(archived_at: nil) }
scope :order_by_name, -> { order(:name) }
+ enum accessibility: [:public_template, :private_template]
+
def fee?
!fee.zero?
end
@@ -66,4 +68,10 @@ class ContractTemplate < ApplicationRecord
def has_questionnaire?
(1..NUMBER_OF_CUSTOM_FIELDS).any? { |n| public_send("question_#{n}_text").presence }
end
+
+ def attributes
+ result = super()
+ result[:signature_legal_text] = signature_legal_text.as_json
+ result
+ end
end
diff --git a/app/models/location_release.rb b/app/models/location_release.rb
index a5b6a02..1e49d73 100644
--- a/app/models/location_release.rb
+++ b/app/models/location_release.rb
@@ -10,6 +10,13 @@ class LocationRelease < ApplicationRecord
include Syncable
include Taggable
include PersonName
+ include CsvExportable
+
+ class << self
+ def custom_csv_exportable_headers
+ %i[name address]
+ end
+ end
composed_of :address,
mapping: [
diff --git a/app/models/material_release.rb b/app/models/material_release.rb
index 56d45ee..dc5380e 100644
--- a/app/models/material_release.rb
+++ b/app/models/material_release.rb
@@ -10,8 +10,15 @@ class MaterialRelease < ApplicationRecord
include Syncable
include Taggable
include PersonName
-
- composed_of :person_address,
+ include CsvExportable
+
+ class << self
+ def custom_csv_exportable_headers
+ %i[name]
+ end
+ end
+
+ composed_of :person_address,
class_name: "Address",
mapping: [
%w(person_address_street1 street1),
@@ -30,15 +37,15 @@ class MaterialRelease < ApplicationRecord
validates :signature, attached: true
end
- searchable_on %i[
- name
+ searchable_on %i[
+ name
person_address_street1 person_address_street2 person_address_city person_address_state person_address_zip person_address_country
]
def contact_person
@contact_person ||= Contact.new(person_name, person_address, person_email, person_phone)
end
-
+
def minor?
false
end
diff --git a/app/models/medical_release.rb b/app/models/medical_release.rb
index 996bfc5..e037ef5 100644
--- a/app/models/medical_release.rb
+++ b/app/models/medical_release.rb
@@ -11,6 +11,13 @@ class MedicalRelease < ApplicationRecord
include SecondGuardianPhotoable
include GuardianName
include SecondGuardianName
+ include CsvExportable
+
+ class << self
+ def custom_csv_exportable_headers
+ %i[approved? name contact_info]
+ end
+ end
NUMBER_OF_CUSTOM_FIELDS = 15
diff --git a/app/models/misc_release.rb b/app/models/misc_release.rb
index f9437dd..2679542 100644
--- a/app/models/misc_release.rb
+++ b/app/models/misc_release.rb
@@ -9,6 +9,13 @@ class MiscRelease < ApplicationRecord
include PersonName
include GuardianName
include GuardianPhotoable
+ include CsvExportable
+
+ class << self
+ def custom_csv_exportable_headers
+ %i[name contact_info]
+ end
+ end
NUMBER_OF_CUSTOM_FIELDS = 15
diff --git a/app/models/music_release.rb b/app/models/music_release.rb
index 29fd426..b324b9f 100644
--- a/app/models/music_release.rb
+++ b/app/models/music_release.rb
@@ -7,7 +7,14 @@ class MusicRelease < ApplicationRecord
include Searchable
include Taggable
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 :composers, dependent: :destroy
has_many :publishers, dependent: :destroy
@@ -72,6 +79,18 @@ class MusicRelease < ApplicationRecord
false
end
+ def file_infos_count
+ file_infos.size
+ end
+
+ def composers_count
+ composers.size
+ end
+
+ def publishers_count
+ publishers.size
+ end
+
private
def publisher_percentages_add_up_to_100
diff --git a/app/models/talent_release.rb b/app/models/talent_release.rb
index 8ca4dbe..f507ba7 100644
--- a/app/models/talent_release.rb
+++ b/app/models/talent_release.rb
@@ -14,6 +14,13 @@ class TalentRelease < ApplicationRecord
include SecondGuardianPhotoable
include GuardianName
include SecondGuardianName
+ include CsvExportable
+
+ class << self
+ def custom_csv_exportable_headers
+ %i[name phone email]
+ end
+ end
composed_of :person_address,
class_name: "Address",
@@ -86,6 +93,14 @@ class TalentRelease < ApplicationRecord
person_name
end
+ def phone
+ person_phone
+ end
+
+ def email
+ person_email
+ end
+
def filename_suffix
"#{person_last_name} #{person_first_name}"
end
diff --git a/app/policies/contract_template_policy.rb b/app/policies/contract_template_policy.rb
index e6bb8d1..ca439b8 100644
--- a/app/policies/contract_template_policy.rb
+++ b/app/policies/contract_template_policy.rb
@@ -3,8 +3,10 @@ class ContractTemplatePolicy < ApplicationPolicy
def resolve
if user.account_manager?
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 })
+ else
+ scope.public_template.left_outer_joins(project: :project_memberships).where(project_memberships: { user_id: user.id })
end
end
end
diff --git a/app/views/contract_templates/_form.html.erb b/app/views/contract_templates/_form.html.erb
index ff40dfe..e2d164c 100644
--- a/app/views/contract_templates/_form.html.erb
+++ b/app/views/contract_templates/_form.html.erb
@@ -4,6 +4,10 @@
<%= 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.radio_button :accessibility, :public_template, label: "Public", wrapper_class: "mr-3" %>
+ <%= form.radio_button :accessibility, :private_template, label: "Private" %>
+
<%= form.number_field :fee, min:"0", max:"99999999", step: "0.01", prepend: "$", wrapper_class: "col-sm-6" %>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 4fd633d..290ef7e 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -50,6 +50,7 @@ en:
empty: Acquired Media Releases will appear here
table_headers:
file_infos_count: No. Files
+ name: Name
notes: Notes
signed_at: Date Signed
tags: Tags
@@ -151,6 +152,8 @@ en:
empty: Appearance Releases will appear here
imported_appearance_release_missing_attachment: Person photo or contract missing for imported appearance release
table_headers:
+ contact_info: Contact info
+ name: Name
notes: Notes
signed_at: Date Signed
tags: Tags
@@ -742,6 +745,7 @@ en:
empty: Location Releases will appear here
table_headers:
address: Address
+ name: Name
notes: Notes
signed_at: Date Signed
tags: Tags
@@ -776,6 +780,7 @@ en:
search: Search
empty: Material Releases will appear here
table_headers:
+ name: Name
notes: Notes
signed_at: Date Signed
tags: Tags
@@ -798,6 +803,9 @@ en:
empty: Medical releases will appear here
table_headers:
approved: Approved
+ approved?: Approved
+ contact_info: Contact info
+ name: Person name
notes: Notes
signed_at: Date Signed
tags: Tags
@@ -815,6 +823,8 @@ en:
search: Search
empty: Misc Releases will appear here
table_headers:
+ contact_info: Contact info
+ name: Person name
notes: Notes
signed_at: Date Signed
tags: Tags
@@ -849,6 +859,7 @@ en:
table_headers:
composers_count: No. Composers
file_infos_count: No. Files
+ name: Name
notes: Notes
publishers_count: No. Publishers
signed_at: Date Signed
@@ -1245,7 +1256,10 @@ en:
search: Search
empty: Talent Releases will appear here
table_headers:
+ email: Email
+ name: Name
notes: Notes
+ phone: Phone
signed_at: Date Signed
tags: Tags
new:
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 10d3be8..8c6711c 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -1,4 +1,14 @@
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:
attributes:
appearance_release:
@@ -41,6 +51,12 @@ es:
heading: Person Photo (ES)
index:
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:
imported_appearance_release_contract_name: Contrato Importado
imported_appearance_release_headshot_name: Retrato Importado
@@ -296,21 +312,57 @@ es:
form:
photos:
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:
form:
photos:
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:
custom_validation_errors:
question_answer_is_required: answer is required (ES)
index:
table_headers:
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:
actions:
review: Review (ES)
messages:
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:
appearance_releases:
create:
@@ -415,6 +467,14 @@ es:
heading: Second Guardian Photo (ES)
guardian_photo:
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:
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)
diff --git a/db/data_migrations/20200712192301_add_duration_to_broadcast_recordings.rb b/db/data_migrations/20200712192301_add_duration_to_broadcast_recordings.rb
new file mode 100644
index 0000000..35efee1
--- /dev/null
+++ b/db/data_migrations/20200712192301_add_duration_to_broadcast_recordings.rb
@@ -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
\ No newline at end of file
diff --git a/db/migrate/20200709120630_add_accessibility_to_contract_templates.rb b/db/migrate/20200709120630_add_accessibility_to_contract_templates.rb
new file mode 100644
index 0000000..9ac3dd7
--- /dev/null
+++ b/db/migrate/20200709120630_add_accessibility_to_contract_templates.rb
@@ -0,0 +1,5 @@
+class AddAccessibilityToContractTemplates < ActiveRecord::Migration[6.0]
+ def change
+ add_column :contract_templates, :accessibility, :integer, default: 0
+ end
+end
diff --git a/db/migrate/20200712181139_add_duration_to_broadcast_recordings.rb b/db/migrate/20200712181139_add_duration_to_broadcast_recordings.rb
new file mode 100644
index 0000000..d79b21a
--- /dev/null
+++ b/db/migrate/20200712181139_add_duration_to_broadcast_recordings.rb
@@ -0,0 +1,5 @@
+class AddDurationToBroadcastRecordings < ActiveRecord::Migration[6.0]
+ def change
+ add_column :broadcast_recordings, :duration, :float
+ end
+end
diff --git a/db/structure.sql b/db/structure.sql
index 616c0ac..ba4ce52 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -9,6 +9,20 @@ 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: -
--
@@ -494,7 +508,8 @@ CREATE TABLE public.broadcast_recordings (
asset_playback_uid character varying NOT NULL,
file_name character varying 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_13_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'),
('20200625144713'),
('20200702152130'),
-('20200707155717');
+('20200707155717'),
+('20200709120630'),
+('20200712181139');
diff --git a/spec/controllers/api/contract_templates_controller_spec.rb b/spec/controllers/api/contract_templates_controller_spec.rb
index 6124c3b..161d67f 100644
--- a/spec/controllers/api/contract_templates_controller_spec.rb
+++ b/spec/controllers/api/contract_templates_controller_spec.rb
@@ -30,6 +30,21 @@ RSpec.describe Api::ContractTemplatesController, type: :controller do
expect(response).to be_successful
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
private
diff --git a/spec/controllers/api/sync_controller_spec.rb b/spec/controllers/api/sync_controller_spec.rb
index 14b8de3..f34878a 100644
--- a/spec/controllers/api/sync_controller_spec.rb
+++ b/spec/controllers/api/sync_controller_spec.rb
@@ -127,9 +127,16 @@ RSpec.describe Api::SyncController, type: :controller do
get :index
medical_releases = attributes_for_type('medical_releases')
-
expect(medical_releases.first).to include('id')
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
private
@@ -149,6 +156,13 @@ RSpec.describe Api::SyncController, type: :controller do
create(:appearance_release, :minor_with_guardian_photo, project: project)
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
JSON.parse(response.body)
end
diff --git a/spec/factories/contract_templates.rb b/spec/factories/contract_templates.rb
index 8d90846..22583c4 100644
--- a/spec/factories/contract_templates.rb
+++ b/spec/factories/contract_templates.rb
@@ -7,6 +7,7 @@ FactoryBot.define do
body "This is a test contract template."
guardian_clause "Is the signer a minor?"
fee "$0.00"
+ accessibility "public_template"
trait :archived do
archived_at Time.zone.now
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 2f1b77a..1e9a73b 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -49,12 +49,18 @@ FactoryBot.define do
predefined_client_name "nat_geo"
end
- factory :project_with_contract_template do
+ factory :project_with_contract_template_public do
after(:build) do |project, _|
project.contract_templates << build(:contract_template, project: nil)
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
after(:build) do |project, _|
project.directories << build(:directory, project: nil, name: "Shared")
diff --git a/spec/jobs/generate_contracts_zip_job_spec.rb b/spec/jobs/generate_contracts_zip_job_spec.rb
index a438ae4..3d3ee5f 100644
--- a/spec/jobs/generate_contracts_zip_job_spec.rb
+++ b/spec/jobs/generate_contracts_zip_job_spec.rb
@@ -11,7 +11,7 @@ describe GenerateContractsZipJob do
dir = Rails.root.join("spec", "fixtures", "files")
files = ["contract.pdf", "AppearanceRelease.pdf"]
# 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(:build).and_yield(dir, files)
end
@@ -35,6 +35,38 @@ describe GenerateContractsZipJob do
expect(download.file).to be_attached
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
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_any_instance_of(ReleaseContractCollectionService).to receive(:build).and_raise(StandardError, "Contracts or contract templates not found")
end
-
+
it "updates status to 'failure' and sends user a notification" do
GenerateContractsZipJob.perform_now(project, download, "AppearanceRelease", project.appearance_releases.ids)
-
+
expect(download.status).to eq "failure"
expect(ProjectsChannel).to have_received(:broadcast_download_generation_update).with(download, I18n.t("contract_downloads.download.failure"))
end
@@ -56,6 +88,21 @@ describe GenerateContractsZipJob do
# Delete the file created in fixture.
# Or the tests will fail on next run due to already existing files in existing zip.
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
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 4210321..5df8155 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Project, type: :model do
describe "#import_contract_templates" 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)
expect {
diff --git a/spec/policies/contract_template_policy_spec.rb b/spec/policies/contract_template_policy_spec.rb
index 241ca38..f1055f4 100644
--- a/spec/policies/contract_template_policy_spec.rb
+++ b/spec/policies/contract_template_policy_spec.rb
@@ -75,14 +75,17 @@ describe ContractTemplatePolicy do
end
permissions ".scope" do
- let!(:member_project) do
- create(:project_with_contract_template, name: "Member Project", members: user, account: account)
+ let!(:member_project_public_template) do
+ 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
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
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
let(:account) { build(:account) }
@@ -93,7 +96,8 @@ describe ContractTemplatePolicy do
context "for an account manager" do
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.not_to include(outside_project.contract_templates.first) }
end
@@ -101,15 +105,17 @@ describe ContractTemplatePolicy do
context "for manager" do
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(outside_project.contract_templates.first) }
end
context "for associate" do
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(outside_project.contract_templates.first) }
end