easycare.util.db.TestData.java Source code

Java tutorial

Introduction

Here is the source code for easycare.util.db.TestData.java

Source

package easycare.util.db;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import easycare.common.Clock;
import easycare.contract.compliance.ComplianceOptions;
import easycare.dao.AirTubingRepository;
import easycare.dao.ApplicationDmeProviderRepository;
import easycare.dao.BillingPlanPatientRepository;
import easycare.dao.BillingPlanRepository;
import easycare.dao.CommunicationModuleRepository;
import easycare.dao.ComplianceRuleRepository;
import easycare.dao.CountryRepository;
import easycare.dao.EcxIntegratorRepository;
import easycare.dao.FlowGenRepository;
import easycare.dao.GroupPatientMembershipHistoryRepository;
import easycare.dao.GroupPatientMembershipRepository;
import easycare.dao.GroupRuleStatRepository;
import easycare.dao.HmePartnersRepository;
import easycare.dao.HumidifierRepository;
import easycare.dao.InsurerRepository;
import easycare.dao.IntegratorPatientRepository;
import easycare.dao.LocalisedFlowGenTypeRepository;
import easycare.dao.MaskSizeTypeRepository;
import easycare.dao.OrganisationRepository;
import easycare.dao.PartyRepository;
import easycare.dao.PartyRoleRepository;
import easycare.dao.PatientFlowGenRepository;
import easycare.dao.PatientGroupLayoutMapRepository;
import easycare.dao.PatientGroupLayoutRepository;
import easycare.dao.PatientRepository;
import easycare.dao.PayorComplianceRuleRepository;
import easycare.dao.PayorRepository;
import easycare.dao.RoleRepository;
import easycare.dao.UserRepository;
import easycare.dao.config.InstallSettingRepository;
import easycare.dao.flowgendata.FlowGenSummaryDataRepository;
import easycare.model.ApplicationDmeProvider;
import easycare.model.BillingPlan;
import easycare.model.ComplianceRule;
import easycare.model.ComplianceRuleTypeEnum;
import easycare.model.Country;
import easycare.model.CountryCode;
import easycare.model.DefaultComplianceRule;
import easycare.model.EcxIntegrator;
import easycare.model.FlowGenSummaryData;
import easycare.model.GroupPatientMembership;
import easycare.model.GroupPatientMembershipHistory;
import easycare.model.GroupPatientMembershipHistoryId;
import easycare.model.GroupPatientMembershipId;
import easycare.model.GroupRuleStat;
import easycare.model.HmePartner;
import easycare.model.Insurer;
import easycare.model.IntegratorPatient;
import easycare.model.MembershipStatusTypeEnum;
import easycare.model.MonitoringMethod;
import easycare.model.Organisation;
import easycare.model.OrganisationType;
import easycare.model.PartyRelationshipTypeEnum;
import easycare.model.PartyRole;
import easycare.model.Patient;
import easycare.model.PatientGroupLayout;
import easycare.model.PatientGroupLayoutMap;
import easycare.model.RoleTypeEnum;
import easycare.model.SubscriptionLevel;
import easycare.model.Title;
import easycare.model.User;
import easycare.model.UsleepGroupRule;
import easycare.model.config.InstallSetting;
import easycare.model.config.InstallSettingType;
import easycare.model.dto.PartyRelationship;
import easycare.model.dto.PatientDmeProvPayorMap;
import easycare.model.dto.PayorComplianceRuleDto;
import easycare.model.dto.PayorDto;
import easycare.model.security.Role;
import easycare.model.security.RoleEnum;
import easycare.model.therapyequipment.AirTubingType;
import easycare.model.therapyequipment.CommunicationModule;
import easycare.model.therapyequipment.CommunicationModuleType;
import easycare.model.therapyequipment.FlowGen;
import easycare.model.therapyequipment.FlowGenType;
import easycare.model.therapyequipment.HumidifierType;
import easycare.model.therapyequipment.LocalisedFlowGenType;
import easycare.model.therapyequipment.MaskSizeType;
import easycare.model.therapyequipment.PatientFlowGen;
import easycare.service.FlowGenSummaryDataService;
import easycare.service.OrganisationService;
import easycare.service.UserService;
import easycare.service.therapyequipment.FlowGenService;
import easycare.util.db.generator.EcxIntegratorGeneratorHelper;
import easycare.util.db.generator.HstPatientGenerator;
import easycare.util.db.generator.InsurerGeneratorHelper;
import easycare.util.db.generator.OrganisationGeneratorHelper;
import easycare.util.db.generator.PatientGeneratorHelper;
import easycare.util.db.generator.TherapyEquipmentGeneratorHelper;
import easycare.util.db.generator.UserGeneratorHelper;
import easycare.util.faker.Faker;
import easycare.web.ReflectionTestUtil;
import lombok.Setter;
import org.apache.commons.lang.math.RandomUtils;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import resmed.cal.common.dto.MID;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static com.google.common.collect.Lists.newArrayList;
import static easycare.dao.flowgendata.FlowGenDataChangePlan.newAddPlan;
import static easycare.model.OrganisationType.HME;
import static easycare.model.OrganisationType.INTEGRATED_HME_SLEEP_LAB;
import static easycare.model.OrganisationType.PRACTICE;
import static easycare.model.OrganisationType.ROOT;
import static easycare.model.OrganisationType.SLEEP_LAB;
import static easycare.model.Title.DR;
import static easycare.model.Title.MISS;
import static easycare.model.Title.MR;
import static easycare.model.Title.MRS;
import static easycare.model.Title.MS;
import static easycare.model.security.RoleEnum.ROLE_ADMIN;
import static easycare.model.security.RoleEnum.ROLE_CLINICIAN;
import static easycare.model.security.RoleEnum.ROLE_INTERPRETING_PHYSICIAN;
import static easycare.model.security.RoleEnum.ROLE_RESMED_CS;
import static easycare.util.db.generator.InsurancePolicyGeneratorHelper.createInsurancePolicies;
import static java.lang.String.format;
import static org.apache.commons.lang.StringUtils.substring;
import static org.apache.commons.lang.math.RandomUtils.nextInt;

/**
 * This class loads fake test data for testing, development and showcase
 * purposes. This should never be set in production.
 */
@Component
public class TestData {
    private static final String CARD_ONLY_PLAN_CODE = "CARD_ONLY_PLAN";

    private static final String CARD_ONLY_PLAN_NAME = "Card only";

    private static final String GLOBAL_EVERYTHING_PLAN_CODE = "GLOBAL_EVERYTHING_PLAN";

    private static final String GLOBAL_EVERYTHING_PLAN_NAME = "Global Everything Plan";

    private static final String US_COUNTRY_CODE = CountryCode.US.getCode();

    private static final Logger log = LoggerFactory.getLogger(TestData.class);

    private static final Integer INDEFINITE_TROUBLE_SHOOTING_DURATION_DAYS = null;

    private static final Integer ZERO_TROUBLE_SHOOTING_DURATION_DAYS = 0;

    private static Map<Country, List<FlowGenType>> flowGenTypesByCountry = new HashMap<>();

    private static List<CommunicationModuleType> allCommunicationsModuleTypes;

    private static List<MaskSizeType> allMasksTypes;

    private static List<AirTubingType> allAirTubingTypes;

    private static List<HumidifierType> allHumidifierTypes;

    @Setter
    private int hstPatientsPerPhysician = 5;

    @Setter
    private int hmeMinPatientsPerPhysician = 3;

    @Setter
    private int hmeMaxPatientsPerPhysician = 8;

    @Setter
    private int hmeUsPatientsPerPhysician = 10;

    @PersistenceContext(unitName = "easycare")
    private EntityManager entityManager;

    @Autowired
    private EcxIntegratorRepository ecxIntegratorRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private LocalisedFlowGenTypeRepository localisedFlowGenTypeRepository;

    @Autowired
    private FlowGenRepository flowGenRepository;

    @Autowired(required = false)
    private FlowGenService flowGenService;

    @Autowired
    private CommunicationModuleRepository communicationsModuleRepository;

    @Autowired
    private MaskSizeTypeRepository maskSizeTypeRepository;

    @Autowired
    private AirTubingRepository airTubingRepository;

    @Autowired
    private HumidifierRepository humidifierRepository;

    @Autowired
    private CountryRepository countryRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private InsurerRepository insurerRepository;

    @Autowired(required = false)
    private UserService userService;

    @Autowired
    private OrganisationRepository organisationRepository;

    @Autowired
    private HmePartnersRepository hmePartnersRepository;

    @Autowired
    private FlowGenSummaryDataRepository flowGenSummaryDataRepository;

