def test_process_other_id_records(app, mocker):
    """Test create or update researcher other id."""
    mocker.patch("orcid_hub.utils.send_email", send_mail_mock)
    mocker.patch("orcid_api.MemberAPIV20Api.create_external_identifier",
                 create_or_update_fund_mock)
    mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record",
                 return_value=get_profile())
    org = app.data["org"]
    u = User.create(email="*****@*****.**",
                    name="TEST USER",
                    roles=Role.RESEARCHER,
                    orcid="12344",
                    confirmed=True,
                    organisation=org)

    UserOrg.create(user=u, org=org)

    t = Task.create(org=org,
                    filename="xyz.json",
                    created_by=u,
                    updated_by=u,
                    task_type=TaskType.OTHER_ID)

    OtherIdRecord.create(task=t,
                         type="grant_number",
                         value="xyz",
                         url="https://xyz.com",
                         relationship="SELF",
                         is_active=True,
                         status="email sent",
                         first_name="Test",
                         last_name="Test",
                         email="*****@*****.**",
                         visibility="PUBLIC",
                         display_index=1)

    UserInvitation.create(invitee=u,
                          inviter=u,
                          org=org,
                          task=t,
                          email="*****@*****.**",
                          token="xyztoken")

    OrcidToken.create(user=u,
                      org=org,
                      scopes="/read-limited,/person/update",
                      access_token="Test_token")
    utils.process_other_id_records()
    record = OtherIdRecord.get(email="*****@*****.**")
    assert 12399 == record.put_code
    assert "12344" == record.orcid
def test_sync_profile(app, mocker):
    """Test sync_profile."""
    mocker.patch("orcid_api.MemberAPIV20Api.update_employment",
                 return_value=Mock(status=201,
                                   headers={'Location': '12344/XYZ/54321'}))
    mocker.patch("orcid_api.MemberAPIV20Api.update_education",
                 return_value=Mock(status=201,
                                   headers={'Location': '12344/XYZ/12345'}))

    org = Organisation.create(
        name="THE ORGANISATION:test_sync_profile",
        tuakiri_name="THE ORGANISATION:test_sync_profile",
        confirmed=True,
        orcid_client_id="APP-5ZVH4JRQ0C27RVH5",
        orcid_secret="Client Secret",
        city="CITY",
        country="COUNTRY",
        disambiguated_id="ID",
        disambiguation_source="SOURCE")
    u = User.create(email="*****@*****.**",
                    name="TEST USER",
                    roles=Role.RESEARCHER,
                    orcid="12344",
                    confirmed=True,
                    organisation=org)
    UserOrg.create(user=u, org=org)
    access_token = "ACCESS-TOKEN"

    t = Task.create(org=org, task_type=TaskType.SYNC)
    api = MemberAPI(org=org)

    mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record",
                 lambda *args: None)
    api.sync_profile(task=t, user=u, access_token=access_token)

    OrcidToken.create(user=u,
                      org=org,
                      scope="/read-limited,/activities/update")
    mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record",
                 lambda *args: None)
    api.sync_profile(task=t, user=u, access_token=access_token)
    assert Log.select().count() > 0

    mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record",
                 return_value=get_profile())
    api.sync_profile(task=t, user=u, access_token=access_token)
    last_log = Log.select().order_by(Log.id.desc()).first()
    assert "Successfully update" in last_log.message
