def test_integrate_sources_with_crecord(dclient, admin_user, example_crecord): """ User can post source records and an empty crecord to the server and receive a crecord with the cases from the source record incorporated. """ dclient.force_authenticate(user=admin_user) docket = os.listdir("tests/data/dockets/")[0] with open(f"tests/data/dockets/{docket}", "rb") as d: doc_1 = SourceRecord.objects.create( caption="Hello v. World", docket_num="MC-1234", court=SourceRecord.Courts.CP, url="https://abc.def", record_type=SourceRecord.RecTypes.DOCKET_PDF, file=File(d), owner=admin_user, ) summary = os.listdir("tests/data/summaries")[0] with open(f"tests/data/summaries/{summary}", "rb") as s: doc_2 = SourceRecord.objects.create( caption="Hello v. Goodbye", docket_num="MC-1235", court=SourceRecord.Courts.MDJ, url="https://def.ghi", record_type=SourceRecord.RecTypes.SUMMARY_PDF, file=File(s), owner=admin_user, ) # when sent to api, serialized document data won't have a file included. # The request is asking to do stuff using the file that is on the server. doc_1_data = SourceRecordSerializer(doc_1).data # doc_1_data.pop("file") doc_2_data = SourceRecordSerializer(doc_2).data # doc_2_data.pop("file") source_records = [doc_1_data, doc_2_data] data = { "crecord": CRecordSerializer(example_crecord).data, "source_records": source_records, } resp = dclient.put("/api/record/cases/", data=data) assert resp.status_code == 200 assert "crecord" in resp.data assert "source_records" in resp.data # the response source_records list might include new source records, so will be at # least as long as the original source records list. assert len(resp.data["source_records"]) >= len(source_records) try: CRecord.from_dict(resp.data["crecord"]) except Exception as err: pytest.fail(err)
def post(self, request): """ Analyze a Criminal Record for expungeable and sealable cases and charges. POST body should be json-endoded CRecord object. Return, if not an error, will be a json-encoded Decision that explains the expungements and sealings that can be generated for this record. """ try: serializer = CRecordSerializer(data=request.data) if serializer.is_valid(): rec = CRecord.from_dict(serializer.validated_data) analysis = (Analysis(rec).rule(expunge_deceased).rule( expunge_over_70).rule(expunge_nonconvictions).rule( expunge_summary_convictions).rule(seal_convictions)) return Response(to_serializable(analysis)) return Response( {"validation_errors": serializer.errors}, status=status.HTTP_500_INTERNAL_SERVER_ERROR, ) except Exception as err: logger.error(err) return Response("Something went wrong", status=status.HTTP_400_BAD_REQUEST)
def test_integrate_sources_with_crecord(dclient, admin_user, example_crecord): dclient.force_authenticate(user=admin_user) docket = os.listdir("tests/data/dockets/")[0] with open(f"tests/data/dockets/{docket}", "rb") as d: doc_1 = SourceRecord.objects.create( caption="Hello v. World", docket_num="MC-1234", court=SourceRecord.Courts.CP, url="https://abc.def", record_type=SourceRecord.RecTypes.DOCKET_PDF, file=File(d), owner=admin_user, ) summary = os.listdir("tests/data/summaries")[0] with open(f"tests/data/summaries/{summary}", "rb") as s: doc_2 = SourceRecord.objects.create( caption="Hello v. Goodbye", docket_num="MC-1235", court=SourceRecord.Courts.MDJ, url="https://def.ghi", record_type=SourceRecord.RecTypes.SUMMARY_PDF, file=File(s), owner=admin_user, ) # when sent to api, serialized document data won't have a file included. # The request is asking to do stuff using the file that is on the server. doc_1_data = SourceRecordSerializer(doc_1).data doc_1_data.pop("file") doc_2_data = SourceRecordSerializer(doc_2).data doc_2_data.pop("file") data = { "crecord": CRecordSerializer(example_crecord).data, "source_records": [doc_1_data, doc_2_data] } resp = dclient.put("/record/sources/", data=data) assert resp.status_code == 200 assert "crecord" in resp.data try: CRecord.from_dict(resp.data["crecord"]) except Exception as err: pytest.fail(err)
def put(self, request, *args, **kwargs): """ Accept a CRecord and a set of SourceRecords. Incorporate the information that the SourceRecords contain into the CRecord. TODO this should replace FileUpload view. """ try: serializer = IntegrateSourcesSerializer(data=request.data) if serializer.is_valid(): crecord = CRecord.from_dict( serializer.validated_data["crecord"]) for source_record_data in serializer.validated_data[ "source_records"]: source_record = SourceRecord.objects.get( id=source_record_data["id"]) if source_record.record_type == SourceRecord.RecTypes.SUMMARY_PDF: summary = parse_pdf(source_record.file.path) crecord.add_summary( summary, case_merge_strategy="overwrite_old", override_person=True) elif source_record.record_type == SourceRecord.RecTypes.DOCKET_PDF: docket, errs = Docket.from_pdf(source_record.file.path) crecord.add_docket(docket) else: logger.error( f"Cannot parse a source record with type {source_record.record_type}" ) return Response({'crecord': CRecordSerializer(crecord).data}, status=status.HTTP_200_OK) else: return Response({"errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST) except Exception as err: return Response({"errors": [str(err)]}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
def test_from_dict(example_crecord): serialized = to_serializable(example_crecord) crec2 = CRecord.from_dict(serialized) assert example_crecord.person.last_name == crec2.person.last_name
def put(self, request): """ Accept a CRecord and a set of SourceRecords. Parse the SourceRecords, and incorporate the information that the SourceRecords contain into the CRecord. Two api endpoints of the Django app interact with RecordLib. This one accepts a serialzed crecord and a list of sourcerecords. It attempts to parse each source_record, and then integrate the sourcerecords into the crecord. TODO IntegrateCRecordWithSources should communicate failures better. """ try: serializer = IntegrateSourcesSerializer(data=request.data) if serializer.is_valid(): nonfatal_errors = [] crecord = CRecord.from_dict( serializer.validated_data["crecord"]) source_records = [] # Find the SourceRecords in the database that have been sent in this request, # or if these are new source records, download the files they point to. # TODO this probably doesn't handle a request with a new SoureRecord missing a URL. for source_record_data in serializer.validated_data[ "source_records"]: try: source_records.append( SourceRecord.objects.get( id=source_record_data["id"])) except Exception: # create this source record in the database, if it is new. source_rec = SourceRecord(**source_record_data, owner=request.user) source_rec.save() # also download it to the server. download_service.source_records([source_rec]) source_records.append(source_rec) # Parse the uploaded source records, collecting RecordLib.SourceRecord objects. # These objects are parsing the records and figuring out case information in the SourceRecords. # For any source records that are summaries, find out if the summary describes cases that aren't also # docket source records. Search CPCMS for those, add the missing dockets to the list of source records. # First, parse the dockets. # Then we'll parse the summaries to find out if there are cases the summaries mention which the dockets do not. docket_source_records = [ sr for sr in source_records if sr.record_type == SourceRecord.RecTypes.DOCKET_PDF ] crecord, nonfatal_errors = integrate_dockets( crecord, docket_source_records, nonfatal_errors) # Now attempt to parse summary records. Check the cases in each summary record to see if we have a docket for this case yet. # If we dont yet have a docket for this case, fetch it, parse it, integrate it into the CRecord. summary_source_records = [ sr for sr in source_records if sr.record_type == SourceRecord.RecTypes.SUMMARY_PDF ] crecord, new_source_records, nonfatal_errors = integrate_summaries( crecord, summary_source_records, docket_source_records, nonfatal_errors, owner=request.user, ) source_records += new_source_records return Response( { "crecord": CRecordSerializer(crecord).data, "source_records": SourceRecordSerializer(source_records, many=True).data, "errors": nonfatal_errors, }, status=status.HTTP_200_OK, ) return Response({"errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST) except Exception as err: return Response({"errors": [str(err)]}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)