    @Autowired
    private FlowGenSummaryDataService flowGenSummaryDataService;

    @Autowired(required = false)
    private PatientRepository patientRepository;

    @Autowired
    private PatientFlowGenRepository patientFlowGenRepository;

    @Autowired
    private IntegratorPatientRepository integratorPatientRepository;

    @Autowired
    private Clock clock;

    @Autowired
    private BillingPlanRepository billingPlanRepository;

    @Autowired
    private BillingPlanPatientRepository billingPlanPatientRepository;

    @Autowired
    private InstallSettingRepository installSettingRepository;

    @Autowired
    private EcxIntegratorGeneratorHelper ecxIntegratorGeneratorHelper;

    @Autowired
    private HstPatientGenerator hstPatientGenerator;

    @Autowired
    private PatientGroupLayoutRepository patientGroupLayoutRepository;

    @Autowired
    private PatientGroupLayoutMapRepository patientGroupLayoutMapRepository;

    @Autowired
    private GroupPatientMembershipRepository groupPatientMembershipRepository;

    @Autowired
    private GroupPatientMembershipHistoryRepository groupPatientMembershipHistoryRepository;

    @Autowired
    private GroupRuleStatRepository groupRuleStatRepository;

    @Autowired
    private PayorRepository payorRepository;

    @Autowired
    private ComplianceRuleRepository complianceRuleRepository;

    @Autowired
    private PayorComplianceRuleRepository payorComplianceRuleRepository;

    @Autowired
    private PartyRoleRepository partyRoleRepository;

    @Autowired
    private PartyRepository partyRepository;

    @Autowired
    private ApplicationDmeProviderRepository applicationDmeProviderRepository;

    @Autowired
    private OrganisationService organisationService;

    private final List<User> allUsers = new ArrayList<>();

    private List<PatientGroupLayout> patientGroupLayoutList;

    private Country us;
    private Country ca;
    private Country fr;
    private Country de;
    private Country fi;
    private Country ch;
    private Country se;
    private Country pt;
    private Country bnl;
    private Country no;
    private Country dk;
    private Country es;
    private Country it;
    private Country bi;
    private Country au;
    private Country jp;

    private Organisation resMedOrg;
    private Organisation hmeLargeUsOrg;
    private Organisation hmeSmallCaOrg;
    private Organisation hmePremiumFrenchOrg;
    private Organisation hmeBasicFrenchOrg;
    private Organisation sleepLab1;
    private Organisation sleepLab2;
    private Organisation sleepLab3;
    private Organisation sleepLabFrench;
    private Organisation practice;

    private Organisation hmeGermanOrg;
    private Organisation sleepLabGerman;

    private Organisation hmeFinnishOrg;
    private Organisation sleepLabFinnish;

    private Organisation hmeSwissOrg;
    private Organisation sleepLabSwiss;

    private Organisation hmeSwedishOrg;
    private Organisation sleepLabSwedish;

    private Organisation hmePortugueseOrg;
    private Organisation sleepLabPortuguese;

    private Organisation hmeBeneluxOrg;
    private Organisation sleepLabBenelux;

    private Organisation hmeNorwegianOrg;
    private Organisation sleepLabNorwegian;

    private Organisation hmeDanishOrg;
    private Organisation sleepLabDanish;

    private Organisation hmeSpanishOrg;
    private Organisation sleepLabSpanish;

    private Organisation hmeItalianOrg;
    private Organisation sleepLabItalian;

    private Organisation hmeBritishOrg;
    private Organisation sleepLabBritish;

    private Organisation hmeAustralianOrg;
    private Organisation sleepLabAustralian;

    private Organisation hmeJapaneseOrg;
    private Organisation sleepLabJapanese;

    private Organisation hmeUnmigratedUsOrg;
    private Organisation hmeUnmigratedFrenchOrg;
    private Organisation hmeUnmigratedGermanOrg;

    private static List<Organisation> unmigratedOrganisations = new ArrayList<Organisation>();

    private Integer currentOrgAccount = 200000;

    private static final OrganisationType[] POSSIBLE_ORG_TYPES = new OrganisationType[] { HME, SLEEP_LAB, PRACTICE,
            INTEGRATED_HME_SLEEP_LAB };

    public TestData() {
        super();
    }

    public TestData(int hmeMinPatients, int hmeMaxPatients, int hmeUSPatients, int hstPatients) {
        this.hmeMinPatientsPerPhysician = hmeMinPatients;
        this.hmeMaxPatientsPerPhysician = hmeMaxPatients;
        this.hmeUsPatientsPerPhysician = hmeUSPatients;
        this.hstPatientsPerPhysician = hstPatients;
    }

    private void createCommunicationModulesForOrganisations(Organisation... organisations) {
        for (Organisation organisation : organisations) {
            createCommunicationModulesForOrganisation(organisation);
        }
    }

    private List<CommunicationModule> createCommunicationModulesForOrganisation(Organisation organisation) {
        List<CommunicationModule> modules = new ArrayList<>();

        int maxModulesPerOrg = 10;
        for (int i = 0; i < maxModulesPerOrg; i++) {
            Faker faker = Faker.getInstance();
            CommunicationModule module = TherapyEquipmentGeneratorHelper
                    .createCommModule(allCommunicationsModuleTypes);
            module.setOrganisation(organisation);
            module.setSerialNumber(faker.commModuleSerialNumber());
            modules.add(communicationsModuleRepository.save(module));
        }
        return modules;
    }