def test_create_or_update_affiliation(app, mocker):
    """Test create or update affiliation."""
    mocker.patch("orcid_api.MemberAPIV20Api.update_employment",
                 return_value=Mock(status=201,
                                   headers={'Location': '12344/XYZ/12399'}))
    mocker.patch("orcid_api.MemberAPIV20Api.create_employment",
                 return_value=Mock(status=201,
                                   headers={'Location': '12344/XYZ/12399'}))
    send_email = mocker.patch("orcid_hub.utils.send_email")
    capture_event = mocker.patch(
        "sentry_sdk.transport.HttpTransport.capture_event")
    org = app.data["org"]
    u = User.create(email="*****@*****.**",
                    name="TEST USER",
                    roles=Role.RESEARCHER,
                    orcid="123",
                    confirmed=True,
                    organisation=org)
    UserOrg.create(user=u, org=org)
    t = Task.create(org=org,
                    filename="xyz.json",
                    created_by=u,
                    updated_by=u,
                    task_type=TaskType.AFFILIATION)
    OrcidToken.create(user=u,
                      org=org,
                      scopes="/read-limited,/activities/update",
                      access_token="Test_token")
    UserInvitation.create(invitee=u,
                          inviter=u,
                          org=org,
                          task=t,
                          email="*****@*****.**",
                          token="xyztoken")

    u = User.create(email="*****@*****.**",
                    name="TEST USER 2",
                    roles=Role.RESEARCHER,
                    confirmed=True,
                    organisation=org)
    UserOrg.create(user=u, org=org)

    AffiliationRecord.create(is_active=True,
                             task=t,
                             external_id="Test",
                             first_name="Test",
                             last_name="Test",
                             email="*****@*****.**",
                             orcid="123112311231",
                             organisation="asdasd",
                             affiliation_type="staff",
                             role="Test",
                             department="Test",
                             city="Test",
                             state="Test",
                             country="Test",
                             disambiguated_id="Test",
                             disambiguation_source="Test")
    AffiliationRecord.create(is_active=True,
                             task=t,
                             external_id="Test",
                             first_name="Test",
                             last_name="Test",
                             email="*****@*****.**",
                             orcid="123112311231",
                             organisation=org.name,
                             affiliation_type="staff",
                             role="Test",
                             department="Test",
                             city="Test",
                             state="Test",
                             country="Test")
    AffiliationRecord.create(is_active=True,
                             task=t,
                             external_id="Test",
                             first_name="Test",
                             last_name="Test",
                             email="*****@*****.**",
                             orcid="123112311231",
                             organisation="ANOTHER ORG",
                             affiliation_type="staff",
                             role="Test",
                             department="Test",
                             city="Test",
                             state="Test",
                             country="Test",
                             visibility="PUBLIC")
    AffiliationRecord.create(is_active=True,
                             task=t,
                             external_id="Test#2",
                             first_name="Test2",
                             last_name="Test2",
                             email="*****@*****.**",
                             organisation=org.name,
                             affiliation_type="staff")

    tasks = (Task.select(
        Task, AffiliationRecord, User,
        UserInvitation.id.alias("invitation_id"), OrcidToken).join(
            AffiliationRecord,
            on=(Task.id == AffiliationRecord.task_id).alias("record")).join(
                User,
                JOIN.LEFT_OUTER,
                on=((User.email == AffiliationRecord.email)
                    | (User.orcid == AffiliationRecord.orcid))).join(
                        Organisation,
                        JOIN.LEFT_OUTER,
                        on=(Organisation.id == Task.org_id)).join(
                            UserInvitation,
                            JOIN.LEFT_OUTER,
                            on=((UserInvitation.email
                                 == AffiliationRecord.email)
                                & (UserInvitation.task_id == Task.id))).
             join(OrcidToken,
                  JOIN.LEFT_OUTER,
                  on=((OrcidToken.user_id == User.id)
                      & (OrcidToken.org_id == Organisation.id)
                      & (OrcidToken.scopes.contains("/activities/update")))))
    app.config["SERVER_NAME"] = "orcidhub"
    for (task_id, org_id, user), tasks_by_user in groupby(
            tasks, lambda t: (
                t.id,
                t.org_id,
                t.record.user,
            )):
        with patch("orcid_hub.orcid_client.MemberAPI.get_record",
                   return_value=get_profile()
                   if user.orcid else None) as get_record:
            utils.create_or_update_affiliations(user=user,
                                                org_id=org_id,
                                                records=tasks_by_user)
            get_record.assert_any_call()
    affiliation_record = AffiliationRecord.select().order_by(
        AffiliationRecord.id).limit(1).first()
    assert 12399 == affiliation_record.put_code
    assert "12344" == affiliation_record.orcid
    assert ("Employment record was updated" in affiliation_record.status
            or "Employment record was created" in affiliation_record.status)
    capture_event.assert_called()
    send_email.assert_called_once()
