sul-dlss/dor-services-app

View on GitHub
app/services/refresh_description_from_catalog.rb

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
# frozen_string_literal: true

# Fetch descriptive metadata from catalog and update description.
class RefreshDescriptionFromCatalog
  include Dry::Monads[:result]

  Result = Struct.new('Result', :description_props, :mods_ng_xml)

  # @param [Cocina::Models::DRO|Collection|APO|Agreement|RequestDRO|RequestCollection|RequestAPO|RequestAgreement] cocina_object to refresh
  # @param [string] druid
  # @return [Dry::Monads::Results] returns Failure if there was no refreshable catalog link or barcode, otherwise Success (Result with description_props and mods)
  def self.run(cocina_object:, druid:, use_barcode: false)
    new(cocina_object:, druid:, use_barcode:).run
  end

  def initialize(cocina_object:, druid:, use_barcode:)
    @cocina_object = cocina_object
    @druid = druid
    @use_barcode = use_barcode
  end

  # @return [Dry::Monads::Results] Returns Failure if description unchanged (e.g., no refreshable identifiers), otherwise Success (Result with description_props and mods)
  # @raises Catalog::MarcService::MarcServiceError
  def run
    # Admin policies don't have identification.
    return Failure() if cocina_object.admin_policy?
    # No identifiers to refresh from.
    return Failure() unless identifiers.any?

    return Failure() if marc_service.mods.nil?

    description_props = Cocina::Models::Mapping::FromMods::Description.props(mods: marc_service.mods_ng, druid:, label: cocina_object.label)
    return Failure() if description_props.nil?

    Success(Result.new(description_props, marc_service.mods_ng))
  end

  private

  attr_reader :cocina_object, :druid, :use_barcode

  # @raises Catalog::MarcService::MarcServiceError
  def marc_service
    @marc_service ||= Catalog::MarcService.new(**identifiers)
  end

  def identifiers
    {
      folio_instance_hrid:,
      barcode:
    }.compact
  end

  def folio_instance_hrid
    Array(cocina_object.identification&.catalogLinks).find { |link| link.catalog == 'folio' && link.refresh }&.catalogRecordId
  end

  def barcode
    return nil unless use_barcode

    cocina_object.identification.try(:barcode)
  end
end