    private void createOrganisations() {
        log.info("Generating Organisations and Locations");
        resMedOrg = organisationRepository.save(OrganisationGeneratorHelper.createOrganisation(us, "ResMed",
                "000001", ROOT, "resmed-usa-logo.gif"));
        hmeLargeUsOrg = organisationRepository.save(OrganisationGeneratorHelper.createOrganisation(us, "Large HME",
                "000002", HME, "resmed-usa-logo.gif", getPatientGroupLayout("US")));
        sleepLab1 = organisationRepository
                .save(OrganisationGeneratorHelper.createOrganisation(us, "Sleepy lab", "000003", SLEEP_LAB, null));
        sleepLab2 = organisationRepository.save(OrganisationGeneratorHelper.createOrganisation(us,
                "Westside Medical Supplies", "000004", SLEEP_LAB, null));
        practice = organisationRepository.save(
                OrganisationGeneratorHelper.createOrganisation(us, "Practical Practice", "000005", PRACTICE, null));

        hmeSmallCaOrg = organisationRepository.save(OrganisationGeneratorHelper.createOrganisation(ca, "Small HME",
                "100001", HME, null, getPatientGroupLayout("CA")));
        sleepLab3 = organisationRepository.save(OrganisationGeneratorHelper.createOrganisation(ca,
                "Green Associated Medical", "100002", SLEEP_LAB, null));
        createHmePartners(sleepLab1, hmeLargeUsOrg, hmeSmallCaOrg);
        createHmePartners(sleepLab2, hmeLargeUsOrg, hmeSmallCaOrg);
        createHmePartners(sleepLab3, hmeLargeUsOrg, hmeSmallCaOrg);
        createHmePartners(practice, hmeLargeUsOrg, hmeSmallCaOrg);

        hmeAustralianOrg = createOrganisation(au, "Australian HME", HME, null, getPatientGroupLayout("AU"));
        sleepLabAustralian = createOrganisation(au, "Australian Sleep Lab", SLEEP_LAB);
        createHmePartners(sleepLabAustralian, hmeAustralianOrg);

        hmeJapaneseOrg = organisationRepository.save(
                OrganisationGeneratorHelper.createOrganisation(jp, "Japanese HME", "000006", HME, null, null));
        sleepLabJapanese = createOrganisation(jp, "Japanese Sleep Lab", SLEEP_LAB);
        createHmePartners(sleepLabJapanese, hmeJapaneseOrg);

        hmePremiumFrenchOrg = createOrganisation(fr, "French Premium HME", HME, SubscriptionLevel.PREMIUM,
                getPatientGroupLayout("FR"));
        hmeBasicFrenchOrg = createOrganisation(fr, "French Basic HME", HME, SubscriptionLevel.BASIC,
                getPatientGroupLayout("FR"));
        sleepLabFrench = createOrganisation(fr, "French Exhaustion Lab", SLEEP_LAB);
        createHmePartners(sleepLabFrench, hmeBasicFrenchOrg, hmePremiumFrenchOrg);

        hmeGermanOrg = createOrganisation(de, "German HME", HME, null, getPatientGroupLayout("DE"));
        sleepLabGerman = createOrganisation(de, "German Sleep Lab", SLEEP_LAB);
        createHmePartners(sleepLabGerman, hmeGermanOrg);

        hmeFinnishOrg = createOrganisation(fi, "Finnish HME", HME, null, getPatientGroupLayout("FI"));
        sleepLabFinnish = createOrganisation(fi, "Finnish Sleep Lab", SLEEP_LAB);
        createHmePartners(sleepLabFinnish, hmeFinnishOrg);

        hmeSwissOrg = createOrganisation(ch, "Swiss HME", HME, null, getPatientGroupLayout("CH"));
        sleepLabSwiss = createOrganisation(ch, "Swiss Sleep Lab", SLEEP_LAB);
        createHmePartners(sleepLabSwiss, hmeSwissOrg);

        hmeSwedishOrg = createOrganisation(se, "Swedish HME", HME, null, getPatientGroupLayout("SE"));
        sleepLabSwedish = createOrganisation(se, "Swedish Sleep Lab", SLEEP_LAB);
        createHmePartners(sleepLabSwedish, hmeSwedishOrg);

        hmePortugueseOrg = createOrganisation(pt, "Portuguese HME", HME, null, getPatientGroupLayout("PT"));
        sleepLabPortuguese = createOrganisation(pt, "Portuguese Sleep Lab", SLEEP_LAB);
        createHmePartners(sleepLabPortuguese, hmePortugueseOrg);

        hmeBeneluxOrg = createOrganisation(bnl, "Benelux HME", HME, null, getPatientGroupLayout("BX"));
        sleepLabBenelux = createOrganisation(bnl, "Benelux Sleep Lab", SLEEP_LAB);
        createHmePartners(sleepLabBenelux, hmeBeneluxOrg);

        hmeNorwegianOrg = createOrganisation(no, "Norwegian HME", HME, null, getPatientGroupLayout("NO"));
        sleepLabNorwegian = createOrganisation(no, "Norwegian Sleep Lab", SLEEP_LAB);
        createHmePartners(sleepLabNorwegian, hmeNorwegianOrg);

        hmeDanishOrg = createOrganisation(dk, "Danish HME", HME, null, getPatientGroupLayout("DK"));
        sleepLabDanish = createOrganisation(dk, "Danish Sleep Lab", SLEEP_LAB);
        createHmePartners(sleepLabDanish, hmeDanishOrg);

        hmeSpanishOrg = createOrganisation(es, "Spanish HME", HME, null, getPatientGroupLayout("ES"));
        sleepLabSpanish = createOrganisation(es, "Spanish Sleep Lab", SLEEP_LAB);
        createHmePartners(sleepLabSpanish, hmeSpanishOrg);

        hmeItalianOrg = createOrganisation(it, "Italian HME", HME, null, getPatientGroupLayout("IT"));
        sleepLabItalian = createOrganisation(it, "Italian Sleep Lab", SLEEP_LAB);
        createHmePartners(sleepLabItalian, hmeItalianOrg);

        hmeBritishOrg = createOrganisation(bi, "British HME", HME, null, getPatientGroupLayout("GB"));
        sleepLabBritish = createOrganisation(bi, "British Sleep Lab", SLEEP_LAB);
        createHmePartners(sleepLabBritish, hmeBritishOrg);

        hmeUnmigratedUsOrg = createOrganisation(us, "US Unmigrated HME", HME);
        unmigratedOrganisations.add(hmeUnmigratedUsOrg);

        hmeUnmigratedFrenchOrg = createOrganisation(fr, "French Unmigrated HME", HME);
        unmigratedOrganisations.add(hmeUnmigratedFrenchOrg);

        hmeUnmigratedGermanOrg = createOrganisation(de, "German Unmigrated HME", HME);
        unmigratedOrganisations.add(hmeUnmigratedGermanOrg);

        Faker faker = Faker.getInstance();
        Set<String> orgNames = new HashSet<>();
        for (int i = 0; i < 120; i++) {
            orgNames.add(faker.company());
        }
        int accountNumberSeed = 3;
        for (String orgName : orgNames) {
            String accountNumber = format("A%09d", accountNumberSeed++);
            Organisation org = organisationRepository.save(OrganisationGeneratorHelper.createOrganisation(us,
                    orgName, accountNumber, POSSIBLE_ORG_TYPES[RandomUtils.nextInt(POSSIBLE_ORG_TYPES.length)],
                    "resmed-usa-logo.gif"));
            createUser(MR, faker.firstName(), "Generated", format("user%d", accountNumberSeed),
                    newArrayList(ROLE_ADMIN, ROLE_CLINICIAN), org);
        }

        createCommunicationModulesForOrganisations(hmePremiumFrenchOrg, hmeBasicFrenchOrg);
        createCommunicationModulesForOrganisations(hmeGermanOrg);
        createCommunicationModulesForOrganisations(hmeFinnishOrg);
        createCommunicationModulesForOrganisations(hmeSwissOrg);
        createCommunicationModulesForOrganisations(hmeSwedishOrg);
        createCommunicationModulesForOrganisations(hmePortugueseOrg);
        createCommunicationModulesForOrganisations(hmeBeneluxOrg);
        createCommunicationModulesForOrganisations(hmeNorwegianOrg);
        createCommunicationModulesForOrganisations(hmeDanishOrg);
        createCommunicationModulesForOrganisations(hmeSpanishOrg);
        createCommunicationModulesForOrganisations(hmeItalianOrg);
        createCommunicationModulesForOrganisations(hmeBritishOrg);
        createCommunicationModulesForOrganisation(hmeSmallCaOrg);
        createCommunicationModulesForOrganisation(hmeLargeUsOrg);
        createCommunicationModulesForOrganisation(hmeAustralianOrg);
        createCommunicationModulesForOrganisation(hmeJapaneseOrg);
    }

    private void unmigrateOrganisations() {
        for (Organisation organisation : unmigratedOrganisations) {
            log.info("Unmigrate Organisation: " + organisation.getName());
            ApplicationDmeProvider applicationDmeProvider = applicationDmeProviderRepository
                    .findByOrganisation(organisation);
            applicationDmeProviderRepository
                    .save(ReflectionTestUtil.setMigratedToBudapestFlag(applicationDmeProvider, false));
        }
    }

    private HmePartner createHmePartners(Organisation sleepLab, Organisation... hmeOrgs) {
        HmePartner hmePartner = null;
        for (Organisation hmeOrganisation : hmeOrgs) {
            hmePartner = new HmePartner(sleepLab, hmeOrganisation.getLocations().get(0));
            hmePartner.setNickName(substring(hmePartner.getNickName(), 0, HmePartner.NICK_NAME_MAX_LENGTH));
            hmePartner = hmePartnersRepository.save(hmePartner);
        }
        return hmePartner;
    }

    private Organisation createOrganisation(Country country, String name, OrganisationType organisationType) {
        Organisation org = OrganisationGeneratorHelper.createOrganisation(country, name, nextOrgAccount(),
                organisationType, null);
        return organisationRepository.save(org);
    }

    private Organisation createOrganisation(Country country, String name, OrganisationType type,
            SubscriptionLevel subscription, PatientGroupLayout layout) {
        Organisation org = OrganisationGeneratorHelper.createOrganisationWithSubscription(country, name,
                nextOrgAccount(), type, null, subscription, layout);
        return organisationRepository.save(org);
    }

    private InstallSetting getCurrentInstallSetting() {
        return installSettingRepository.findByType(InstallSettingType.INSTALLATION_IDENTIFIER);
    }

    private void createPatientsForUsers() throws Exception {
        log.info("Generating Patients with FlowGenSummaryData");
        Role clinician = roleRepository.findRoleByEnum(RoleEnum.ROLE_CLINICIAN);
        int patientTotalHmeCount = 0;
        int patientTotalHstCount = 0;
        for (User user : allUsers) {
            OrganisationType orgType = user.getOrganisation().getType();
            String countryCode = user.getOrganisation().getCountry().getCountryCode();
            log.info("***** Generating User: " + user.getUsername() + " Country: " + countryCode + " OrgType: "
                    + orgType + " *****");

            if (orgType == HME && user.hasRole(clinician)) {
                int patientCount;
                if (countryCode.equals("us") || countryCode.equals("ca")) {
                    patientCount = hmeUsPatientsPerPhysician;
                } else {
                    patientCount = hmeMinPatientsPerPhysician;
                    int additionalPatients = hmeMaxPatientsPerPhysician - hmeMinPatientsPerPhysician;
                    if (additionalPatients > 0) {
                        patientCount += RandomUtils.nextInt(hmeMaxPatientsPerPhysician);
                    }
                }
                for (int i = 0; i < patientCount; i++) {
                    createPatientWithUsageData(user);
                    patientTotalHmeCount++;
                }
            } else if (user.isPhysician()) {
                for (int i = 0; i < hstPatientsPerPhysician; i++) {
                    hstPatientGenerator.createHstPatient(user);
                    patientTotalHstCount++;
                }
            }
            entityManager.flush();
        }
        log.info("Created " + patientTotalHmeCount + " HME patients and " + patientTotalHstCount
                + " HST patients for " + allUsers.size() + " users.");
    }