def test_create_or_update_property_record(app, mocker):
    """Test create or update researcher keyword, researcher url, other name and country"""
    mocker.patch("orcid_hub.utils.send_email", send_mail_mock)
    mocker.patch("orcid_api.MemberAPIV20Api.create_keyword",
                 create_or_update_fund_mock)
    mocker.patch("orcid_api.MemberAPIV20Api.create_researcher_url",
                 create_or_update_fund_mock)
    mocker.patch("orcid_api.MemberAPIV20Api.create_other_name",
                 create_or_update_fund_mock)
    mocker.patch("orcid_api.MemberAPIV20Api.create_address",
                 create_or_update_fund_mock)
    mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record",
                 return_value=get_profile())
    org = app.data["org"]
    u = User.create(email="*****@*****.**",
                    name="TEST USER",
                    roles=Role.RESEARCHER,
                    orcid="12344",
                    confirmed=True,
                    organisation=org)

    UserOrg.create(user=u, org=org)
    OrcidToken.create(user=u,
                      org=org,
                      scopes="/read-limited,/person/update",
                      access_token="Test_token")

    t = Task.create(id=12,
                    org=org,
                    filename="xyz.json",
                    created_by=u,
                    updated_by=u,
                    task_type=TaskType.PROPERTY)

    PropertyRecord.create(task=t,
                          type="KEYWORD",
                          is_active=True,
                          status="email sent",
                          first_name="Test",
                          last_name="Test",
                          email="*****@*****.**",
                          visibility="PUBLIC",
                          value="dummy name",
                          display_index=1)

    PropertyRecord.create(task=t,
                          type="COUNTRY",
                          is_active=True,
                          status="email sent",
                          first_name="Test",
                          last_name="Test",
                          email="*****@*****.**",
                          visibility="PUBLIC",
                          value="IN",
                          display_index=1)

    PropertyRecord.create(task=t,
                          type="URL",
                          is_active=True,
                          status="email sent",
                          first_name="Test",
                          last_name="Test",
                          email="*****@*****.**",
                          visibility="PUBLIC",
                          name="url name",
                          value="https://www.xyz.com",
                          display_index=1)

    PropertyRecord.create(task=t,
                          type="NAME",
                          is_active=True,
                          status="email sent",
                          first_name="Test",
                          last_name="Test",
                          email="*****@*****.**",
                          visibility="PUBLIC",
                          value="dummy name",
                          display_index=1)

    UserInvitation.create(invitee=u,
                          inviter=u,
                          org=org,
                          task=t,
                          email="*****@*****.**",
                          token="xyztoken")

    utils.process_property_records()
    keyword_record = PropertyRecord.get(email="*****@*****.**",
                                        type="KEYWORD")
    assert 12399 == keyword_record.put_code
    assert "12344" == keyword_record.orcid
    address_record = PropertyRecord.get(email="*****@*****.**",
                                        type="COUNTRY")
    assert 12399 == address_record.put_code
    assert "12344" == address_record.orcid
    url_record = PropertyRecord.get(email="*****@*****.**",
                                    type="URL")
    assert 12399 == url_record.put_code
    assert "12344" == url_record.orcid
    other_name_record = PropertyRecord.get(email="*****@*****.**",
                                           type="NAME")
    assert 12399 == other_name_record.put_code
    assert "12344" == other_name_record.orcid
