Skip to content

Commit

Permalink
Retrieves unmodified MARC record before updating
Browse files Browse the repository at this point in the history
  • Loading branch information
jermnelson committed Apr 16, 2024
1 parent c54dd0e commit 7fa1b52
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 60 deletions.
29 changes: 20 additions & 9 deletions libsys_airflow/plugins/data_exports/oclc_api.py
Expand Up @@ -66,6 +66,12 @@ def __generate_snapshot__(self) -> None:
post_result.raise_for_status()
self.snapshot = snapshot_uuid

def __get_srs_record__(self, srs_uuid: str) -> pymarc.Record:
marc_json = self.folio_client.folio_get(f"/source-storage/records/{srs_uuid}")
marc_json_handler = pymarc.JSONHandler()
marc_json_handler.elements(marc_json)
return marc_json_handler.records[0]

def __read_marc_files__(self, marc_files: list) -> list:
records = []
for marc_file in marc_files:
Expand All @@ -85,13 +91,12 @@ def __srs_uuid__(self, record) -> Union[str, None]:
logger.error("Record Missing SRS uuid")
return srs_uuid

def __update_035__(
self, oclc_put_result: bytes, record: pymarc.Record, srs_uuid: str
) -> bool:
def __update_035__(self, oclc_put_result: bytes, srs_uuid: str) -> bool:
"""
Extracts 035 field with new OCLC number and adds to existing MARC21
record
"""
record = self.__get_srs_record__(srs_uuid)
oclc_record = pymarc.Record(data=oclc_put_result) # type: ignore
fields_035 = oclc_record.get_fields('035')
for field in fields_035:
Expand All @@ -101,12 +106,11 @@ def __update_035__(
break
return self.__put_folio_record__(srs_uuid, record)

def __update_oclc_number__(
self, record: pymarc.Record, control_number: str, srs_uuid: str
) -> bool:
def __update_oclc_number__(self, control_number: str, srs_uuid: str) -> bool:
"""
Updates 035 field if control_number has changed
"""
record = self.__get_srs_record__(srs_uuid)
for field in record.get_fields('035'):
for subfield in field.get_subfields("a"):
if control_number in subfield:
Expand All @@ -119,6 +123,12 @@ def __update_oclc_number__(
record.add_ordered_field(new_035)
return self.__put_folio_record__(srs_uuid, record)

def __pre_process__(self, record: pymarc.Record) -> bytes:
"""
Pre-processes MARC record specifically for OCLC
"""
return record.as_marc21()

def __put_folio_record__(self, srs_uuid: str, record: pymarc.Record) -> bool:
"""
Updates FOLIO SRS with updated MARC record with new OCLC Number
Expand Down Expand Up @@ -157,7 +167,8 @@ def new(self, marc_files: List[str]) -> dict:
continue
with MetadataSession(authorization=self.oclc_token) as session:
try:
marc21 = record.as_marc21()
marc21 = self.__pre_process__(record)

session.bib_validate(
record=marc21,
recordFormat="application/marc",
Expand All @@ -167,7 +178,7 @@ def new(self, marc_files: List[str]) -> dict:
record=marc21,
recordFormat="application/marc",
)
if self.__update_035__(new_record.text, record, srs_uuid): # type: ignore
if self.__update_035__(new_record.text, srs_uuid): # type: ignore
output['success'].append(srs_uuid)
else:
output['failures'].append(srs_uuid)
Expand Down Expand Up @@ -196,7 +207,7 @@ def update(self, marc_files: List[str]):
output['failures'].append(srs_uuid)
continue
if self.__update_oclc_number__(
record, response.json()['controlNumber'], srs_uuid
response.json()['controlNumber'], srs_uuid
):
output['success'].append(srs_uuid)
else:
Expand Down
112 changes: 61 additions & 51 deletions tests/data_exports/test_oclc_api.py
@@ -1,3 +1,4 @@
import json
import httpx
import pymarc
import pytest
Expand All @@ -9,6 +10,47 @@
from libsys_airflow.plugins.data_exports import oclc_api


def sample_marc_records():
sample = []
marc_record = pymarc.Record()
marc_record.add_field(
pymarc.Field(
tag='999',
indicators=['f', 'f'],
subfields=[
pymarc.Subfield(code='s', value='08ca5a68-241a-4a5f-89b9-5af5603981ad')
],
)
)
sample.append(marc_record)
no_srs_record = pymarc.Record()
no_srs_record.add_field(
pymarc.Field(
tag='245',
indicators=[' ', ' '],
subfields=[pymarc.Subfield(code='a', value='Much Ado about Something')],
)
)
sample.append(no_srs_record)
another_record = pymarc.Record()
another_record.add_field(
pymarc.Field(
tag='035',
indicators=['', ''],
subfields=[pymarc.Subfield(code='a', value='(OCoLC)445667')],
),
pymarc.Field(
tag='999',
indicators=['f', 'f'],
subfields=[
pymarc.Subfield(code='s', value='d63085c0-cab6-4bdd-95e8-d53696919ac1')
],
),
)
sample.append(another_record)
return sample


def mock_metadata_session(authorization=None):
mock_response = MagicMock()

Expand Down Expand Up @@ -93,9 +135,20 @@ def mock_response(request):


def mock_folio_client(mocker):
sample_marc = sample_marc_records()

def mock_folio_get(*args, **kwargs):
output = {}
if args[0].endswith("08ca5a68-241a-4a5f-89b9-5af5603981ad"):
output = json.loads(sample_marc[0].as_json())
if args[0].endswith("d63085c0-cab6-4bdd-95e8-d53696919ac1"):
output = json.loads(sample_marc[2].as_json())
return output

mock = mocker
mock.okapi_headers = {}
mock.okapi_url = "https://okapi.stanford.edu/"
mock.folio_get = mock_folio_get
return mock


Expand Down Expand Up @@ -142,26 +195,7 @@ def test_oclc_api_class_no_new_records(mock_oclc_api, caplog):


def test_oclc_api_class_new_records(tmp_path, mock_oclc_api):

marc_record = pymarc.Record()
marc_record.add_field(
pymarc.Field(
tag='999',
indicators=['f', 'f'],
subfields=[
pymarc.Subfield(code='s', value='08ca5a68-241a-4a5f-89b9-5af5603981ad')
],
)
)

no_srs_record = pymarc.Record()
no_srs_record.add_field(
pymarc.Field(
tag='245',
indicators=[' ', ' '],
subfields=[pymarc.Subfield(code='a', value='Much Ado about Something')],
)
)
marc_record, no_srs_record, _ = sample_marc_records()
marc_file = tmp_path / "202403273-STF-new.mrc"

with marc_file.open('wb') as fo:
Expand All @@ -185,28 +219,12 @@ def test_oclc_api_class_new_records(tmp_path, mock_oclc_api):


def test_oclc_api_class_updated_records(tmp_path, mock_oclc_api):
marc_record = pymarc.Record()
marc_record.add_field(
marc_record, no_srs_record, _ = sample_marc_records()
marc_record.add_ordered_field(
pymarc.Field(
tag='035',
indicators=['', ''],
subfields=[pymarc.Subfield(code='a', value='(OCoLC-M)on455677')],
),
pymarc.Field(
tag='999',
indicators=['f', 'f'],
subfields=[
pymarc.Subfield(code='s', value='ea5b38dc-8f96-45de-8306-a2dd673716d5')
],
),
)

no_srs_record = pymarc.Record()
no_srs_record.add_field(
pymarc.Field(
tag='245',
indicators=[' ', ' '],
subfields=[pymarc.Subfield(code='a', value='Much Ado about Something')],
)
)

Expand All @@ -224,7 +242,7 @@ def test_oclc_api_class_updated_records(tmp_path, mock_oclc_api):

updated_result = oclc_api_instance.update([str(marc_file.absolute())])

assert updated_result['success'] == ['ea5b38dc-8f96-45de-8306-a2dd673716d5']
assert updated_result['success'] == ['08ca5a68-241a-4a5f-89b9-5af5603981ad']
assert updated_result['failures'] == []


Expand Down Expand Up @@ -281,16 +299,6 @@ def test_failed_oclc_new_record(tmp_path, mock_oclc_api):


def test_bad_srs_put_in_new_context(tmp_path, mock_oclc_api):
record = pymarc.Record()
record.add_field(
pymarc.Field(
tag='999',
indicators=['f', 'f'],
subfields=[
pymarc.Subfield(code='s', value='d63085c0-cab6-4bdd-95e8-d53696919ac1')
],
)
)

oclc_api_instance = oclc_api.OCLCAPIWrapper(
client_id="EDIoHuhLbdRvOHDjpEBtcEnBHneNtLUDiPRYtAqfTlpOThrxzUwHDUjMGEakoIJSObKpICwsmYZlmpYK",
Expand All @@ -301,7 +309,7 @@ def test_bad_srs_put_in_new_context(tmp_path, mock_oclc_api):

with marc_file.open('wb+') as fo:
marc_writer = pymarc.MARCWriter(fo)
marc_writer.write(record)
marc_writer.write(sample_marc_records()[2])

new_results = oclc_api_instance.new([str(marc_file.absolute())])

Expand Down Expand Up @@ -408,4 +416,6 @@ def test_already_exists_control_number(tmp_path, mock_oclc_api):
secret="c867b1dd75e6490f99d1cd1c9252ef22",
)

assert oclc_api_instance.__update_oclc_number__(marc_record, '445667', '')
assert oclc_api_instance.__update_oclc_number__(
'445667', 'd63085c0-cab6-4bdd-95e8-d53696919ac1'
)

0 comments on commit 7fa1b52

Please sign in to comment.