    private void createPatientsForPatientLevelIntegrators() {
        log.info("Generating Patients with Patient Level Integrators");

        createPatientWithIntegrator("PatientLevelIntegrator1");

        createPatientWithIntegrator("PatientLevelIntegrator2");
    }

    private void createPatientWithIntegrator(String name) {
        EcxIntegrator ecxIntegrator = ecxIntegratorRepository.findByDisplayName(name);

        User clinicalUser = userRepository.findByUsernameWithContactInformation("careyl");
        ecxIntegrator.addOrganisation(clinicalUser.getOrganisation());

        Patient patient = createPatientWithUsageData(clinicalUser);
        patient.setLastName("aPatientWithAssociated");
        patient.setFirstName(name);

        saveIntegratorPatientRelationship(ecxIntegrator, patient, clinicalUser);
    }

    private void saveIntegratorPatientRelationship(EcxIntegrator integrator, Patient patient, User user) {
        LocalDateTime now = clock.getCurrentLocalDateTime();
        IntegratorPatient integratorPatient = new IntegratorPatient();
        integratorPatient.setEcxIntegrator(integrator);
        integratorPatient.setPatient(patient);
        integratorPatient.setCreatedOn(now);
        integratorPatient.setUpdatedByEcoUser(user);
        integratorPatient.setAccessPermitted(true);
        integratorPatient.setIntegrated(true);
        integratorPatient.setUpdatedOn(now);

        integratorPatientRepository.save(integratorPatient);
    }

    private void generateFlowGenReceivedTime(FlowGenSummaryData flowGenSummaryData) {
        LocalDate readingDate = flowGenSummaryData.getDate();
        int timeOfReading = nextInt(2) + 1;
        LocalDateTime time = new LocalDateTime(readingDate.plusDays(timeOfReading).toDateMidnight());
        flowGenSummaryData.setReceivedDateTime(time);
    }

    private Patient createPatientWithUsageData(User clinicalUser) {
        Organisation organisation = clinicalUser.getOrganisation();
        Country country = organisation.getCountry();
        // Generate a patient
        Patient patient = patientRepository.save(PatientGeneratorHelper.createPatientWithGeneralInformation(
                clinicalUser, organisationRepository, clock.getCurrentLocalDateTime()));

        assignDefaultPayorToPatient(patient);

        List<FlowGenType> flowGenTypes = getFlowGenTypes(country);
        FlowGen flowGen = TherapyEquipmentGeneratorHelper.createFlowGen(flowGenTypes);
        flowGen = flowGenRepository.save(flowGen);
        patient = flowGenService.assignFlowGenToPatient(patient, flowGen);

        if (MonitoringMethod.values()[RandomUtils
                .nextInt(MonitoringMethod.values().length)] == MonitoringMethod.MODULE_ACTIVE) {
            createMonitoringSchedule(patient, country);
            CommunicationModule cm = TherapyEquipmentGeneratorHelper.createCommModule(allCommunicationsModuleTypes);
            cm.setOrganisation(organisation);
            cm = communicationsModuleRepository.save(cm);
            patient.assignModule(cm, clock.getCurrentLocalDate());
        }

        // Mask / AirTubing / Humidifier
        patient.setMask(TherapyEquipmentGeneratorHelper.createMask(allMasksTypes));
        patient.setAirTubing(TherapyEquipmentGeneratorHelper.createAirTubing(allAirTubingTypes));
        patient.setHumidifier(TherapyEquipmentGeneratorHelper.createHumidifier(allHumidifierTypes));

        // Insurers
        createInsurancePolicies(patient, insurerRepository);

        patient = patientRepository.save(patient);

        // Generate FlowGenSummaryData
        List<FlowGenSummaryData> flowGenSummaryDatas = TherapyEquipmentGeneratorHelper
                .createFlowGenSummaryData(patient, flowGen);

        flowGenSummaryDataService
                .saveAndUpdateComplianceForAPatientAndPublishEvent(newAddPlan(flowGenSummaryDatas));
        List<FlowGenSummaryData> dataFix = flowGenSummaryDataRepository.findByPatientOrderByDate(patient);
        for (FlowGenSummaryData flowGenSummaryData : dataFix) {
            generateFlowGenReceivedTime(flowGenSummaryData);
            flowGenSummaryDataService.save(flowGenSummaryData);
        }

        PatientFlowGen record = patient.getCurrentAssignedFlowGen();
        FlowGenSummaryData earliestSummaryData = flowGenSummaryDataService
                .findEarliestFlowGenSummaryDataForPatient(patient);
        LocalDate earliestSummaryDataDate = (earliestSummaryData == null) ? clock.getCurrentLocalDate()
                : earliestSummaryData.getDate();

        record.assign(earliestSummaryDataDate.minusDays(RandomUtils.nextInt(180)));
        patientFlowGenRepository.save(record);

        String therapyMode = "";
        if (flowGenSummaryDatas.size() > 0) {
            therapyMode = flowGenSummaryDatas.get(0).getTherapyMode().toString();
        }

        log.info(format("%s, %s FG: %s %d %s %s", patient.getLastName(), patient.getFirstName(),
                flowGen.getType().toConnectedFGType().name(), flowGenSummaryDatas.size(), therapyMode,
                patient.getAssignedModule() == null ? "card" : "wireless"));

        return patient;
    }

    private void assignDefaultPayorToPatient(Patient patient) {
        Organisation organisation = patient.getOrganisation();
        Integer orgPartyId = partyRepository.findOrganizationPartyIdByName(organisation.getName());
        PartyRole organizationPartyRole = partyRoleRepository.findByPartyIdAndRoleType(orgPartyId,
                RoleTypeEnum.DME_PROVIDER);
        PayorDto defaultPayor = organisationRepository.findDefaultPayorForDmeProvider(organizationPartyRole);
        if (defaultPayor != null) {
            Integer payorPartyId = partyRepository.findOrganizationPartyIdByName(defaultPayor.getName());
            PartyRelationship partyRelationship = organisationRepository
                    .findPartyRelationshipByOrgAndPayorPartyId(orgPartyId, payorPartyId);
            PatientDmeProvPayorMap patientDmeProvPayorMap = new PatientDmeProvPayorMap(patient, partyRelationship);
            patientRepository.createPatientPayorRelationship(patientDmeProvPayorMap);
        }
    }

    private void createMonitoringSchedule(Patient patient, Country country) {
        if (country.equals(us) || country.equals(ca)) {
            patient.createStandardMonitoringSchedule();
        } else {
            patient.createIndefiniteMonitoringSchedule();
        }
    }

    private User createUser(Title title, String firstName, String lastName, String username,
            List<RoleEnum> roleEnums, Organisation organisation) {
        List<Role> roles = new ArrayList<>();
        for (RoleEnum roleEnum : roleEnums) {
            roles.add(roleRepository.findRoleByEnum(roleEnum));
        }

        User user = UserGeneratorHelper.createUser(title, firstName, lastName, username, organisation, roles);
        user = userService.createUserWithManualPassword(user);
        user = userService.changePassword(user, UserGeneratorHelper.DEFAULT_PASSWORD);
        user = userService.acceptLicenseAgreement(user);
        user = userService.updateUserContactInformation(user,
                organisation.getPrimaryContact().getContactInformation());
        return userRepository.save(user);
    }

    private User createUser(Title title, String firstName, String lastName, String username, RoleEnum roleEnum,
            Organisation organisation) {
        return createUser(title, firstName, lastName, username, newArrayList(roleEnum), organisation);
    }

