def test_companies_update(employment: Employment):
    assert employment.role == Employment.ROLE_ADMIN
    user = employment.user
    company = employment.company

    client = APIClient()
    client.force_authenticate(user)

    other_company = CompanyFactory.create()

    patch_data = {
        "data": {
            "type": "company",
            "id": str(company.id),
            "attributes": {},
        },
    }

    # Part one - update the company where the user is admin
    new_name = 'new name'
    updated = company.updated
    assert company.name != new_name
    patch_data['data']['attributes'] = {'name': new_name}
    resp = client.patch(client.reverse('company-detail', pk=company.pk),
                        patch_data)
    validate_jsonapi_detail_response(
        resp,
        expected_attributes=ATTRIBUTES_FULL,
        expected_relationships=RELATIONSHIPS_FULL,
    )
    refreshed_company = Company.objects.get(id=company.id)
    assert refreshed_company.name == new_name
    assert refreshed_company.updated > updated

    # Part two - PUT should not be allowed
    resp = client.put(client.reverse('company-detail', pk=company.pk),
                      patch_data)
    validate_jsonapi_error_response(resp, expected_status_code=405)

    # Part three - updating is only allowed for admins, so it should fail after user is demoted to non-admin
    employment.role = Employment.ROLE_NORMAL
    employment.save()
    resp = client.patch(client.reverse('company-detail', pk=company.pk),
                        patch_data)
    validate_jsonapi_error_response(resp, expected_status_code=403)

    # Part four - try to patch company where we don't have permissions
    patch_data['data']['id'] = str(other_company.id)
    resp = client.patch(client.reverse('company-detail', pk=other_company.pk))
    validate_jsonapi_error_response(resp, expected_status_code=403)
def test_employments_update(employment: Employment, other_user: User):
    """ Admins should be able to update employment info (= role) of companies where they are admins.
    """

    assert employment.role == Employment.ROLE_ADMIN
    user = employment.user
    company = employment.company
    other_employment = Employment.objects.create(company=company,
                                                 user=other_user,
                                                 role=Employment.ROLE_NORMAL)

    client = APIClient()
    client.force_authenticate(user)

    patch_data = {
        "data": {
            "type": "employment",
            "id": str(other_employment.id),
            "attributes": {},
        },
    }

    # Part one - update the employment, changing role to admin
    updated = other_employment.updated
    patch_data['data']['attributes'] = {'role': Employment.ROLE_ADMIN}
    resp = client.patch(
        client.reverse('employment-detail', pk=other_employment.pk),
        patch_data)
    validate_jsonapi_detail_response(
        resp,
        expected_attributes=ATTRIBUTES_FULL,
        expected_relationships=RELATIONSHIPS_FULL,
    )
    refreshed_employment = Employment.objects.get(id=other_employment.id)
    assert refreshed_employment.role == Employment.ROLE_ADMIN
    assert refreshed_employment.updated > updated

    # Part two - PUT should not be allowed
    resp = client.put(
        client.reverse('employment-detail', pk=other_employment.pk),
        patch_data)
    validate_jsonapi_error_response(resp, expected_status_code=405)

    # Part three - updating is only allowed for admins, so it should fail after user is demoted to non-admin
    employment.role = Employment.ROLE_NORMAL
    employment.save()
    resp = client.patch(
        client.reverse('employment-detail', pk=other_employment.pk),
        patch_data)
    validate_jsonapi_error_response(resp, expected_status_code=403)
def test_companies_create_only_fields(user: User):
    """ Ensures that create-only fields cannot be updated for existing instances.

    It also acts as general test for the create-only fields functionality.
    """

    client = APIClient()
    client.force_authenticate(user)

    # Part one - try creating a company without reg_code (required and create-only field) - this should fail
    req_data = deepcopy(COMPANIES_CREATE_REQUEST)
    del req_data['data']['attributes']['reg_code']
    resp = client.post(client.reverse('company-list'), data=req_data)
    validate_jsonapi_error_response(resp, expected_status_code=400)

    # Part two - create a company with all the necessary fields
    req_data = deepcopy(COMPANIES_CREATE_REQUEST)
    resp = client.post(client.reverse('company-list'), data=req_data)
    resp_data = validate_jsonapi_detail_response(resp,
                                                 expected_status_code=201)

    # Ensure everything is as intended
    req_data_attributes = req_data['data']['attributes']
    company = Company.objects.get(id=resp_data['data']['id'])
    for attr_name in req_data_attributes:
        assert getattr(company, attr_name) == req_data_attributes[attr_name]

    # Next, try updating the reg_code, which should be read-only
    new_reg_code = 123456
    assert company.reg_code != new_reg_code
    patch_data = {
        "data": {
            "type": "company",
            "id": str(company.id),
            "attributes": {
                'reg_code': new_reg_code,
            },
        },
    }

    # Try to update the value - it should be no-op
    resp = client.patch(client.reverse('company-detail', pk=company.pk),
                        patch_data)
    validate_jsonapi_detail_response(
        resp,
        expected_attributes=ATTRIBUTES_FULL,
        expected_relationships=RELATIONSHIPS_FULL,
    )
    # Ensure the value in database hasn't been changed
    refreshed_company = Company.objects.get(id=company.id)
    assert refreshed_company.reg_code == company.reg_code