Sync of the branch

This commit is contained in:
Senad Uka
2020-06-01 18:59:15 +02:00
committed by bilal
parent 9a540efc74
commit dafef462b2
11 changed files with 199 additions and 52 deletions

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
filtered_attachments = filter_attachments attachments
MatchAppearanceReleasesJob.perform_later(@project, filtered_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,18 @@ class AppearanceReleaseImportsController < ApplicationController
params.require(:attachments)
end
def build_appearance_release(params = {})
authorize appearance_releases.build(params)
def filter_attachments(attachments)
filtered_attachments = []
attachments.each do |attachment|
blob = ActiveStorage::Blob.find_signed attachment
next if blob.nil?
extension = blob.filename.extension
filtered_attachments << attachment if blob.image? || extension == 'pdf'
end
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

@@ -0,0 +1,79 @@
# frozen_string_literal: true
class MatchAppearanceReleasesJob < ApplicationJob
queue_as :default
def perform(project, attachments)
matching_request = MatchingRequest.create project: project, attachments: attachments
payload = { request_id: matching_request.id, bucket: aws_bucket_name, files: attachments}
response = BrayniacAI::AppearanceReleaseMatching.match_attachments payload
matches = response[:matches] || []
errors = response[:errors] || []
handle_matches matches, project
handle_errors errors
end
private
def handle_matches(matches, project)
matches.each do |match|
contract = match[:contract]
headshot = match[:headshot]
identifier = match[:identifier]
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 handle_errors(errors)
logger.error "== MATCHING ERRORS ==" unless errors.empty?
errors.each do |error|
logger.error "[#{error[:error_code]}] #{error[:file]}"
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
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

@@ -0,0 +1,7 @@
# frozen_string_literal: true
class MatchingRequest < ApplicationRecord
include Attachable
belongs_to :project
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

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)

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

@@ -3,6 +3,7 @@ require_relative "./brayniac_ai/aws_request_signing"
require_relative "./brayniac_ai/aws_signed_connection"
require_relative "./brayniac_ai/base"
require_relative "./brayniac_ai/appearance_release_matching"
require_relative "./brayniac_ai/audio_recognition"
require_relative "./brayniac_ai/collection"
require_relative "./brayniac_ai/document_analysis"

View File

@@ -0,0 +1,64 @@
# frozen_string_literal: true
module BrayniacAI
class AppearanceReleaseMatching
class << self
def match_attachments(request_data)
# TODO: Send request with request_data and receive real response
mock_response request_data
end
private
def mock_response(request_data)
attachments = request_data[:files]
pdfs = []
images = []
matches = []
errors = []
# Use first file for the error entry
first_attachment = attachments.shift
unless first_attachment.nil?
errors << { file: first_attachment, error_code: 1 }
end
attachments.each do |attachment|
blob = ActiveStorage::Blob.find_signed attachment
next if blob.nil?
if blob.image?
images << attachment
else
pdfs << attachment
end
end
# Create pairs of matches and single headshot/contract after pairs are exhausted
more_pdfs = pdfs.length > images.length
pairs = more_pdfs ? pdfs.zip(images) : images.zip(pdfs)
pairs.each do |pair_element1, pair_element2|
if more_pdfs
pdf = pair_element1
image = pair_element2
else
pdf = pair_element2
image = pair_element1
end
if pdf.nil? || image.nil?
matches << { headshot: image } if pdf.nil?
matches << { contract: pdf } if image.nil?
else
matches << { headshot: image, contract: pdf, identifier: '' }
end
end
{
request_id: request_data[:request_id],
matches: matches,
errors: errors
}
end
end
end
end

View File

@@ -148,6 +148,7 @@ feature 'User managing appearance releases' do
end
scenario 'importing a releases works when image is selected', js: true do
skip 'Will be changed according to new matching capability'
visit project_appearance_releases_path(project)
expect(page).to have_content submit_create_button
@@ -160,6 +161,7 @@ feature 'User managing appearance releases' do
end
scenario 'importing a releases works when pdf is selected', js: true do
skip 'Will be changed according to new matching capability'
visit project_appearance_releases_path(project)
expect(page).to have_content submit_create_button
@@ -172,6 +174,7 @@ feature 'User managing appearance releases' do
end
scenario 'importing a releases fails when file other than image or pdf is selected', js: true do
skip 'Will be changed according to new matching capability'
visit project_appearance_releases_path(project)
expect(page).to have_content submit_create_button