def test_create_or_update_peer_review(app, mocker):
    """Test create or update peer review."""
    mocker.patch("orcid_hub.utils.send_email", send_mail_mock)
    mocker.patch("orcid_api.MemberAPIV20Api.create_peer_review",
                 create_or_update_fund_mock)
    mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record",
                 return_value=get_profile())
    org = app.data["org"]
    u = User.create(email="*****@*****.**",
                    name="TEST USER",
                    roles=Role.RESEARCHER,
                    orcid="12344",
                    confirmed=True,
                    organisation=org)

    UserOrg.create(user=u, org=org)

    t = Task.create(id=12,
                    org=org,
                    filename="xyz.json",
                    created_by=u,
                    updated_by=u,
                    task_type=TaskType.PEER_REVIEW)
    pr = PeerReviewRecord.create(task=t,
                                 review_group_id="issn:12131",
                                 reviewer_role="reviewer",
                                 review_url="xyz",
                                 review_type="REVIEW",
                                 subject_external_id_type="doi",
                                 subject_external_id_value="1212",
                                 subject_external_id_url="url/SELF",
                                 subject_external_id_relationship="SELF",
                                 subject_container_name="Journal title",
                                 subject_type="JOURNAL_ARTICLE",
                                 subject_name_title="name",
                                 subject_name_subtitle="subtitle",
                                 subject_name_translated_title_lang_code="en",
                                 subject_name_translated_title="sdsd",
                                 subject_url="url",
                                 convening_org_name="THE ORGANISATION",
                                 convening_org_city="auckland",
                                 convening_org_region="auckland",
                                 convening_org_country="nz",
                                 convening_org_disambiguated_identifier="123",
                                 convening_org_disambiguation_source="1212",
                                 is_active=True)

    PeerReviewInvitee.create(record=pr,
                             first_name="Test",
                             email="*****@*****.**",
                             orcid="12344",
                             visibility="PUBLIC")

    PeerReviewExternalId.create(record=pr,
                                type="Test_type",
                                value="122334_different",
                                url="Test",
                                relationship="SELF")

    UserInvitation.create(invitee=u,
                          inviter=u,
                          org=org,
                          task=t,
                          email="*****@*****.**",
                          token="xyztoken")

    OrcidToken.create(user=u,
                      org=org,
                      scopes="/read-limited,/activities/update",
                      access_token="Test_token")

    utils.process_peer_review_records()
    peer_review_invitees = PeerReviewInvitee.get(orcid=12344)
    assert 12399 == peer_review_invitees.put_code
    assert "12344" == peer_review_invitees.orcid
def test_create_or_update_work(app, mocker):
    """Test create or update work."""
    mocker.patch("orcid_hub.utils.send_email", send_mail_mock)
    mocker.patch("orcid_api.MemberAPIV20Api.create_work",
                 create_or_update_fund_mock)
    mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record",
                 return_value=get_profile())

    org = app.data["org"]
    u = User.create(email="*****@*****.**",
                    name="TEST USER",
                    roles=Role.RESEARCHER,
                    orcid="12344",
                    confirmed=True,
                    organisation=org)

    UserOrg.create(user=u, org=org)

    t = Task.create(org=org,
                    filename="xyz.json",
                    created_by=u,
                    updated_by=u,
                    task_type=TaskType.WORK)

    wr = WorkRecord.create(task=t,
                           title="Test titile",
                           sub_title="Test titile",
                           translated_title="Test title",
                           translated_title_language_code="Test",
                           journal_title="Test titile",
                           short_description="Test desc",
                           citation_type="Test",
                           citation_value="Test",
                           type="BOOK_CHAPTER",
                           url="Test org",
                           language_code="en",
                           country="Test",
                           org_name="Test_orgname",
                           city="Test city",
                           region="Test",
                           is_active=True)

    WorkInvitee.create(record=wr,
                       first_name="Test",
                       email="*****@*****.**",
                       orcid="12344",
                       visibility="PUBLIC")

    WorkExternalId.create(record=wr,
                          type="Test_type",
                          value="Test_value",
                          url="Test",
                          relationship="SELF")

    WorkContributor.create(record=wr,
                           contributor_sequence="1",
                           orcid="1213",
                           role="LEAD",
                           name="xyz",
                           email="*****@*****.**")

    UserInvitation.create(invitee=u,
                          inviter=u,
                          org=org,
                          task=t,
                          email="*****@*****.**",
                          token="xyztoken")

    OrcidToken.create(user=u,
                      org=org,
                      scopes="/read-limited,/activities/update",
                      access_token="Test_token")

    utils.process_work_records()
    invitee = WorkInvitee.get(orcid="12344")
    assert 12399 == invitee.put_code
    assert "12344" == invitee.orcid
