diff --git a/app/models/dataset_record/darwin_core/occurrence.rb b/app/models/dataset_record/darwin_core/occurrence.rb index 583ccb5f06..9a9f4be8b8 100644 --- a/app/models/dataset_record/darwin_core/occurrence.rb +++ b/app/models/dataset_record/darwin_core/occurrence.rb @@ -52,18 +52,11 @@ def import }) - ### Create collecting event - #end_date = Date.ordinal(get_field_value("year").to_i, get_field_value("endDayOfYear").to_i) + ### Parse Event class fields + attributes = parse_event_class #TODO: If all attributes are equal assume it is the same event and share it with other specimens? CollectingEvent.create!({ - verbatim_date: get_field_value("verbatimEventDate"), - start_date_year: get_field_value("year"), - start_date_month: get_field_value("month"), - start_date_day: get_field_value("day"), - #end_date_year: end_date.year, - #end_date_month: end_date.month, - #end_date_day: end_date.day, collection_objects: [specimen], with_verbatim_data_georeference: true, verbatim_latitude: get_field_value("decimalLatitude"), @@ -71,7 +64,7 @@ def import verbatim_datum: get_field_value("geodeticDatum"), verbatim_locality: get_field_value("locality"), no_dwc_occurrence: true - }) + }.merge!(attributes[:collecting_event])) self.metadata["imported_objects"] = { collection_object: { id: specimen.id } } self.status = "Imported" @@ -110,10 +103,26 @@ def get_fields_mapping end def get_field_value(field_name) - index = get_fields_mapping[field_name] + index = get_fields_mapping[field_name.to_s] data_fields[index]&.dig("value") if index end + def get_integer_field_value(field_name) + value = get_field_value(field_name) + + unless value.blank? + begin + value = Integer(value) + rescue + raise DarwinCore::InvalidData.new({ field_name => ["'#{value} is not a valid integer value"] }) + end + else + value = nil + end + + value + end + def parse_identifiedBy DwcAgent.parse(get_field_value("identifiedBy")).map! do |name| { @@ -123,7 +132,110 @@ def parse_identifiedBy prefix: name.title || name.appellation } end + end + def set_hash_val(hsh, key, value) + hsh[key] = value unless value.nil? end + def parse_event_class + collecting_event = { } + + # eventID: [Not mapped] + + # parentEventID: [Not mapped] + + # fieldNumber: verbatim_trip_identifier + set_hash_val(collecting_event, :verbatim_trip_identifier, get_field_value(:fieldNumber)) + + eventDate = get_field_value(:eventDate) + + begin + start_date = DateTime.iso8601(eventDate) if eventDate + rescue Date::Error + raise DarwinCore::InvalidData.new({ "eventDate": ["Invalid date. Please make sure it conforms to ISO 8601"] }) + end + + year = get_integer_field_value(:year) + month = get_integer_field_value(:month) + day = get_integer_field_value(:day) + startDayOfYear = get_integer_field_value(:startDayOfYear) + + raise DarwinCore::InvalidData.new({ "eventDate": ["Conflicting values. Please check year, month, and day match eventDate"] }) if start_date && + (year && start_date.year != year || month && start_date.month != month || day && start_date.day != day) + + year ||= start_date&.year + month ||= start_date&.month + day ||= start_date&.day + + if startDayOfYear + raise DarwinCore::InvalidData.new({ "startDayOfYear": ["Missing year value"] }) if year.nil? || eventDate.nil? + + begin + ordinal = Date.ordinal(year, startDayOfYear) + rescue Date::Error + raise DarwinCore::InvalidData.new({ "startDayOfYear": ["Out of range. Please also check year field"] }) + end + + if month && ordinal.month != month || day && ordinal.day != day + raise DarwinCore::InvalidData.new({ "startDayOfYear": ["Month and/or day of the event date do not match"] }) + end + + month ||= ordinal.month + day ||= ordinal.day + end + + # eventDate | (year+month+day) | (year+startDayOfYear): start_date_* + set_hash_val(collecting_event, :start_date_year, year) + set_hash_val(collecting_event, :start_date_month, month) + set_hash_val(collecting_event, :start_date_day, day) + + # eventTime: time_start_* + /(?\d+)(:(?\d+))?(:(?\d+))?/ =~ get_field_value(:eventTime) + set_hash_val(collecting_event, :time_start_hour, hour) + set_hash_val(collecting_event, :time_start_minute, minute) + set_hash_val(collecting_event, :time_start_second, second) + + endDayOfYear = get_integer_field_value(:endDayOfYear) + + if endDayOfYear + raise DarwinCore::InvalidData.new({ "endDayOfYear": ["Missing year value"] }) if year.nil? || eventDate.nil? + + begin + ordinal = Date.ordinal(year, endDayOfYear) + rescue Date::Error + raise DarwinCore::InvalidData.new({ "endDayOfYear": ["Out of range. Please also check year field"] }) + end + + month = ordinal.month + day = ordinal.day + end + + # endDayOfYear: end_date_* ## TODO: Might need to support date ranges for eventDate as this field does not make possible to end next year + set_hash_val(collecting_event, :end_date_year, year) + set_hash_val(collecting_event, :end_date_month, month) + set_hash_val(collecting_event, :end_date_day, day) + + # verbatimEventDate: verbatim_date + set_hash_val(collecting_event, :verbatimEventDate, get_field_value(:verbatim_date)) + + # habitat: verbatim_habitat + set_hash_val(collecting_event, :verbatim_habitat, get_field_value(:habitat)) + + # samplingProtocol: verbatim_method + set_hash_val(collecting_event, :verbatim_method, get_field_value(:samplingProtocol)) + + # sampleSizeValue: [Not mapped] + + # sampleSizeUnit: [Not mapped] + + # samplingEffort: [Not mapped] + + # fieldNotes: field_notes + set_hash_val(collecting_event, :field_notes, get_field_value(:fieldNotes)) + + # eventRemarks: Maybe field_notes (concatenated with fieldNotes) + + { collecting_event: collecting_event } + end end