def test_terminate_engagement_when_to_date_set(self): sd_updater = setup_sd_changed_at() sd_updater.mo_engagements_cache["person_uuid"] = [{ "user_key": "00000", "uuid": "mo_engagement_uuid", }] morahelper = sd_updater.morahelper_mock mock_post_mo = morahelper._mo_post mock_post_mo.return_value = attrdict({ "status_code": 200, "text": lambda: "mo_engagement_uuid" }) sd_updater._terminate_engagement( user_key="00000", person_uuid="person_uuid", from_date="2021-10-15", to_date="2021-10-20", ) mock_post_mo.assert_called_once_with( "details/terminate", { "type": "engagement", "uuid": "mo_engagement_uuid", "validity": { "from": "2021-10-15", "to": "2021-10-20" }, }, )
def test_terminate_engagement(self): employment_id = "01337" sd_updater = setup_sd_changed_at() morahelper = sd_updater.morahelper_mock sd_updater.mo_engagements_cache["user_uuid"] = [{ "user_key": employment_id, "uuid": "mo_engagement_uuid", }] _mo_post = morahelper._mo_post _mo_post.return_value = attrdict({ "status_code": 200, "text": lambda: "mo_engagement_uuid" }) self.assertFalse(_mo_post.called) sd_updater._terminate_engagement(user_key=employment_id, person_uuid="user_uuid", from_date="2020-11-01") _mo_post.assert_called_once_with( "details/terminate", { "type": "engagement", "uuid": "mo_engagement_uuid", "validity": { "from": "2020-11-01", "to": None }, }, )
def test_set_engagement_on_leave(mock_uuid4): # Arrange mock_uuid4.return_value = UUID("00000000-0000-0000-0000-000000000000") sd = get_sd_importer() sd.nodes["org_unit_uuid"] = attrdict({"name": "org_unit"}) cpr_no = "0101709999" sd.importer.add_employee( name=("given_name", "sur_name"), identifier=cpr_no, cpr_no=cpr_no, user_key="employee_user_key", uuid="employee_uuid", ) # Act # Create an employee on leave (SD EmploymentStatusCode = 3) sd.create_employee({ "PersonCivilRegistrationIdentifier": cpr_no, "Employment": [{ "EmploymentDate": "1960-01-01", "AnniversaryDate": "2004-08-15", "Profession": { "JobPositionIdentifier": "job_id_123" }, "EmploymentStatus": { "EmploymentStatusCode": "3", "ActivationDate": "1970-01-01", "DeactivationDate": "9999-12-31", }, "EmploymentIdentifier": "TEST123", "WorkingTime": { "OccupationRate": 1 }, "EmploymentDepartment": { "DepartmentUUIDIdentifier": "org_unit_uuid", }, }], }) # Assert details = sd.importer.employee_details[cpr_no] engagement, leave = details assert engagement.uuid == "00000000-0000-0000-0000-000000000000" assert leave.engagement_uuid == "00000000-0000-0000-0000-000000000000"
def test_update_changed_persons(self): cpr = "0101709999" first_name = "John" last_name = "Deere" _, read_person_result = get_sd_person_fixture( cpr=cpr, first_name=first_name, last_name=last_name, employment_id="01337", ) sd_updater = setup_sd_changed_at() sd_updater.get_sd_person = lambda cpr: read_person_result generate_uuid = uuid_generator("test") org_uuid = str(generate_uuid("org_uuid")) user_uuid = str(generate_uuid("user_uuid")) sd_updater.org_uuid = org_uuid morahelper = sd_updater.morahelper_mock morahelper.read_user.return_value = { "uuid": user_uuid, "name": " ".join(["Old firstname", last_name]), "first_name": "Old firstname", "surname": last_name, } _mo_post = morahelper._mo_post _mo_post.return_value = attrdict({ "status_code": 201, "json": lambda: user_uuid }) self.assertFalse(_mo_post.called) sd_updater.update_changed_persons(in_cpr=cpr) _mo_post.assert_called_with( "e/create", { "type": "employee", "givenname": first_name, "surname": last_name, "cpr_no": cpr, "org": { "uuid": org_uuid }, "uuid": user_uuid, "user_key": user_uuid, }, )
def test_handle_status_changes_terminates_let_go_employment_status( self, sd_deactivation_date, mo_termination_to_date): cpr = "0101709999" employment_id = "01337" _, read_employment_result = read_employment_fixture( cpr=cpr, employment_id=employment_id, job_id="1234", job_title="EDB-Mand", status="1", ) sd_employment = read_employment_result[0]["Employment"] sd_employment["EmploymentStatus"].pop( 0) # Remove the one with status 8 sd_employment["EmploymentStatus"][0][ "DeactivationDate"] = sd_deactivation_date sd_updater = setup_sd_changed_at() sd_updater.mo_engagements_cache["person_uuid"] = [{ "user_key": employment_id, "uuid": "mo_engagement_uuid", }] morahelper = sd_updater.morahelper_mock mock_mo_post = morahelper._mo_post mock_mo_post.return_value = attrdict({ "status_code": 200, "text": lambda: "mo_engagement_uuid" }) sd_updater._handle_employment_status_changes( cpr=cpr, sd_employment=sd_employment, person_uuid="person_uuid") mock_mo_post.assert_called_once_with( "details/terminate", { "type": "engagement", "uuid": "mo_engagement_uuid", "validity": { "from": "2021-02-10", "to": mo_termination_to_date }, }, )
def test_construct_object(self, sd_payloads_mock, job_position, no_salary_minimum): expected = no_salary_minimum is not None expected = expected and job_position < no_salary_minimum expected = not expected sd_updater = setup_sd_changed_at({ "sd_no_salary_minimum_id": no_salary_minimum, }) sd_updater.apply_NY_logic = ( lambda org_unit, user_key, validity, person_uuid: org_unit) morahelper = sd_updater.morahelper_mock morahelper.read_ou.return_value = { "org_unit_level": { "user_key": "IHaveNoIdea", }, "uuid": "uuid-a", } _mo_post = morahelper._mo_post _mo_post.return_value = attrdict({ "status_code": 201, "text": lambda: "OK" }) engagement = { "EmploymentIdentifier": "BIGAL", "EmploymentDepartment": [{ "DepartmentUUIDIdentifier": "uuid-c" }], "Profession": [{ "JobPositionIdentifier": str(job_position) }], } status = { "ActivationDate": "", "DeactivationDate": "", "EmploymentStatusCode": "", } cpr = "" result = sd_updater.create_new_engagement(engagement, status, cpr, "uuid-b") self.assertEqual(result, expected) if expected: sd_payloads_mock.create_engagement.assert_called_once() else: sd_payloads_mock.create_engagement.assert_not_called()
def test_handle_status_changes_terminates_slettet_employment_status(self): cpr = "0101709999" employment_id = "01337" _, read_employment_result = read_employment_fixture( cpr=cpr, employment_id=employment_id, job_id="1234", job_title="EDB-Mand", status="S", ) sd_employment = read_employment_result[0]["Employment"] sd_updater = setup_sd_changed_at() sd_updater.mo_engagements_cache["person_uuid"] = [{ "user_key": employment_id, "uuid": "mo_engagement_uuid", }] morahelper = sd_updater.morahelper_mock mock_mo_post = morahelper._mo_post mock_mo_post.return_value = attrdict({ "status_code": 200, "text": lambda: "mo_engagement_uuid" }) sd_updater._handle_employment_status_changes( cpr=cpr, sd_employment=sd_employment, person_uuid="person_uuid") mock_mo_post.assert_called_once_with( "details/terminate", { "type": "engagement", "uuid": "mo_engagement_uuid", "validity": { "from": "2020-11-01", "to": None }, }, )
def test_create_employee(create_associations: bool): sd = get_sd_importer( override_settings={ "sd_importer_create_associations": create_associations, }) sd.nodes["org_unit_uuid"] = attrdict({"name": "org_unit"}) original_classes = set(sd.importer.klasse_objects.keys()) cpr_no = "0101709999" sd.importer.add_employee( name=("given_name", "sur_name"), identifier=cpr_no, cpr_no=cpr_no, user_key="employee_user_key", uuid="employee_uuid", ) sd.create_employee({ "PersonCivilRegistrationIdentifier": cpr_no, "Employment": [{ "Profession": { "JobPositionIdentifier": "job_id_123" }, "AnniversaryDate": "2004-08-15", "EmploymentStatus": { "EmploymentStatusCode": "1", "ActivationDate": "1970-01-01", "DeactivationDate": "9999-12-31", }, "EmploymentIdentifier": "TEST123", "WorkingTime": { "OccupationRate": 1 }, "EmploymentDepartment": { "DepartmentUUIDIdentifier": "org_unit_uuid", }, }], }) new_classes = { key: value for key, value in sd.importer.klasse_objects.items() if key not in original_classes } assert len(new_classes) == 2 engagement_type = new_classes["engagement_typejob_id_123"] job_id = new_classes["job_id_123"] assert engagement_type.date_from == job_id.date_from == "1930-01-01" assert engagement_type.date_to == job_id.date_to == "infinity" assert engagement_type.integration_data == job_id.integration_data == {} assert engagement_type.description == job_id.description is None assert engagement_type.scope == job_id.scope == "TEXT" assert engagement_type.example == job_id.example is None assert engagement_type.organisation_uuid == job_id.organisation_uuid is None assert engagement_type.facet_uuid == job_id.facet_uuid is None assert engagement_type.user_key == "engagement_typejob_id_123" assert engagement_type.title == "job_id_123" assert engagement_type.facet_type_ref == "engagement_type" UUID(engagement_type.uuid) assert job_id.user_key == "job_id_123" assert job_id.title == "job_id_123" assert job_id.facet_type_ref == "engagement_job_function" UUID(job_id.uuid) # 18 facets in os2mo_data_import/defaults.py assert len(sd.importer.facet_objects) == 18 # None of these objects assert len(sd.importer.addresses) == 0 assert len(sd.importer.itsystems) == 0 assert len(sd.importer.organisation_units) == 0 assert len(sd.importer.organisation_unit_details) == 0 # But one of these assert len(sd.importer.employees) == 1 employee = sd.importer.employees[cpr_no] assert employee.givenname == "given_name" assert employee.surname == "sur_name" assert employee.cpr_no == cpr_no assert employee.user_key == "employee_user_key" assert len(sd.importer.employee_details) == 1 details = sd.importer.employee_details[cpr_no] if create_associations: # We expect one engagement, and one association assert len(details) == 2 association, engagement = details assert association.type_id == "association" assert association.date_from == "1970-01-01" assert association.date_to is None assert association.user_key == "TEST123" assert association.org_unit_ref == "org_unit_uuid" assert association.type_ref == "SD-medarbejder" else: # We expect just an engagement assert len(details) == 1 engagement = details[0] assert engagement.type_id == "engagement" assert engagement.date_from == "1970-01-01" assert engagement.date_to is None assert engagement.user_key == "TEST123" assert engagement.fraction == 1000000 assert engagement.primary_ref == "non-primary" assert engagement.org_unit_ref == "org_unit_uuid" assert engagement.type_ref == "engagement_typejob_id_123" assert engagement.job_function_ref == "job_id_123"
def test_edit_engagement_job_position_id_set_to_value_above_9000( self, mock_sd_lookup, mock_sd_lookup_settings): """ If an employment exists in MO but with no engagement (e.g. which happens when the MO employment was created with an SD payload having a JobPositionIdentifier < 9000) and we receive an SD change payload, where the JobPositionIdentifier is set to a value greater than 9000, then we must ensure that an engagement is create for the corresponding employee in MO. """ # Arrange sd_updater = setup_sd_changed_at({ "sd_monthly_hourly_divide": 80000, "sd_no_salary_minimum_id": 9000, "sd_import_too_deep": [ "Afdelings-niveau", "NY1-niveau", ], }) sd_updater.engagement_types = { "månedsløn": "monthly pay", "timeløn": "hourly pay", } engagement = OrderedDict([ ("EmploymentIdentifier", "DEERE"), ( "Profession", OrderedDict([ ("@changedAtDate", "2021-12-20"), ("ActivationDate", "2021-12-19"), ("DeactivationDate", "9999-12-31"), ("JobPositionIdentifier", "9002"), ("EmploymentName", "dummy"), ("AppointmentCode", "0"), ]), ), ]) mock_sd_lookup_settings.return_value = ("", "", "") # Necessary for the _find_engagement call in edit_engagement # Mock the call to arrange that no engagements are found for the user mora_helper = sd_updater.morahelper_mock _mo_lookup = mora_helper._mo_lookup _mo_lookup.return_value = [] # Mock the call in sd_updater.read_employment_at(...) mock_sd_lookup.return_value = get_employment_fixture( 1234561234, "emp_id", "dep_id", "dep_uuid", "9002", "job_title") mock_apply_NY_logic = MagicMock() sd_updater.apply_NY_logic = mock_apply_NY_logic mock_apply_NY_logic.return_value = "org_unit_uuid" primary_types = sd_updater.primary_types_mock __getitem__ = primary_types.__getitem__ __getitem__.return_value = "primary_uuid" _mo_post = mora_helper._mo_post _mo_post.return_value = attrdict({ "status_code": 201, }) # Act sd_updater.edit_engagement(engagement, "person_uuid") # Assert _mo_post.assert_called_once_with( "details/create", { "engagement_type": { "uuid": "new_class_uuid" }, "fraction": 0, "job_function": { "uuid": "new_class_uuid" }, "org_unit": { "uuid": "org_unit_uuid" }, "person": { "uuid": "person_uuid" }, "primary": { "uuid": "primary_uuid" }, "type": "engagement", "user_key": "emp_id", "validity": { "from": "2020-11-10", "to": "2021-02-09" }, }, )
def test_edit_engagement(self): engagement = OrderedDict([ ("EmploymentIdentifier", "DEERE"), ( "Profession", OrderedDict([ ("@changedAtDate", "1970-01-01"), ("ActivationDate", "1960-01-01"), ("DeactivationDate", "9999-12-31"), ("JobPositionIdentifier", "9002"), ("EmploymentName", "dummy"), ("AppointmentCode", "0"), ]), ), ]) sd_updater = setup_sd_changed_at() sd_updater.engagement_types = { "månedsløn": "monthly pay", "timeløn": "hourly pay", } sd_updater.mo_engagements_cache["person_uuid"] = [{ "user_key": engagement["EmploymentIdentifier"], "uuid": "mo_engagement_uuid", "validity": { "from": "1950-01-01", "to": None }, }] morahelper = sd_updater.morahelper_mock _mo_post = morahelper._mo_post _mo_post.return_value = attrdict({ "status_code": 201, }) sd_updater._create_engagement_type = MagicMock( wraps=sd_updater._create_engagement_type) sd_updater._create_professions = MagicMock( wraps=sd_updater._create_professions) # Return 1 on first call, 2 on second call sd_updater._create_class.side_effect = [ "new_class_1_uuid", "new_class_2_uuid", ] sd_updater.edit_engagement(engagement, "person_uuid") # Check that the create functions are both called sd_updater._create_engagement_type.assert_called_with( "engagement_type9002", "9002") sd_updater._create_professions.assert_called_with("9002", "9002") # And thus that job_sync is called once from each sd_updater.job_sync.sync_from_sd.assert_has_calls( [call("9002", refresh=True), call("9002", refresh=True)]) # And that the results are returned to MO _mo_post.assert_has_calls([ call( "details/edit", { "type": "engagement", "uuid": "mo_engagement_uuid", "data": { "job_function": { "uuid": "new_class_1_uuid" }, "validity": { "from": "1960-01-01", "to": None }, }, }, ), call( "details/edit", { "type": "engagement", "uuid": "mo_engagement_uuid", "data": { "engagement_type": { "uuid": "new_class_2_uuid" }, "validity": { "from": "1960-01-01", "to": None }, }, }, ), ])
def test_update_all_employments_editing(self, employment_id, engagement_type): cpr = "0101709999" job_id = "1234" _, read_employment_result = read_employment_fixture( cpr=cpr, employment_id=employment_id, job_id=job_id, job_title="EDB-Mand", ) sd_updater = setup_sd_changed_at() sd_updater.engagement_types = { "månedsløn": "monthly pay", "timeløn": "hourly pay", "engagement_type" + job_id: "employment pay", } sd_updater.read_employment_changed = lambda: read_employment_result # Load noop NY logic sd_updater.apply_NY_logic = ( lambda org_unit, user_key, validity, person_uuid: org_unit) morahelper = sd_updater.morahelper_mock morahelper.read_user.return_value.__getitem__.return_value = "user_uuid" morahelper.read_user_engagement.return_value = [{ "user_key": employment_id, "uuid": "mo_engagement_uuid", "validity": { "to": "9999-12-31" }, }] # Set primary types sd_updater.primary_types = { "primary": "primary_uuid", "non_primary": "non_primary_uuid", "no_salary": "no_salary_uuid", "fixed_primary": "fixed_primary_uuid", } _mo_post = morahelper._mo_post _mo_post.return_value = attrdict({ "status_code": 201, "text": lambda: "OK" }) self.assertFalse(_mo_post.called) sd_updater._create_engagement_type = MagicMock() sd_updater._create_engagement_type.return_value = "new_engagement_type_uuid" sd_updater._create_professions = MagicMock() sd_updater._create_professions.return_value = "new_profession_uuid" sd_updater.update_all_employments() # We expect the exact following 4 calls to have been made self.assertEqual(len(_mo_post.mock_calls), 5) _mo_post.assert_has_calls([ call( "details/edit", { "type": "engagement", "uuid": "mo_engagement_uuid", "data": { "validity": { "from": "2020-11-10", "to": "2021-02-09" }, "primary": { "uuid": "non_primary_uuid" }, }, }, ), call( "details/edit", { "type": "engagement", "uuid": "mo_engagement_uuid", "data": { "org_unit": { "uuid": "department_uuid" }, "validity": { "from": "2020-11-10", "to": None }, }, }, ), call( "details/edit", { "type": "engagement", "uuid": "mo_engagement_uuid", "data": { "job_function": { "uuid": "new_profession_uuid" }, "validity": { "from": "2020-11-10", "to": None }, }, }, ), call( "details/edit", { "type": "engagement", "uuid": "mo_engagement_uuid", "data": { "engagement_type": { "uuid": engagement_type }, "validity": { "from": "2020-11-10", "to": None }, }, }, ), call( "details/terminate", { "type": "engagement", "uuid": "mo_engagement_uuid", "validity": { "from": "2021-02-10", "to": None }, }, ), ]) sd_updater._create_engagement_type.assert_not_called() sd_updater._create_professions.assert_called_once()
def test_create_new_engagement(self, employment_id, engagement_type): cpr = "0101709999" job_id = "1234" _, read_employment_result = read_employment_fixture( cpr=cpr, employment_id=employment_id, job_id=job_id, job_title="EDB-Mand", ) sd_updater = setup_sd_changed_at() sd_updater.engagement_types = { "månedsløn": "monthly pay", "timeløn": "hourly pay", "engagement_type" + job_id: "employment pay", } morahelper = sd_updater.morahelper_mock # Load noop NY logic sd_updater.apply_NY_logic = ( lambda org_unit, user_key, validity, person_uuid: org_unit) # Set primary types sd_updater.primary_types = { "primary": "primary_uuid", "non_primary": "non_primary_uuid", "no_salary": "no_salary_uuid", "fixed_primary": "fixed_primary_uuid", } engagement = read_employment_result[0]["Employment"] # First employment status entry from read_employment_result status = read_employment_result[0]["Employment"]["EmploymentStatus"][0] _mo_post = morahelper._mo_post _mo_post.return_value = attrdict({ "status_code": 201, }) self.assertFalse(_mo_post.called) sd_updater._create_engagement_type = MagicMock() sd_updater._create_engagement_type.return_value = "new_engagement_type_uuid" sd_updater._create_professions = MagicMock() sd_updater._create_professions.return_value = "new_profession_uuid" sd_updater.create_new_engagement(engagement, status, cpr, "user_uuid") _mo_post.assert_called_with( "details/create", { "type": "engagement", "org_unit": { "uuid": "department_uuid" }, "person": { "uuid": "user_uuid" }, "job_function": { "uuid": "new_profession_uuid" }, "primary": { "uuid": "non_primary_uuid" }, "engagement_type": { "uuid": engagement_type }, "user_key": employment_id, "fraction": 0, "validity": { "from": "2020-11-10", "to": "2021-02-09" }, }, ) sd_updater._create_engagement_type.assert_not_called() sd_updater._create_professions.assert_called_once()
def get_organisation_fixture( institution_id="XX", institution_uuid=None, region_id="XY", region_uuid=None, department_structure_name="XX-Basis", department1_id="D1X", department1_uuid=None, sub_department1_id="D1Y", sub_department1_uuid=None, department2_id="D2X", department2_uuid=None, sub_department2_id="D2Y", sub_department2_uuid=None, ): institution_uuid = institution_uuid or str(uuid4()) region_uuid = region_uuid or str(uuid4()) department1_uuid = department1_uuid or str(uuid4()) sub_department1_uuid = sub_department1_uuid or str(uuid4()) department2_uuid = department2_uuid or str(uuid4()) sub_department2_uuid = sub_department2_uuid or str(uuid4()) return attrdict({ "text": f""" <GetOrganization20111201 creationDateTime="2021-10-20T14:35:44"> <RequestStructure> <InstitutionIdentifier>{institution_id}</InstitutionIdentifier> <ActivationDate>2021-10-20</ActivationDate> <DeactivationDate>2021-10-20</DeactivationDate> <UUIDIndicator>true</UUIDIndicator> </RequestStructure> <RegionIdentifier>{region_id}</RegionIdentifier> <RegionUUIDIdentifier>{region_uuid}</RegionUUIDIdentifier> <InstitutionIdentifier>{institution_id}</InstitutionIdentifier> <InstitutionUUIDIdentifier>{institution_uuid}</InstitutionUUIDIdentifier> <DepartmentStructureName>{department_structure_name}</DepartmentStructureName> <OrganizationStructure> <DepartmentLevelReference> <DepartmentLevelIdentifier>Afdelings-niveau</DepartmentLevelIdentifier> <DepartmentLevelReference> <DepartmentLevelIdentifier>NY0-niveau</DepartmentLevelIdentifier> <DepartmentLevelReference> <DepartmentLevelIdentifier>NY1-niveau</DepartmentLevelIdentifier> <DepartmentLevelReference> <DepartmentLevelIdentifier>NY2-niveau</DepartmentLevelIdentifier> <DepartmentLevelReference> <DepartmentLevelIdentifier>NY3-niveau</DepartmentLevelIdentifier> <DepartmentLevelReference> <DepartmentLevelIdentifier>NY4-niveau</DepartmentLevelIdentifier> <DepartmentLevelReference> <DepartmentLevelIdentifier>NY5-niveau</DepartmentLevelIdentifier> <DepartmentLevelReference> <DepartmentLevelIdentifier>NY6-niveau</DepartmentLevelIdentifier> </DepartmentLevelReference> </DepartmentLevelReference> </DepartmentLevelReference> </DepartmentLevelReference> </DepartmentLevelReference> </DepartmentLevelReference> </DepartmentLevelReference> </DepartmentLevelReference> </OrganizationStructure> <Organization> <ActivationDate>2021-10-01</ActivationDate> <DeactivationDate>2021-10-20</DeactivationDate> <DepartmentReference> <DepartmentIdentifier>{department1_id}</DepartmentIdentifier> <DepartmentUUIDIdentifier>{department1_uuid}</DepartmentUUIDIdentifier> <DepartmentLevelIdentifier>Afdelings-niveau</DepartmentLevelIdentifier> <DepartmentReference> <DepartmentIdentifier>{sub_department1_id}</DepartmentIdentifier> <DepartmentUUIDIdentifier>{sub_department1_uuid}</DepartmentUUIDIdentifier> <DepartmentLevelIdentifier>NY5-niveau</DepartmentLevelIdentifier> </DepartmentReference> </DepartmentReference> <DepartmentReference> <DepartmentIdentifier>{department2_id}</DepartmentIdentifier> <DepartmentUUIDIdentifier>{department2_uuid}</DepartmentUUIDIdentifier> <DepartmentLevelIdentifier>Afdelings-niveau</DepartmentLevelIdentifier> <DepartmentReference> <DepartmentIdentifier>{sub_department2_id}</DepartmentIdentifier> <DepartmentUUIDIdentifier>{sub_department2_uuid}</DepartmentUUIDIdentifier> <DepartmentLevelIdentifier>NY5-niveau</DepartmentLevelIdentifier> </DepartmentReference> </DepartmentReference> </Organization> </GetOrganization20111201> """ })
def get_department_fixture( institution_id="XX", institution_uuid=None, region_id="XY", region_uuid=None, department1_id="D1X", department1_uuid=None, department1_name="D1X-name", sub_department1_id="D1Y", sub_department1_uuid=None, sub_department1_name="D1Y-name", department2_id="D2X", department2_uuid=None, department2_name="D2X-name", sub_department2_id="D2Y", sub_department2_uuid=None, sub_department2_name="D2Y-name", ): institution_uuid = institution_uuid or str(uuid4()) region_uuid = region_uuid or str(uuid4()) department1_uuid = department1_uuid or str(uuid4()) sub_department1_uuid = sub_department1_uuid or str(uuid4()) department2_uuid = department2_uuid or str(uuid4()) sub_department2_uuid = sub_department2_uuid or str(uuid4()) return attrdict({ "text": f""" <GetDepartment20111201 creationDateTime="2021-10-20T14:51:23"> <RequestStructure> <InstitutionIdentifier>{institution_id}</InstitutionIdentifier> <ActivationDate>2021-10-20</ActivationDate> <DeactivationDate>2021-10-20</DeactivationDate> <ContactInformationIndicator>true</ContactInformationIndicator> <DepartmentNameIndicator>true</DepartmentNameIndicator> <EmploymentDepartmentIndicator>true</EmploymentDepartmentIndicator> <PostalAddressIndicator>true</PostalAddressIndicator> <ProductionUnitIndicator>true</ProductionUnitIndicator> <UUIDIndicator>true</UUIDIndicator> </RequestStructure> <RegionIdentifier>{region_id}</RegionIdentifier> <RegionUUIDIdentifier>{region_uuid}</RegionUUIDIdentifier> <InstitutionIdentifier>{institution_id}</InstitutionIdentifier> <InstitutionUUIDIdentifier>{institution_uuid}</InstitutionUUIDIdentifier> <Department> <ActivationDate>2010-01-01</ActivationDate> <DeactivationDate>9999-12-31</DeactivationDate> <DepartmentIdentifier>{department1_id}</DepartmentIdentifier> <DepartmentUUIDIdentifier>{department1_uuid}</DepartmentUUIDIdentifier> <DepartmentLevelIdentifier>Afdelings-niveau</DepartmentLevelIdentifier> <DepartmentName>{department1_name}</DepartmentName> <PostalAddress> <StandardAddressIdentifier> Department 1 Address </StandardAddressIdentifier> <PostalCode>8600</PostalCode> <DistrictName>Silkeborg</DistrictName> <MunicipalityCode>0740</MunicipalityCode> </PostalAddress> </Department> <Department> <ActivationDate>2011-01-01</ActivationDate> <DeactivationDate>9999-12-31</DeactivationDate> <DepartmentIdentifier>{sub_department1_id}</DepartmentIdentifier> <DepartmentUUIDIdentifier>{sub_department1_uuid}</DepartmentUUIDIdentifier> <DepartmentLevelIdentifier>NY5-niveau</DepartmentLevelIdentifier> <DepartmentName>{sub_department1_name}</DepartmentName> <PostalAddress> <StandardAddressIdentifier> Sub Department 1 Address </StandardAddressIdentifier> <PostalCode>8600</PostalCode> <DistrictName>Silkeborg</DistrictName> <MunicipalityCode>0740</MunicipalityCode> </PostalAddress> <ContactInformation> <EmailAddressIdentifier>[email protected]</EmailAddressIdentifier> <EmailAddressIdentifier>Empty@Empty</EmailAddressIdentifier> </ContactInformation> </Department> <Department> <ActivationDate>2012-01-01</ActivationDate> <DeactivationDate>9999-12-31</DeactivationDate> <DepartmentIdentifier>{department2_id}</DepartmentIdentifier> <DepartmentUUIDIdentifier>{department2_uuid}</DepartmentUUIDIdentifier> <DepartmentLevelIdentifier>Afdelings-niveau</DepartmentLevelIdentifier> <DepartmentName>{department2_name}</DepartmentName> <PostalAddress> <StandardAddressIdentifier> Department 2 Address </StandardAddressIdentifier> <PostalCode>8600</PostalCode> <DistrictName>Silkeborg</DistrictName> <MunicipalityCode>0740</MunicipalityCode> </PostalAddress> </Department> <Department> <ActivationDate>2013-01-01</ActivationDate> <DeactivationDate>9999-12-31</DeactivationDate> <DepartmentIdentifier>{sub_department2_id}</DepartmentIdentifier> <DepartmentUUIDIdentifier>{sub_department2_uuid}</DepartmentUUIDIdentifier> <DepartmentLevelIdentifier>NY5-niveau</DepartmentLevelIdentifier> <DepartmentName>{sub_department2_name}</DepartmentName> <PostalAddress> <StandardAddressIdentifier> Sub Department 2 Address </StandardAddressIdentifier> <PostalCode>8600</PostalCode> <DistrictName>Silkeborg</DistrictName> <MunicipalityCode>0740</MunicipalityCode> </PostalAddress> <ContactInformation> <EmailAddressIdentifier>[email protected]</EmailAddressIdentifier> <EmailAddressIdentifier>Empty@Empty</EmailAddressIdentifier> </ContactInformation> </Department> </GetDepartment20111201> """ })
def get_sd_person_fixture( cpr: str, first_name: str, last_name: str, employment_id: str ) -> Tuple[AttrDict, List[typing.OrderedDict[str, Any]]]: """ Get an SD person fixture. The function generates both the XML response returned from the SD API endpoint "GetPerson20111201" and the expected `OrderedDict` after parsing the XML. Args: cpr: The CPR number of the SD person. first_name: The first name (given name) of the SD person. last_name: The last name (surname) of the SD person. employment_id: The employmentID, e.g. 12345, of the SD person. Returns: Tuple with two elements. The first element is the raw XML response from the "GetPerson20111201" SD endpoint. The second element is the `OrderedDict` expected to be returned from get_sd_person. Example: ``` >>> fix = get_sd_person_fixture('123456-1234', 'Bruce', 'Lee', "12345") >>> print(fix[0].text) <GetPerson20111201 creationDateTime="2020-12-03T17:40:10"> <RequestStructure> <InstitutionIdentifier>XX</InstitutionIdentifier> <PersonCivilRegistrationIdentifier>123456-1234</PersonCivilRegistrationIdentifier> <EffectiveDate>2020-12-03</EffectiveDate> <StatusActiveIndicator>true</StatusActiveIndicator> <StatusPassiveIndicator>false</StatusPassiveIndicator> <ContactInformationIndicator>false</ContactInformationIndicator> <PostalAddressIndicator>false</PostalAddressIndicator> </RequestStructure> <Person> <PersonCivilRegistrationIdentifier>123456-1234</PersonCivilRegistrationIdentifier> <PersonGivenName>Bruce</PersonGivenName> <PersonSurnameName>Lee</PersonSurnameName> <Employment> <EmploymentIdentifier>12345</EmploymentIdentifier> </Employment> </Person> </GetPerson20111201> >>> print(fix[1]) [ OrderedDict([ ('PersonCivilRegistrationIdentifier', '123456-1234'), ('PersonGivenName', 'Bruce'), ('PersonSurnameName', 'Lee'), ('Employment', OrderedDict([ ('EmploymentIdentifier', '12345') ])) ]) ] ``` """ institution_id = "XX" sd_request_reply = attrdict({ "text": f""" <GetPerson20111201 creationDateTime="2020-12-03T17:40:10"> <RequestStructure> <InstitutionIdentifier>{institution_id}</InstitutionIdentifier> <PersonCivilRegistrationIdentifier>{cpr}</PersonCivilRegistrationIdentifier> <EffectiveDate>2020-12-03</EffectiveDate> <StatusActiveIndicator>true</StatusActiveIndicator> <StatusPassiveIndicator>false</StatusPassiveIndicator> <ContactInformationIndicator>false</ContactInformationIndicator> <PostalAddressIndicator>false</PostalAddressIndicator> </RequestStructure> <Person> <PersonCivilRegistrationIdentifier>{cpr}</PersonCivilRegistrationIdentifier> <PersonGivenName>{first_name}</PersonGivenName> <PersonSurnameName>{last_name}</PersonSurnameName> <Employment> <EmploymentIdentifier>{employment_id}</EmploymentIdentifier> </Employment> </Person> </GetPerson20111201> """ }) expected_read_person_result = [ OrderedDict([ ("PersonCivilRegistrationIdentifier", cpr), ("PersonGivenName", first_name), ("PersonSurnameName", last_name), ( "Employment", OrderedDict([("EmploymentIdentifier", employment_id)]), ), ]) ] return sd_request_reply, expected_read_person_result
def read_employment_fixture( cpr: str, employment_id: str, job_id: str, job_title: str, status: str = "1" ) -> Tuple[AttrDict, List[typing.OrderedDict[str, Any]]]: """ Get an SD employment fixture. The function is use for mocking calls to the "GetEmploymentChangedAtDate20111201" SD API endpoint, i.e. the endpoint that gets new changes *registered* between a from date and a to date. The function generates both the XML response endpoint "GetEmploymentChangedAtDate20111201" and the expected `OrderedDict` after parsing the XML. Args: cpr: The CPR number of the SD person. employment_id: The SD employment ID. job_id: The SD job ID. job_title: The SD profession. status: SD employment status. Returns: Tuple with two elements. The first element is the raw XML response from the "GetEmploymentChangedAtDate20111201" SD endpoint. The second element is the `OrderedDict` expected to be returned from read_employment_changed. Example: ``` >>> fix=read_employment_fixture("123456-1234", "12345", "1", "chief", "1") >>> print(fix[1]) [ OrderedDict([ ('PersonCivilRegistrationIdentifier', '123456-1234'), ('Employment', OrderedDict([ ('EmploymentIdentifier', '12345'), ('EmploymentDate', '2020-11-10'), ('AnniversaryDate', '2004-08-15'), ('EmploymentDepartment', OrderedDict([ ('@changedAtDate', '2020-11-10'), ('ActivationDate', '2020-11-10'), ('DeactivationDate', '9999-12-31'), ('DepartmentIdentifier', 'deprtment_id'), ('DepartmentUUIDIdentifier', 'department_uuid') ])), ('Profession', OrderedDict([ ('@changedAtDate', '2020-11-10'), ('ActivationDate', '2020-11-10'), ('DeactivationDate', '9999-12-31'), ('JobPositionIdentifier', '1'), ('EmploymentName', 'chief'), ('AppointmentCode', '0') ])), ('EmploymentStatus', [ OrderedDict([ ('@changedAtDate', '2020-11-10'), ('ActivationDate', '2020-11-10'), ('DeactivationDate', '2021-02-09'), ('EmploymentStatusCode', '1') ]), OrderedDict([ ('@changedAtDate', '2020-11-10'), ('ActivationDate', '2021-02-10'), ('DeactivationDate', '9999-12-31'), ('EmploymentStatusCode', '8') ]) ]) ])) ]) ] ``` """ institution_id = "institution_id" department_id = "deprtment_id" department_uuid = "department_uuid" sd_request_structure = f""" <RequestStructure> <InstitutionIdentifier>{institution_id}</InstitutionIdentifier> <ActivationDate>2020-11-01</ActivationDate> <ActivationTime>00:00:00</ActivationTime> <DeactivationDate>2020-12-02</DeactivationDate> <DeactivationTime>23:59:59</DeactivationTime> <DepartmentIndicator>true</DepartmentIndicator> <EmploymentStatusIndicator>true</EmploymentStatusIndicator> <ProfessionIndicator>true</ProfessionIndicator> <SalaryAgreementIndicator>false</SalaryAgreementIndicator> <SalaryCodeGroupIndicator>false</SalaryCodeGroupIndicator> <WorkingTimeIndicator>false</WorkingTimeIndicator> <UUIDIndicator>true</UUIDIndicator> <FutureInformationIndicator>false</FutureInformationIndicator> </RequestStructure> """ sd_request_person_employeed = f""" <Person> <PersonCivilRegistrationIdentifier>{cpr}</PersonCivilRegistrationIdentifier> <Employment> <EmploymentIdentifier>{employment_id}</EmploymentIdentifier> <EmploymentDate>2020-11-10</EmploymentDate> <AnniversaryDate>2004-08-15</AnniversaryDate> <EmploymentDepartment changedAtDate="2020-11-10"> <ActivationDate>2020-11-10</ActivationDate> <DeactivationDate>9999-12-31</DeactivationDate> <DepartmentIdentifier>{department_id}</DepartmentIdentifier> <DepartmentUUIDIdentifier>{department_uuid}</DepartmentUUIDIdentifier> </EmploymentDepartment> <Profession changedAtDate="2020-11-10"> <ActivationDate>2020-11-10</ActivationDate> <DeactivationDate>9999-12-31</DeactivationDate> <JobPositionIdentifier>{job_id}</JobPositionIdentifier> <EmploymentName>{job_title}</EmploymentName> <AppointmentCode>0</AppointmentCode> </Profession> <EmploymentStatus changedAtDate="2020-11-10"> <ActivationDate>2020-11-10</ActivationDate> <DeactivationDate>2021-02-09</DeactivationDate> <EmploymentStatusCode>1</EmploymentStatusCode> </EmploymentStatus> <EmploymentStatus changedAtDate="2020-11-10"> <ActivationDate>2021-02-10</ActivationDate> <DeactivationDate>9999-12-31</DeactivationDate> <EmploymentStatusCode>8</EmploymentStatusCode> </EmploymentStatus> </Employment> </Person> """ employeed_result = OrderedDict([ ("PersonCivilRegistrationIdentifier", cpr), ( "Employment", OrderedDict([ ("EmploymentIdentifier", employment_id), ("EmploymentDate", "2020-11-10"), ("AnniversaryDate", "2004-08-15"), ( "EmploymentDepartment", OrderedDict([ ("@changedAtDate", "2020-11-10"), ("ActivationDate", "2020-11-10"), ("DeactivationDate", "9999-12-31"), ("DepartmentIdentifier", department_id), ( "DepartmentUUIDIdentifier", department_uuid, ), ]), ), ( "Profession", OrderedDict([ ("@changedAtDate", "2020-11-10"), ("ActivationDate", "2020-11-10"), ("DeactivationDate", "9999-12-31"), ("JobPositionIdentifier", job_id), ("EmploymentName", job_title), ("AppointmentCode", "0"), ]), ), ( "EmploymentStatus", [ OrderedDict([ ("@changedAtDate", "2020-11-10"), ("ActivationDate", "2020-11-10"), ("DeactivationDate", "2021-02-09"), ("EmploymentStatusCode", "1"), ]), OrderedDict([ ("@changedAtDate", "2020-11-10"), ("ActivationDate", "2021-02-10"), ("DeactivationDate", "9999-12-31"), ("EmploymentStatusCode", "8"), ]), ], ), ]), ), ]) sd_request_person_deleted = f""" <Person> <PersonCivilRegistrationIdentifier>{cpr}</PersonCivilRegistrationIdentifier> <Employment> <EmploymentIdentifier>{employment_id}</EmploymentIdentifier> <EmploymentStatus changedAtDate="2020-11-09"> <ActivationDate>2020-11-01</ActivationDate> <DeactivationDate>9999-12-31</DeactivationDate> <EmploymentStatusCode>S</EmploymentStatusCode> </EmploymentStatus> </Employment> </Person> """ deleted_result = OrderedDict([ ("PersonCivilRegistrationIdentifier", cpr), ( "Employment", OrderedDict([ ("EmploymentIdentifier", employment_id), ( "EmploymentStatus", OrderedDict([ ("@changedAtDate", "2020-11-09"), ("ActivationDate", "2020-11-01"), ("DeactivationDate", "9999-12-31"), ("EmploymentStatusCode", "S"), ]), ), ]), ), ]) person_table = { "1": (sd_request_person_employeed, employeed_result), "S": (sd_request_person_deleted, deleted_result), } sd_response = (""" <GetEmploymentChangedAtDate20111201 creationDateTime="2020-12-02T16:44:19"> """ + sd_request_structure + person_table[status][0] + """ </GetEmploymentChangedAtDate20111201> """) sd_request_reply = attrdict({"text": sd_response}) expected_read_employment_result = [person_table[status][1]] return sd_request_reply, expected_read_employment_result