    private void createUsers() {
        log.info("Generating Users");
        // Resmed
        allUsers.add(createUser(MRS, "Hazel", "Resmed", "hazelr", ROLE_RESMED_CS, resMedOrg));

        // Small Org
        allUsers.add(createUser(MS, "Carey", "Small", "careys", ROLE_CLINICIAN, hmeSmallCaOrg));
        allUsers.add(createUser(MR, "Jack", "AllTrades", "jackal", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeSmallCaOrg));

        // Create physicians users
        allUsers.add(createUser(MR, "Hstadmin1", "Sleeplab1", "hstadmin1", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                sleepLab1));
        allUsers.add(createUser(DR, "Hstdoc1", "Sleeplab1", "hstdoc1", newArrayList(ROLE_CLINICIAN), sleepLab1));
        allUsers.add(createUser(MR, "Hstadmin2", "Sleeplab2", "hstadmin2", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                sleepLab2));
        allUsers.add(createUser(DR, "Hstdoc2", "Sleeplab2", "hstdoc2", newArrayList(ROLE_CLINICIAN), sleepLab2));
        allUsers.add(createUser(DR, "Hstdoc3", "Sleeplab3", "hstdoc3", newArrayList(ROLE_CLINICIAN), sleepLab3));
        allUsers.add(
                createUser(DR, "Hstdocfr", "Sleeplabfr", "hstdocfr", newArrayList(ROLE_CLINICIAN), sleepLabFrench));

        // European Premium Orgs
        allUsers.add(createUser(MR, "Charles", "Alliman", "chacal", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmePremiumFrenchOrg));
        allUsers.add(createUser(MS, "Marie", "Franaise", "marief", ROLE_CLINICIAN, hmePremiumFrenchOrg));
        allUsers.add(createUser(MR, "David", "Hilbert", "davidh", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeGermanOrg));
        allUsers.add(createUser(MS, "Angela", "Merkel", "angelam", ROLE_CLINICIAN, hmeGermanOrg));
        allUsers.add(createUser(MR, "William", "Tell", "williamt", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeSwissOrg));
        allUsers.add(createUser(MS, "Stefi", "Talman", "stefit", ROLE_CLINICIAN, hmeSwissOrg));
        allUsers.add(createUser(MR, "Aarne", "Lakomaa", "aarnel", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeFinnishOrg));
        allUsers.add(createUser(MS, "Janina", "Frostell", "janinaf", ROLE_CLINICIAN, hmeFinnishOrg));
        allUsers.add(
                createUser(MR, "Axel", "Munthe", "axelm", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN), hmeSwedishOrg));
        allUsers.add(createUser(MS, "Ulrika", "Jonsson", "ulrikaj", ROLE_CLINICIAN, hmeSwedishOrg));
        allUsers.add(createUser(MR, "Pedro", "Nunes", "pedron", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmePortugueseOrg));
        allUsers.add(createUser(MS, "Abel", "Salazar", "abels", ROLE_CLINICIAN, hmePortugueseOrg));
        allUsers.add(createUser(MR, "Claude", "Barzotti", "claudeb", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeBeneluxOrg));
        allUsers.add(createUser(MS, "Sandy", "Boets", "sboets", ROLE_CLINICIAN, hmeBeneluxOrg));
        allUsers.add(createUser(MR, "Magne", "Furuholmen", "magnef", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeNorwegianOrg));
        allUsers.add(createUser(MS, "Sondre", "Lerche", "sondrel", ROLE_CLINICIAN, hmeNorwegianOrg));
        allUsers.add(
                createUser(MR, "Heri", "Joensen", "herij", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN), hmeDanishOrg));
        allUsers.add(createUser(MS, "Hurdy", "Gurdy", "hurdyg", ROLE_CLINICIAN, hmeDanishOrg));
        allUsers.add(createUser(MR, "Pablo", "Picasso", "pablop", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeSpanishOrg));
        allUsers.add(createUser(MS, "Isabel", "Coixet", "isabelc", ROLE_CLINICIAN, hmeSpanishOrg));
        allUsers.add(createUser(MR, "Rudolphe", "Valentino", "rudolphev", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeItalianOrg));
        allUsers.add(createUser(MS, "Monica", "Bellucci", "monicab", ROLE_CLINICIAN, hmeItalianOrg));
        allUsers.add(createUser(MR, "Prince", "Charles", "princec", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeBritishOrg));
        allUsers.add(createUser(MS, "Queen", "Elizabeth", "queene", ROLE_CLINICIAN, hmeBritishOrg));

        // European Basic Orgs
        allUsers.add(createUser(MR, "Adrien", "Barbier", "adrienb", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeBasicFrenchOrg));
        allUsers.add(createUser(MR, "Bruno", "Chauvet", "brunoc", ROLE_CLINICIAN, hmeBasicFrenchOrg));

        // European Sleep Labs
        allUsers.add(createUser(DR, "Darth", "Vader", "darthv", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                sleepLabFrench));
        allUsers.add(createUser(DR, "Luke", "Skywalker", "lukes", ROLE_CLINICIAN, sleepLabFrench));
        allUsers.add(
                createUser(DR, "Max", "Planck", "maxp", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN), sleepLabGerman));
        allUsers.add(createUser(DR, "Georg", "Cantor", "georgc", ROLE_CLINICIAN, sleepLabGerman));
        allUsers.add(createUser(DR, "Leonhard", "Euler", "leonharde",
                newArrayList(ROLE_CLINICIAN, ROLE_INTERPRETING_PHYSICIAN, ROLE_ADMIN), sleepLabSwiss));
        allUsers.add(createUser(DR, "Carl", "Jung", "carlj", ROLE_CLINICIAN, sleepLabSwiss));
        allUsers.add(createUser(DR, "Ingmar", "Bergman", "ingmarb",
                newArrayList(ROLE_CLINICIAN, ROLE_INTERPRETING_PHYSICIAN, ROLE_ADMIN), sleepLabSwedish));
        allUsers.add(createUser(DR, "Alfred", "Nobel", "alfredn", ROLE_CLINICIAN, sleepLabSwedish));
        allUsers.add(createUser(DR, "Linus", "Torvalds", "linust",
                newArrayList(ROLE_CLINICIAN, ROLE_INTERPRETING_PHYSICIAN, ROLE_ADMIN), sleepLabFinnish));
        allUsers.add(createUser(DR, "Ior", "Bock", "iorb", ROLE_CLINICIAN, sleepLabFinnish));
        allUsers.add(createUser(DR, "Miguel", "Torga", "miguelt",
                newArrayList(ROLE_CLINICIAN, ROLE_INTERPRETING_PHYSICIAN, ROLE_ADMIN), sleepLabPortuguese));
        allUsers.add(createUser(DR, "Gil", "Vicente", "gilv", ROLE_CLINICIAN, sleepLabPortuguese));
        allUsers.add(createUser(DR, "Tatiana", "Fabeck", "tatianaf", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                sleepLabBenelux));
        allUsers.add(createUser(DR, "Jim", "Clemes", "jimc", ROLE_CLINICIAN, sleepLabBenelux));
        allUsers.add(createUser(DR, "Hans Erik", "Husby", "hanserikh",
                newArrayList(ROLE_CLINICIAN, ROLE_INTERPRETING_PHYSICIAN, ROLE_ADMIN), sleepLabNorwegian));
        allUsers.add(createUser(DR, "Roy", "Khan", "royk", ROLE_CLINICIAN, sleepLabNorwegian));
        allUsers.add(createUser(DR, "Mia", "Lyhne", "mial",
                newArrayList(ROLE_CLINICIAN, ROLE_INTERPRETING_PHYSICIAN, ROLE_ADMIN), sleepLabDanish));
        allUsers.add(createUser(DR, "Bodil", "Ipsen", "bodili", ROLE_CLINICIAN, sleepLabDanish));
        allUsers.add(createUser(DR, "Eva", "Amaral", "evaa",
                newArrayList(ROLE_CLINICIAN, ROLE_INTERPRETING_PHYSICIAN, ROLE_ADMIN), sleepLabSpanish));
        allUsers.add(createUser(DR, "Lola", "Flores", "lolaf", ROLE_CLINICIAN, sleepLabSpanish));
        allUsers.add(createUser(DR, "Christopher", "Columbus", "christopherc",
                newArrayList(ROLE_CLINICIAN, ROLE_INTERPRETING_PHYSICIAN, ROLE_ADMIN), sleepLabItalian));
        allUsers.add(createUser(DR, "Amerigo", "Vespucci", "amerigov", ROLE_CLINICIAN, sleepLabItalian));
        allUsers.add(createUser(DR, "William", "Shakespeare", "williams", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                sleepLabBritish));
        allUsers.add(createUser(DR, "Colin", "Firth", "colinf", ROLE_CLINICIAN, sleepLabBritish));

        // Large Org
        allUsers.add(createUser(MS, "Carey", "Large", "careyl", ROLE_CLINICIAN, hmeLargeUsOrg));
        allUsers.add(createUser(MISS, "Remey", "Reimbursement", "remeyr", ROLE_CLINICIAN, hmeLargeUsOrg));
        allUsers.add(createUser(MS, "Irene", "IT", "irenei", ROLE_ADMIN, hmeLargeUsOrg));
        allUsers.add(createUser(MR, "Don", "CentreManager", "doncen", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeLargeUsOrg));

        // sleepy lab
        allUsers.add(createUser(DR, "Doctor", "Who", "doctorw",
                newArrayList(ROLE_CLINICIAN, ROLE_INTERPRETING_PHYSICIAN, ROLE_ADMIN), sleepLab1));
        allUsers.add(createUser(DR, "Doctor", "Baker", "doctorb", ROLE_CLINICIAN, sleepLab1));

        // practice
        allUsers.add(createUser(DR, "Doctor", "Knightly", "doctork", ROLE_CLINICIAN, practice));
        allUsers.add(createUser(MRS, "Nancy", "Assistant", "nancya", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                practice));

        // Australian Premium Org
        allUsers.add(createUser(MR, "Paul", "Sydney", "pauls", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeAustralianOrg));
        allUsers.add(createUser(MS, "Dana", "Sydney", "danas", ROLE_CLINICIAN, hmeAustralianOrg));

        // Australian sleepy lab
        allUsers.add(createUser(DR, "Doctor", "Sydney", "doctors",
                newArrayList(ROLE_CLINICIAN, ROLE_INTERPRETING_PHYSICIAN, ROLE_ADMIN), sleepLabAustralian));
        allUsers.add(createUser(DR, "Doctor", "Melbourne", "doctorm", ROLE_CLINICIAN, sleepLabAustralian));

        // Japanese Premium Org
        allUsers.add(createUser(MR, "Akira", "Kurosawa", "akirak", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeJapaneseOrg));
        allUsers.add(createUser(MS, "Sadako", "Sasaki", "sadakos", ROLE_CLINICIAN, hmeJapaneseOrg));

        // Japanese sleepy lab
        allUsers.add(createUser(DR, "Doctor", "Tokyo", "doctort",
                newArrayList(ROLE_CLINICIAN, ROLE_INTERPRETING_PHYSICIAN, ROLE_ADMIN), sleepLabJapanese));
        allUsers.add(createUser(DR, "Doctor", "Osaka", "doctoro", ROLE_CLINICIAN, sleepLabJapanese));

        // Unmigrated Org
        allUsers.add(createUser(MR, "Albert", "O'Connor", "alberto", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeUnmigratedUsOrg));
        allUsers.add(createUser(MS, "Priscilla", "Sauveterre", "priscillas",
                newArrayList(ROLE_CLINICIAN, ROLE_ADMIN), hmeUnmigratedFrenchOrg));
        allUsers.add(createUser(MR, "Heinz", "Aeschelman ", "heinza", newArrayList(ROLE_CLINICIAN, ROLE_ADMIN),
                hmeUnmigratedGermanOrg));

        entityManager.flush();
    }

    private List<FlowGenType> getFlowGenTypes(Country country) {
        List<FlowGenType> flowGenTypes = flowGenTypesByCountry.get(country);
        if (flowGenTypes == null) {
            flowGenTypes = retrieveS9FlowGenTypesForCountry(country);
            flowGenTypesByCountry.put(country, flowGenTypes);
        }
        return flowGenTypes;
    }

    private List<FlowGenType> retrieveS9FlowGenTypesForCountry(Country country) {
        List<LocalisedFlowGenType> allFlowGenTypes = localisedFlowGenTypeRepository.findAllByCountry(country);
        List<FlowGenType> s9FlowGenTypes = new ArrayList<>();

        for (LocalisedFlowGenType localisedFlowGenType : allFlowGenTypes) {
            s9FlowGenTypes.add(localisedFlowGenType.getFlowGenType());
        }

        return s9FlowGenTypes;
    }

    private void retrieveSeededData() {
        allCommunicationsModuleTypes = communicationsModuleRepository.findAllTypes();
        allMasksTypes = maskSizeTypeRepository.findAll();
        allAirTubingTypes = airTubingRepository.findAllAirTubingTypes();
        allHumidifierTypes = humidifierRepository.findAllHumidifierTypes();

        us = countryRepository.findByCountryCode("us");
        ca = countryRepository.findByCountryCode("ca");
        au = countryRepository.findByCountryCode("au");
        jp = countryRepository.findByCountryCode("jp");
        fr = countryRepository.findByCountryCode("fr");
        de = countryRepository.findByCountryCode("de");
        fi = countryRepository.findByCountryCode("fi");
        ch = countryRepository.findByCountryCode("ch");
        se = countryRepository.findByCountryCode("se");
        pt = countryRepository.findByCountryCode("pt");
        bnl = countryRepository.findByCountryCode("bnl");
        no = countryRepository.findByCountryCode("no");
        dk = countryRepository.findByCountryCode("dk");
        es = countryRepository.findByCountryCode("es");
        it = countryRepository.findByCountryCode("it");
        bi = countryRepository.findByCountryCode("bi");

        patientGroupLayoutList = patientGroupLayoutRepository.findAll();
    }

    private PatientGroupLayout getPatientGroupLayout(String countryCode) {
        final String code = countryCode + "Primary";
        return Iterables.find(patientGroupLayoutList, new Predicate<PatientGroupLayout>() {

            @Override
            public boolean apply(PatientGroupLayout patientGroupLayout) {

                return patientGroupLayout.getPatientGroupLayoutCode().equals(code);
            }
        });
    }

    /**
     * This method loads dummy testings data into the database. It is different
     * to seed data in that this is not data required for the app to function
     * properly, merely data to support testing. You wouldn't load this data
     * when setting up a production server, for example.
     */
    @Transactional
    public void setupTestData() throws Exception {

        if (testDataAlreadyExists()) {
            log.info("Test data already loaded");
            return;
        }

        log.info("Adding test data to database");

        retrieveSeededData();

        createOrganisations();
        unmigrateOrganisations();

        assignPayorsToHMEs();

        log.info("Generating Insurers");
        List<Organisation> orgList = excludeUnmigratedOrganisationsFromList();
        for (Organisation organisation : orgList) {
            List<Insurer> insurers = InsurerGeneratorHelper.createInsurers(organisation);
            for (Insurer insurer : insurers) {
                insurerRepository.save(insurer);
            }
        }

        BillingPlan cardOnlyBillingPlan = ensureCardOnlyBillingPlan();
        BillingPlan globalEverythingBillingPlan = ensureGlobalEverythingPlan(billingPlanRepository,
                GLOBAL_EVERYTHING_PLAN_NAME, null);
        setDefaultBillingPlanForOrganisations(cardOnlyBillingPlan, orgList);
        createUsers();
        ecxIntegratorGeneratorHelper.createEcxIntegratorList(hmeLargeUsOrg, hmeSmallCaOrg);
        createPatientsForPatientLevelIntegrators();
        createPatientsForUsers();
        assignBillingPlanToPatients(globalEverythingBillingPlan, getAllBillingPlanEligibleWirelessPatients());
        assignBillingPlanToPatients(cardOnlyBillingPlan, getAllBillingPlanEligibleCardPatients());
        randomlyAssignPatientsToPatientGroupsAndPayors();
        assignPatientToMultipleGroups("Joe");
        assignPatientToMultipleGroups("Mike");

        log.info("Adding test data completed");
    }

    private List<Patient> getAllBillingPlanEligibleWirelessPatients() {
        return patientRepository.getEntityManager()
                .createQuery("select p " + "from Patient p "
                        + "where (p.currentPatientFlowGen.flowGen.type.metaDataId = :newportMid "
                        + " or p.currentPatientFlowGen.flowGen.type.metaDataId = :lumisMid) "
                        + " and p.assignedModule.communicationModule IS NOT NULL", Patient.class)
                .setParameter("newportMid", MID.S10.value().intValue())
                .setParameter("lumisMid", MID.LUMIS.value().intValue()).getResultList();
    }

    private List<Patient> getAllBillingPlanEligibleCardPatients() {
        return patientRepository.getEntityManager()
                .createQuery("select p " + "from Patient p "
                        + "where (p.currentPatientFlowGen.flowGen.type.metaDataId = :newportMid "
                        + " or p.currentPatientFlowGen.flowGen.type.metaDataId = :lumisMid) "
                        + " and p.assignedModule.communicationModule IS NULL", Patient.class)
                .setParameter("newportMid", MID.S10.value().intValue())
                .setParameter("lumisMid", MID.LUMIS.value().intValue()).getResultList();
    }

    private BillingPlan ensureCardOnlyBillingPlan() {
        InstallSetting installationIdentifierSetting = getCurrentInstallSetting();
        if (!Seed.INSTALLATION_IDENTIFIER_US.equalsIgnoreCase(installationIdentifierSetting.getValue())
                && !Seed.INSTALLATION_IDENTIFIER_FRANCE.equalsIgnoreCase(installationIdentifierSetting.getValue())
                && !Seed.INSTALLATION_IDENTIFIER_APAC.equalsIgnoreCase(installationIdentifierSetting.getValue())) {

            throw new RuntimeException("unrecognized INSTALLATION_IDENTIFIER value: \""
                    + installationIdentifierSetting.getValue() + "\"");
        }
        // at this point a card-only billing plan may or may not exist, and if it does it may or may not match
        // the desired values for the seeded region (US vs. EU).  The differences between the plans for each region
        // are non-obvious, so rather than attempt to determine whether an existing plan is correct we just
        // get its ID (if it exists) and then save the correct values.

        final BillingPlan existingCardOnlyBillingPlan = billingPlanRepository.findByPlanName(CARD_ONLY_PLAN_NAME);
        if (Seed.INSTALLATION_IDENTIFIER_US.equalsIgnoreCase(installationIdentifierSetting.getValue())
                || Seed.INSTALLATION_IDENTIFIER_APAC.equalsIgnoreCase(installationIdentifierSetting.getValue())) {
            return createBillingPlan(existingCardOnlyBillingPlan, installationIdentifierSetting,
                    INDEFINITE_TROUBLE_SHOOTING_DURATION_DAYS);
        } else {
            return createBillingPlan(existingCardOnlyBillingPlan, installationIdentifierSetting,
                    ZERO_TROUBLE_SHOOTING_DURATION_DAYS);
        }
    }

    public static BillingPlan ensureGlobalEverythingPlan(BillingPlanRepository billingPlanRepository,
            String billingPlanName, Integer planDays) {
        final BillingPlan existingEverythingPlan = billingPlanRepository.findByPlanName(billingPlanName);
        if (existingEverythingPlan != null) {
            return existingEverythingPlan;
        }

        final BillingPlan globalEverythingPlan = new BillingPlan();
        globalEverythingPlan.setPlanName(billingPlanName);
        globalEverythingPlan.setPlanCode(GLOBAL_EVERYTHING_PLAN_CODE);
        globalEverythingPlan.setAllowedForAllOrgsFlag(true);
        globalEverythingPlan.setPlanAvailabilityStartDate(new LocalDate(2014, 1, 1));
        globalEverythingPlan.setPlanAvailabilityEndDate(null);
        globalEverythingPlan.setDataStartAtSetupFlag(true);
        globalEverythingPlan.setDataStartOffsetDays(null);
        globalEverythingPlan.setSummaryDataDurationDays(planDays);
        globalEverythingPlan.setNightProfileDurationDays(planDays);
        globalEverythingPlan.setTroubleshootingDurationDays(planDays);
        globalEverythingPlan.setCardOnlyFlag(false);

        return billingPlanRepository.save(globalEverythingPlan);
    }

    private void setDefaultBillingPlanForOrganisations(final BillingPlan plan, final List<Organisation> orgList) {
        for (final Organisation organisation : orgList) {
            organisation.setDefaultBillingPlan(plan);
        }
    }

    private void assignBillingPlanToPatients(final BillingPlan plan, final List<Patient> patientList) {
        for (final Patient patient : patientList) {
            billingPlanPatientRepository.assignPatientPlan(plan, patient, patient.getClinicalUser());
        }
    }

    private void randomlyAssignPatientsToPatientGroupsAndPayors() {
        List<Organisation> organisations = excludeJapaneseAndUnmigratedOrganisationsFromList();
        for (final Organisation org : organisations) {
            if (org.getPatientGroupLayout() == null) {
                continue;
            }

            log.info("Randomly assign patients to payors and patient groups in org: {}", org.getName());
            final PatientGroupLayout orgLayout = org.getPatientGroupLayout();
            final List<PatientGroupLayoutMap> maps = patientGroupLayoutMapRepository
                    .findAllByPatientGroupLayout(orgLayout);
            final int layoutGroupCount = maps.size();
            if (layoutGroupCount <= 0) {
                continue;
            }

            for (final Patient patient : patientRepository.findByOrg(org)) {
                final MembershipStatusTypeEnum statusType;
                final int rand = RandomUtils.nextInt(100);
                if (rand < 60) {
                    // 60% chance
                    statusType = MembershipStatusTypeEnum.IN;
                } else if (rand < 90) {
                    // 30% chance
                    statusType = MembershipStatusTypeEnum.REMOVED;
                } else {
                    // 10% chance
                    continue;
                }

                createGroupMembershipAndHistory(patient, maps.get(RandomUtils.nextInt(layoutGroupCount)),
                        statusType);
                assignPatientToRandomPayor(patient, org);
            }
        }
    }

    private List<Organisation> excludeUnmigratedOrganisationsFromList() {
        List<Organisation> organisations = organisationRepository.findAll();
        for (Organisation unmigratedOrganisation : unmigratedOrganisations) {
            organisations.remove(unmigratedOrganisation);
        }

        return organisations;
    }

    private List<Organisation> excludeJapaneseAndUnmigratedOrganisationsFromList() {
        List<Organisation> organisations = excludeUnmigratedOrganisationsFromList();
        organisations.remove(hmeJapaneseOrg);
        organisations.remove(sleepLabJapanese);

        return organisations;
    }

    private void assignPatientToMultipleGroups(String name) {

        final PatientGroupLayout orgLayout = organisationRepository.findByName("Large HME").getPatientGroupLayout();
        User clinicalUser = userRepository.findByUsernameWithContactInformation("careyl");

        Patient patient = createPatientWithUsageData(clinicalUser);
        patient.setFirstName(name);
        patient.setLastName("In6groups");

        for (PatientGroupLayoutMap patientGroupLayoutMap : patientGroupLayoutMapRepository
                .findAllByPatientGroupLayout(orgLayout)) {
            createGroupMembershipAndHistory(patient, patientGroupLayoutMap, MembershipStatusTypeEnum.IN);
        }
    }

    private void createGroupMembershipAndHistory(Patient patient, PatientGroupLayoutMap map,
            MembershipStatusTypeEnum statusType) {

        UsleepGroupRule usleepGroupRule = map.getPatientGroupLayoutMapId().getUsleepGroupRule();

        // For 10% of patients that are removed, make their membership status updated date be more than 48 hours ago
        final LocalDateTime membershipStatusUpdatedDt = statusType == MembershipStatusTypeEnum.REMOVED
                && RandomUtils.nextInt(10) < 1 ? clock.getCurrentLocalDateTime().minusHours(49)
                        : clock.getCurrentLocalDateTime();

        groupPatientMembershipRepository.save(GroupPatientMembership.builder()
                .groupPatientMembershipId(new GroupPatientMembershipId(usleepGroupRule, patient))
                .membershipStatusTypeCode(statusType.getCode()).membershipStatusUpdatedDt(membershipStatusUpdatedDt)
                .build());

        GroupPatientMembershipHistory membershipHistory = new GroupPatientMembershipHistory(
                GroupPatientMembershipHistoryId.builder().patient(patient).membershipStatusTypeCode(statusType)
                        .membershipStatusUpdatedDt(membershipStatusUpdatedDt).usleepGroupRule(usleepGroupRule)
                        .build());
        membershipHistory
                .setClinicalUser(statusType == MembershipStatusTypeEnum.IN ? null : patient.getClinicalUser());
        membershipHistory.setGroupRuleStatistic(
                statusType == MembershipStatusTypeEnum.IN ? randomlyAssignReasonAddedToGroup() : null);
        groupPatientMembershipHistoryRepository.save(membershipHistory);
    }

    private void assignPatientToRandomPayor(Patient patient, Organisation org) {
        List<PayorDto> payors = payorRepository.findAllPayorsOrderByName(org.getId());
        if (payors == null || payors.size() == 0) {
            return;
        }
        Integer orgPartyId = partyRepository.findOrganizationPartyIdByName(org.getName());

        PayorDto payor = payors.get(RandomUtils.nextInt(payors.size()));
        PartyRelationship partyRelationship = organisationRepository
                .findPartyRelationshipByOrgAndPayorPartyId(orgPartyId, payor.getPartyId());

        if (partyRelationship != null) {
            PatientDmeProvPayorMap patientDmeProvPayorMap = new PatientDmeProvPayorMap(patient, partyRelationship);
            patientRepository.createPatientPayorRelationship(patientDmeProvPayorMap);
        }
    }

    private void assignPayorsToHMEs() {
        List<Organisation> organisations = excludeJapaneseAndUnmigratedOrganisationsFromList();
        List<PayorDto> usPayors = payorRepository.findAllPayorsOrderByName(us.getId());
        int usPayorListSize = usPayors.size();

        for (final Organisation org : organisations) {
            String orgName = org.getName();

            if (!applicationDmeProviderRepository.isOrganisationMigrated(org)
                    || !orgName.toUpperCase().contains("HME")) {
                continue;
            }

            Country orgCountry = org.getCountry();
            log.info("Assign payors to HME org: {}", orgName);

            PartyRole orgPartyRole = partyRoleRepository.findByPartyIdAndRoleType(
                    partyRepository.findOrganizationPartyIdByName(orgName), RoleTypeEnum.DME_PROVIDER);
            DefaultComplianceRule defaultComplianceRule = ComplianceOptions
                    .fromCountryCode(org.getCountry().getCountryCode()).getDefaultComplianceRule();

            if (defaultComplianceRule != null) {
                ComplianceRule defaultRuleForOrgCountry = complianceRuleRepository
                        .findByCode(defaultComplianceRule.getRuleType(), defaultComplianceRule.getCode());

                ComplianceRule initialComplianceRule = complianceRuleRepository
                        .findByCountryAndRuleType(orgCountry, ComplianceRuleTypeEnum.INITIAL).get(0);
                ComplianceRule ongoingComplianceRule = complianceRuleRepository
                        .findByCountryAndRuleType(orgCountry, ComplianceRuleTypeEnum.ONGOING).get(0);

                organisationService.createDefaultPayorComplianceRule(org);
                for (int i = 0; i < 25; i++) {
                    List<ComplianceRule> ruleList = new ArrayList<>();
                    PartyRelationship partyRelationship;
                    if (orgCountry.equals(us)) {
                        partyRelationship = createDmeProviderPayorRelationship(orgPartyRole,
                                usPayors.get(RandomUtils.nextInt(usPayorListSize)));
                    } else {
                        partyRelationship = createDmeProviderDefaultPayorRelationship(orgPartyRole);
                    }

                    // Assign additional compliance rules to Payors 2, 3, and 4 to make testing more meaningful
                    switch (i) {
                    case 2:
                        ruleList.add(initialComplianceRule);
                        break;
                    case 3:
                        ruleList.add(initialComplianceRule);
                        ruleList.add(ongoingComplianceRule);
                        break;
                    case 4:
                        ruleList.add(ongoingComplianceRule);
                        break;
                    default:
                        ruleList.add(defaultRuleForOrgCountry);
                        break;
                    }
                    ComplianceRule[] ruleArray = new ComplianceRule[ruleList.size()];
                    createPayorComplianceRules(partyRelationship, ruleList.toArray(ruleArray));
                }
            }
        }
    }

    private void createPayorComplianceRules(PartyRelationship partyRelationship,
            ComplianceRule... complianceRules) {
        for (ComplianceRule rule : complianceRules) {
            payorComplianceRuleRepository
                    .createPayorComplianceRule(new PayorComplianceRuleDto(rule, partyRelationship));
        }
    }

    private PartyRelationship createDmeProviderPayorRelationship(PartyRole orgPartyRole, PayorDto payor) {
        PartyRole payorPartyRole = partyRoleRepository.findByPartyIdAndRoleType(payor.getPartyId(),
                RoleTypeEnum.PAYOR);
        return organisationRepository.createDmeProviderPayorRelationship(
                new PartyRelationship(orgPartyRole, payorPartyRole, PartyRelationshipTypeEnum.DME_PROVIDER_PAYOR));
    }

    private PartyRelationship createDmeProviderDefaultPayorRelationship(PartyRole orgPartyRole) {
        PayorDto defaultPayor = organisationRepository.findDefaultPayorForDmeProvider(orgPartyRole);
        PartyRole payorPartyRole = partyRoleRepository.findByPartyIdAndRoleType(defaultPayor.getPartyId(),
                RoleTypeEnum.PAYOR);
        return organisationRepository.createDmeProviderPayorRelationship(new PartyRelationship(orgPartyRole,
                payorPartyRole, PartyRelationshipTypeEnum.DME_PROVIDER_DEFAULT_PAYOR));
    }

    private GroupRuleStat randomlyAssignReasonAddedToGroup() {
        final int rand = RandomUtils.nextInt(4);
        GroupRuleStat groupRuleStat;
        switch (rand) {
        case 0:
            groupRuleStat = new GroupRuleStat("usage", "<", 4.0, (short) 3, (short) 5);
            break;
        case 1:
            groupRuleStat = new GroupRuleStat("mask_leak95th_percentile", ">", 12.0, (short) 5, (short) 5);
            break;
        case 2:
            groupRuleStat = new GroupRuleStat("apnea_hypopnea_index", ">=", 15D, (short) 2, (short) 5);
            break;
        default:
            groupRuleStat = new GroupRuleStat("closed_apnea_index", ">=", 10D, (short) 7, (short) 7);
            break;
        }
        return groupRuleStatRepository.save(groupRuleStat);
    }

    private boolean testDataAlreadyExists() {
        return userRepository.findByUsernameWithContactInformation("careys") != null;
    }

    private String nextOrgAccount() {
        currentOrgAccount++;
        return currentOrgAccount.toString();
    }

    public static void main(String[] args) {
        boolean success = true;
        ClassPathXmlApplicationContext context = null;
        try {
            context = new ClassPathXmlApplicationContext("classpath:easycare-properties.xml",
                    "classpath:easycare-dataloader.xml", "classpath:easycare-builder.xml",
                    "classpath:easycare-model.xml", "classpath:easycare-service.xml",
                    "classpath:easycare-email.xml", "classpath:easycare-security.xml", "classpath:easycare-ids.xml",
                    "classpath:easycare-util.xml", "classpath:easycare-report.xml",
                    "classpath:easycare-conversions.xml", "classpath:alc-services.xml",
                    "classpath:easycare-tibco-demo.xml", "classpath:easycare-activemq-demo.xml");
            TestData testData = context.getBean(TestData.class);
            parseArguments(args, testData);
            testData.setupTestData();
        } catch (Exception e) {
            log.error("Exception running DbTool", e);
            success = false;
        } finally {
            if (context != null) {
                context.close();
            }
        }

        if (!success) {
            System.exit(1);
        }
    }

    private BillingPlan createBillingPlan(final BillingPlan existingCardOnlyBillingPlan,
            InstallSetting installationIdentifierSetting, Integer troubleshootingDurationDays) {
        log.info("Setting up the card-only billing plan for the " + installationIdentifierSetting.getValue());
        // values set here need to match the migration script that creates the "Card only" plan
        final BillingPlan cardOnlyBillingPlan = new BillingPlan();
        cardOnlyBillingPlan.setPlanName(CARD_ONLY_PLAN_NAME);
        cardOnlyBillingPlan.setPlanCode(CARD_ONLY_PLAN_CODE);
        cardOnlyBillingPlan.setAllowedForAllOrgsFlag(true);
        cardOnlyBillingPlan.setPlanAvailabilityStartDate(new LocalDate(2014, 1, 1));
        cardOnlyBillingPlan.setPlanAvailabilityEndDate(null);
        cardOnlyBillingPlan.setDataStartAtSetupFlag(true);
        cardOnlyBillingPlan.setDataStartOffsetDays(null);
        cardOnlyBillingPlan.setSummaryDataDurationDays(0);
        cardOnlyBillingPlan.setNightProfileDurationDays(0);
        cardOnlyBillingPlan.setTroubleshootingDurationDays(troubleshootingDurationDays);
        cardOnlyBillingPlan.setCardOnlyFlag(true);

        if (existingCardOnlyBillingPlan != null) {
            cardOnlyBillingPlan.setId(existingCardOnlyBillingPlan.getId());
        }

        return billingPlanRepository.save(cardOnlyBillingPlan);
    }

    private static void parseArguments(String[] args, TestData testData) {
        for (String arg : args) {
            String[] options = arg.split("=");
            if (options.length == 2) {
                try {
                    int argValue = Integer.valueOf(options[1], 10);
                    switch (options[0]) {
                    case "hmeMin":
                        testData.setHmeMinPatientsPerPhysician(argValue);
                        break;
                    case "hmeMax":
                        testData.setHmeMaxPatientsPerPhysician(argValue);
                        break;
                    case "hmeUs":
                        testData.setHmeUsPatientsPerPhysician(argValue);
                        break;
                    case "hstMax":
                        testData.setHstPatientsPerPhysician(argValue);
                        break;
                    default:
                        log.warn("Ignoring unknown option = " + options[0]);
                    }
                } catch (NumberFormatException nfe) {
                    log.warn("Ignoring invalid number in option = " + options[0]);
                }
            }
        }
    }

}