class ProjectDetailsServiceImpl extends AbstractProjectServiceImpl implements ProjectDetailsService {

    @Override
    @Transactional
    public ServiceResult<Void> updatePartnerProjectLocation(ProjectOrganisationCompositeId composite, PostcodeAndTownResource postcodeAndTown) {
        Function<PostcodeAndTownResource, ServiceResult<Void>> validation;
        ExceptionThrowingFunction<PartnerOrganisation, PartnerOrganisation> settingLocation;

        Optional<Organisation> organisation = organisationRepository.findById(composite.getOrganisationId());

        if (organisation.isPresent() && organisation.get().isInternational()) {
            validation = ProjectDetailsServiceImpl::validateTown;
            settingLocation = settingTown(postcodeAndTown);
        } else {
            validation = ProjectDetailsServiceImpl::validatePostcode;
            settingLocation = settingPostcode(postcodeAndTown);
        }

        return validation.apply(postcodeAndTown).
            andOnSuccess(() -> getProject(composite.getProjectId())).
            andOnSuccess(project -> validateGOLGenerated(project, PROJECT_SETUP_LOCATION_CANNOT_BE_UPDATED_IF_GOL_GENERATED)).
            andOnSuccess(() -> getPartnerOrganisation(composite.getProjectId(), composite.getOrganisationId())).
            andOnSuccessReturn(settingLocation)
            .andOnSuccessReturnVoid(partnerOrganisation ->
                getCurrentlyLoggedInProjectUser(partnerOrganisation.getProject(), PROJECT_PARTNER)
                        .andOnSuccessReturnVoid((projectUser) ->
                                projectDetailsWorkflowHandler.projectLocationAdded(partnerOrganisation.getProject(), projectUser)));
    }

}