2024-09-10 21:09:23 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require 'caxlsx'
|
|
|
|
|
|
|
|
module StorageLocations
|
|
|
|
class ImportService
|
|
|
|
def initialize(storage_location, file, user)
|
|
|
|
@storage_location = storage_location
|
2024-09-13 19:43:45 +08:00
|
|
|
@assigned_count = 0
|
|
|
|
@unassigned_count = 0
|
|
|
|
@updated_count = 0
|
|
|
|
@sheet = SpreadsheetParser.open_spreadsheet(file)
|
2024-09-10 21:09:23 +08:00
|
|
|
@user = user
|
|
|
|
end
|
|
|
|
|
|
|
|
def import_items
|
2024-09-13 19:43:45 +08:00
|
|
|
@rows = SpreadsheetParser.spreadsheet_enumerator(@sheet).reject { |r| r.all?(&:blank?) }
|
2024-09-10 21:09:23 +08:00
|
|
|
|
|
|
|
# Check if the file has proper headers
|
2024-09-13 19:43:45 +08:00
|
|
|
header = SpreadsheetParser.parse_row(@rows[0], @sheet)
|
2024-09-10 21:09:23 +08:00
|
|
|
return { status: :error, message: I18n.t('storage_locations.show.import_modal.errors.invalid_structure') } unless header[0] == 'Box position' && header[1] == 'Item ID'
|
|
|
|
|
2024-09-13 19:43:45 +08:00
|
|
|
parse_rows!
|
2024-09-10 21:09:23 +08:00
|
|
|
|
|
|
|
# Check duplicate positions in the file
|
2024-09-13 19:43:45 +08:00
|
|
|
if @storage_location.with_grid? && @rows.pluck(:position).uniq.length != @rows.length
|
2024-09-10 21:09:23 +08:00
|
|
|
return { status: :error, message: I18n.t('storage_locations.show.import_modal.errors.invalid_position') }
|
|
|
|
end
|
|
|
|
|
|
|
|
ActiveRecord::Base.transaction do
|
2024-09-13 19:43:45 +08:00
|
|
|
unassign_repository_rows!
|
2024-09-10 21:09:23 +08:00
|
|
|
|
2024-09-13 19:43:45 +08:00
|
|
|
@rows.each do |row|
|
|
|
|
if @storage_location.with_grid? && !position_valid?(row[:position])
|
|
|
|
@error_message = I18n.t('storage_locations.show.import_modal.errors.invalid_position')
|
|
|
|
raise ActiveRecord::RecordInvalid
|
2024-09-10 21:09:23 +08:00
|
|
|
end
|
|
|
|
|
2024-09-13 19:43:45 +08:00
|
|
|
unless RepositoryRow.exists?(row[:repository_row_id])
|
|
|
|
@error_message = I18n.t('storage_locations.show.import_modal.errors.invalid_item', row_id: row[:repository_row_id])
|
2024-09-10 21:09:23 +08:00
|
|
|
raise ActiveRecord::RecordNotFound
|
|
|
|
end
|
|
|
|
|
2024-09-13 19:43:45 +08:00
|
|
|
import_row!(row)
|
2024-09-10 21:09:23 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-09-13 19:43:45 +08:00
|
|
|
{ status: :ok, assigned_count: @assigned_count, unassigned_count: @unassigned_count, updated_count: @updated_count }
|
|
|
|
rescue ActiveRecord::RecordNotFound, ActiveRecord::RecordInvalid
|
|
|
|
{ status: :error, message: @error_message }
|
2024-09-10 21:09:23 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2024-09-13 19:43:45 +08:00
|
|
|
def parse_rows!
|
|
|
|
# Remove first row
|
|
|
|
@rows.shift
|
|
|
|
|
|
|
|
@rows.map! do |r|
|
|
|
|
row = SpreadsheetParser.parse_row(r, @sheet)
|
|
|
|
{
|
|
|
|
position: convert_position_letter_to_number(row[0]),
|
|
|
|
repository_row_id: row[1].gsub('IT', '').to_i
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
2024-09-10 21:09:23 +08:00
|
|
|
|
2024-09-13 19:43:45 +08:00
|
|
|
def import_row!(row)
|
|
|
|
storage_location_repository_row =
|
|
|
|
@storage_location.storage_location_repository_rows
|
|
|
|
.find_or_initialize_by(
|
|
|
|
repository_row_id: row[:repository_row_id],
|
|
|
|
metadata: { position: row[:position] }
|
|
|
|
)
|
2024-09-10 21:09:23 +08:00
|
|
|
|
2024-09-13 19:43:45 +08:00
|
|
|
@assigned_count += 1 if storage_location_repository_row.new_record?
|
|
|
|
|
|
|
|
storage_location_repository_row.update!(
|
|
|
|
repository_row_id: row[:repository_row_id],
|
|
|
|
created_by: storage_location_repository_row.created_by || @user
|
|
|
|
)
|
|
|
|
end
|
|
|
|
|
|
|
|
def unassign_repository_rows!
|
|
|
|
@storage_location.storage_location_repository_rows.each do |s|
|
|
|
|
if @rows.exclude?({ position: s.metadata['position'], repository_row_id: s.repository_row_id })
|
|
|
|
@unassigned_count += 1
|
|
|
|
s.discard
|
|
|
|
end
|
|
|
|
end
|
2024-09-10 21:09:23 +08:00
|
|
|
end
|
|
|
|
|
2024-09-13 19:43:45 +08:00
|
|
|
def position_valid?(position)
|
|
|
|
position[0].to_i <= @storage_location.grid_size[0].to_i && position[1].to_i <= @storage_location.grid_size[1].to_i
|
|
|
|
end
|
2024-09-10 21:09:23 +08:00
|
|
|
|
2024-09-13 19:43:45 +08:00
|
|
|
def convert_position_letter_to_number(position)
|
2024-09-10 21:09:23 +08:00
|
|
|
return unless position
|
|
|
|
|
2024-09-13 19:43:45 +08:00
|
|
|
column_letter = position[0]
|
2024-09-10 21:09:23 +08:00
|
|
|
row_number = position[1]
|
|
|
|
|
2024-09-13 19:43:45 +08:00
|
|
|
[column_letter.ord - 64, row_number.to_i]
|
2024-09-10 21:09:23 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|