def test_create_or_update_funding(app, mocker):
    """Test create or update funding."""
    mocker.patch("orcid_hub.utils.send_email", send_mail_mock)
    mocker.patch("orcid_api.MemberAPIV20Api.create_funding",
                 create_or_update_fund_mock)
    mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record",
                 return_value=get_profile())

    org = app.data["org"]
    u = User.create(email="*****@*****.**",
                    name="TEST USER",
                    roles=Role.RESEARCHER,
                    orcid="123",
                    confirmed=True,
                    organisation=org)

    UserOrg.create(user=u, org=org)

    t = Task.create(org=org,
                    filename="xyz.json",
                    created_by=u,
                    updated_by=u,
                    task_type=TaskType.FUNDING)

    fr = FundingRecord.create(task=t,
                              title="Test titile",
                              translated_title="Test title",
                              translated_title_language_code="Test",
                              type="GRANT",
                              organization_defined_type="Test org",
                              short_description="Test desc",
                              amount="1000",
                              currency="USD",
                              org_name="Test_orgname",
                              city="Test city",
                              region="Test",
                              country="Test",
                              disambiguated_id="Test_dis",
                              disambiguation_source="Test_source",
                              is_active=True)

    FundingInvitee.create(record=fr,
                          first_name="Test",
                          email="*****@*****.**",
                          visibility="PUBLIC",
                          orcid="123")

    ExternalId.create(record=fr,
                      type="Test_type",
                      value="Test_value",
                      url="Test",
                      relationship="SELF")

    FundingContributor.create(record=fr,
                              orcid="1213",
                              role="LEAD",
                              name="Contributor",
                              email="*****@*****.**")

    UserInvitation.create(invitee=u,
                          inviter=u,
                          org=org,
                          task=t,
                          email="*****@*****.**",
                          token="xyztoken")

    OrcidToken.create(user=u,
                      org=org,
                      scopes="/read-limited,/activities/update",
                      access_token="Test_token")

    utils.process_funding_records()
    funding_invitees = FundingInvitee.get(orcid="12344")
    assert 12399 == funding_invitees.put_code
    assert "12344" == funding_invitees.orcid
def test_sync_profile(app, mocker):
    """Test sync_profile."""
    mocker.patch("orcid_api.MemberAPIV20Api.update_employment",
                 return_value=Mock(status=201,
                                   headers={'Location': '12344/XYZ/54321'}))
    mocker.patch("orcid_api.MemberAPIV20Api.update_education",
                 return_value=Mock(status=201,
                                   headers={'Location': '12344/XYZ/12345'}))

    def sync_profile_mock(*args, **kwargs):
        utils.sync_profile(*args, **kwargs)
        return Mock(id="test-test-test-test")

    mocker.patch("orcid_hub.utils.sync_profile.queue", sync_profile_mock)

    org = Organisation.create(
        name="THE ORGANISATION:test_sync_profile",
        tuakiri_name="THE ORGANISATION:test_sync_profile",
        confirmed=True,
        orcid_client_id="APP-5ZVH4JRQ0C27RVH5",
        orcid_secret="Client Secret",
        city="CITY",
        country="COUNTRY",
        disambiguated_id="ID",
        disambiguation_source="SOURCE")
    u = User.create(email="*****@*****.**",
                    name="TEST USER",
                    roles=Role.RESEARCHER,
                    orcid="12344",
                    confirmed=True,
                    organisation=org)
    UserOrg.create(user=u, org=org)

    utils.sync_profile(task_id=999999)

    t = Task.create(org=org, task_type=TaskType.SYNC)

    mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record",
                 lambda *args: None)
    utils.sync_profile(task_id=t.id, delay=0)

    resp = get_profile()
    mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record",
                 lambda *args: resp)
    utils.sync_profile(task_id=t.id, delay=0)

    resp["activities-summary"]["educations"]["education-summary"] = []
    mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record",
                 lambda *args: resp)
    utils.sync_profile(task_id=t.id, delay=0)

    mocker.patch("orcid_hub.orcid_client.MemberAPI.update_employment",
                 side_effect=Exception("FAILED"))
    utils.sync_profile(task_id=t.id, delay=0)

    resp["activities-summary"]["employments"]["employment-summary"][0][
        "source"] = None
    resp["activities-summary"]["employments"]["employment-summary"][0][
        "source"] = None
    mocker.patch("orcid_hub.orcid_client.MemberAPI.get_record",
                 lambda *args: resp)
    utils.sync_profile(task_id=t.id, delay=0)

    org.disambiguated_id = None
    org.save()
    utils.sync_profile(task_id=t.id, delay=0)

    assert Log.select().count() > 0