diff --git a/avni-server-api/src/main/java/org/avni/server/dao/OrganisationCategoryRepository.java b/avni-server-api/src/main/java/org/avni/server/dao/OrganisationCategoryRepository.java new file mode 100644 index 000000000..16b384118 --- /dev/null +++ b/avni-server-api/src/main/java/org/avni/server/dao/OrganisationCategoryRepository.java @@ -0,0 +1,16 @@ +package org.avni.server.dao; + +import org.avni.server.domain.organisation.OrganisationCategory; +import org.springframework.data.repository.query.Param; +import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import org.springframework.data.rest.core.annotation.RestResource; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +@RepositoryRestResource(collectionResourceRel = "organisationCategory", path = "organisationCategory") +public interface OrganisationCategoryRepository extends AvniJpaRepository, CHSRepository { + @RestResource(path = "findAllById", rel = "findAllById") + List findByIdIn(@Param("ids") Long[] ids); +} diff --git a/avni-server-api/src/main/java/org/avni/server/dao/OrganisationStatusRepository.java b/avni-server-api/src/main/java/org/avni/server/dao/OrganisationStatusRepository.java new file mode 100644 index 000000000..6bc96a9e2 --- /dev/null +++ b/avni-server-api/src/main/java/org/avni/server/dao/OrganisationStatusRepository.java @@ -0,0 +1,16 @@ +package org.avni.server.dao; + +import org.avni.server.domain.organisation.OrganisationStatus; +import org.springframework.data.repository.query.Param; +import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import org.springframework.data.rest.core.annotation.RestResource; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +@RepositoryRestResource(collectionResourceRel = "organisationStatus", path = "organisationStatus") +public interface OrganisationStatusRepository extends AvniJpaRepository, CHSRepository { + @RestResource(path = "findAllById", rel = "findAllById") + List findByIdIn(@Param("ids") Long[] ids); +} diff --git a/avni-server-api/src/main/java/org/avni/server/domain/Organisation.java b/avni-server-api/src/main/java/org/avni/server/domain/Organisation.java index 7acec03b5..aacc528b8 100644 --- a/avni-server-api/src/main/java/org/avni/server/domain/Organisation.java +++ b/avni-server-api/src/main/java/org/avni/server/domain/Organisation.java @@ -26,11 +26,11 @@ public class Organisation extends ETLEntity { private Account account; @NotNull - @Enumerated(EnumType.STRING) + @ManyToOne(fetch = FetchType.EAGER) private OrganisationCategory category; @NotNull - @Enumerated(EnumType.STRING) + @ManyToOne(fetch = FetchType.EAGER) private OrganisationStatus status; public Organisation() { @@ -86,14 +86,20 @@ public String getEffectiveUsernameSuffix() { return usernameSuffix == null ? getDbUser() : usernameSuffix; } + @JsonIgnore public OrganisationCategory getCategory() { return category; } + public Long getCategoryId() { + return category.getId(); + } + public void setCategory(OrganisationCategory organisationCategory) { this.category = organisationCategory; } + @JsonIgnore public OrganisationStatus getStatus() { return status; } @@ -101,4 +107,8 @@ public OrganisationStatus getStatus() { public void setStatus(OrganisationStatus status) { this.status = status; } + + public Long getStatusId() { + return status.getId(); + } } diff --git a/avni-server-api/src/main/java/org/avni/server/domain/organisation/OrganisationCategory.java b/avni-server-api/src/main/java/org/avni/server/domain/organisation/OrganisationCategory.java index fbf5f7fab..c38282fe4 100644 --- a/avni-server-api/src/main/java/org/avni/server/domain/organisation/OrganisationCategory.java +++ b/avni-server-api/src/main/java/org/avni/server/domain/organisation/OrganisationCategory.java @@ -1,5 +1,19 @@ package org.avni.server.domain.organisation; -public enum OrganisationCategory { - Production, UAT, Prototype, Temporary, Trial +import org.avni.server.domain.CHSEntity; + +import javax.persistence.Entity; + +@Entity +public class OrganisationCategory extends CHSEntity { + public static final String Production = "Production"; + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } diff --git a/avni-server-api/src/main/java/org/avni/server/domain/organisation/OrganisationStatus.java b/avni-server-api/src/main/java/org/avni/server/domain/organisation/OrganisationStatus.java index f4fabec0f..eff982d21 100644 --- a/avni-server-api/src/main/java/org/avni/server/domain/organisation/OrganisationStatus.java +++ b/avni-server-api/src/main/java/org/avni/server/domain/organisation/OrganisationStatus.java @@ -1,5 +1,18 @@ package org.avni.server.domain.organisation; -public enum OrganisationStatus { - Archived, Live +import org.avni.server.domain.CHSEntity; + +import javax.persistence.Entity; + +@Entity +public class OrganisationStatus extends CHSEntity { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } diff --git a/avni-server-api/src/main/java/org/avni/server/framework/rest/RepositoryConfig.java b/avni-server-api/src/main/java/org/avni/server/framework/rest/RepositoryConfig.java index 4e7604e55..336de246c 100644 --- a/avni-server-api/src/main/java/org/avni/server/framework/rest/RepositoryConfig.java +++ b/avni-server-api/src/main/java/org/avni/server/framework/rest/RepositoryConfig.java @@ -3,6 +3,8 @@ import org.avni.server.domain.*; import org.avni.server.domain.accessControl.GroupPrivilege; import org.avni.server.domain.accessControl.Privilege; +import org.avni.server.domain.organisation.OrganisationCategory; +import org.avni.server.domain.organisation.OrganisationStatus; import org.springframework.context.annotation.Configuration; import org.springframework.data.rest.core.config.RepositoryRestConfiguration; import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurerAdapter; @@ -37,6 +39,8 @@ public void configureRepositoryRestConfiguration(RepositoryRestConfiguration con config.exposeIdsFor(CommentThread.class); config.exposeIdsFor(RuleFailureTelemetry.class); config.exposeIdsFor(Individual.class); + config.exposeIdsFor(OrganisationCategory.class); + config.exposeIdsFor(OrganisationStatus.class); //TODO /** diff --git a/avni-server-api/src/main/java/org/avni/server/web/ImplementationController.java b/avni-server-api/src/main/java/org/avni/server/web/ImplementationController.java index ba4ff1530..ac98b5080 100644 --- a/avni-server-api/src/main/java/org/avni/server/web/ImplementationController.java +++ b/avni-server-api/src/main/java/org/avni/server/web/ImplementationController.java @@ -109,7 +109,7 @@ public ResponseEntity delete(@Param("deleteMetadata") boolean deleteMetadata) { return new ResponseEntity<>("Super admin cannot delete implementation data", HttpStatus.FORBIDDEN); } Organisation organisation = organisationService.getCurrentOrganisation(); - if (OrganisationCategory.Production.equals(organisation.getCategory())) { + if (OrganisationCategory.Production.equals(organisation.getCategory().getName())) { return new ResponseEntity<>("Production organisation's data cannot be deleted", HttpStatus.CONFLICT); } diff --git a/avni-server-api/src/main/java/org/avni/server/web/OrganisationController.java b/avni-server-api/src/main/java/org/avni/server/web/OrganisationController.java index 44543564a..c6fc8a43e 100644 --- a/avni-server-api/src/main/java/org/avni/server/web/OrganisationController.java +++ b/avni-server-api/src/main/java/org/avni/server/web/OrganisationController.java @@ -26,14 +26,18 @@ public class OrganisationController implements RestControllerResourceProcessor privileges; private boolean isAdmin; + private String organisationCategoryName; private UserInfoWebResponse() { } @@ -29,7 +29,7 @@ public static UserInfoWebResponse createForAdminUser(List getPrivileges() { @@ -62,7 +62,7 @@ public void setLastSessionTime(long lastSessionTime) { this.lastSessionTime = lastSessionTime; } - public OrganisationCategory getOrganisationCategory() { - return organisationCategory; + public String getOrganisationCategoryName() { + return organisationCategoryName; } } diff --git a/avni-server-api/src/main/resources/db/migration/V1_339_3__OrgCategoryTable.sql b/avni-server-api/src/main/resources/db/migration/V1_339_3__OrgCategoryTable.sql new file mode 100644 index 000000000..2ad596539 --- /dev/null +++ b/avni-server-api/src/main/resources/db/migration/V1_339_3__OrgCategoryTable.sql @@ -0,0 +1,30 @@ +create table if not exists organisation_category +( + id serial primary key, + uuid varchar(255) not null, + is_voided boolean NOT NULL DEFAULT FALSE, + name varchar(255) not null, + created_date_time timestamp(3) with time zone not null, + last_modified_date_time timestamp(3) with time zone not null, + created_by_id int not null, + last_modified_by_id int not null +); + +insert into organisation_category (uuid, name, created_date_time, last_modified_date_time, created_by_id, last_modified_by_id) +values ('71e1bf3b-48fb-4d4f-90f3-71c39e15fbf0', 'Production', now(), now(), 1, 1), + ('95e89458-c152-4557-9929-85f1a275d6a3', 'UAT', now(), now(), 1, 1), + ('283af4ea-0024-4440-857f-c8a82328a61d', 'Prototype', now(), now(), 1, 1), + ('f0b0a48d-8d4b-4d13-8956-c1bc577b4971', 'Temporary', now(), now(), 1, 1), + ('470ecdab-f7be-4336-a52a-1fa280080168', 'Trial', now(), now(), 1, 1), + ('d75e667e-b7ea-40dd-8d85-1328943d3b65', 'Training', now(), now(), 1, 1), + ('27eeb3e7-2396-45ac-ba50-b1b50690bcfc', 'Dev', now(), now(), 1, 1); + +alter table organisation add column if not exists category_id int null; + +update organisation set category_id = organisation_category.id +from organisation_category +where organisation.category = organisation_category.name; + +alter table organisation drop column category; + +alter table organisation alter column category_id set not null; diff --git a/avni-server-api/src/main/resources/db/migration/V1_339_4__OrgStatusTable.sql b/avni-server-api/src/main/resources/db/migration/V1_339_4__OrgStatusTable.sql new file mode 100644 index 000000000..a6696e0b6 --- /dev/null +++ b/avni-server-api/src/main/resources/db/migration/V1_339_4__OrgStatusTable.sql @@ -0,0 +1,25 @@ +create table if not exists organisation_status +( + id serial primary key, + uuid varchar(255) not null, + is_voided boolean NOT NULL DEFAULT FALSE, + name varchar(255) not null, + created_date_time timestamp(3) with time zone not null, + last_modified_date_time timestamp(3) with time zone not null, + created_by_id int not null, + last_modified_by_id int not null +); + +insert into organisation_status (uuid, name, created_date_time, last_modified_date_time, created_by_id, last_modified_by_id) +values ('338be2e2-d0e5-4186-b113-b8197ce879c5', 'Live', now(), now(), 1, 1), + ('7e609db3-ff79-472c-8f28-5b12933faaf5', 'Archived', now(), now(), 1, 1); + +alter table organisation add column if not exists status_id int null; + +update organisation set status_id = organisation_status.id +from organisation_status +where organisation.status = organisation_status.name; + +alter table organisation drop column status; + +alter table organisation alter column status_id set not null; diff --git a/avni-server-api/src/main/resources/db/migration/V1_339_5__AddVersions.sql b/avni-server-api/src/main/resources/db/migration/V1_339_5__AddVersions.sql new file mode 100644 index 000000000..d06be3898 --- /dev/null +++ b/avni-server-api/src/main/resources/db/migration/V1_339_5__AddVersions.sql @@ -0,0 +1,2 @@ +alter table organisation_category add column if not exists version int not null default 1; +alter table organisation_status add column if not exists version int not null default 1; diff --git a/avni-server-api/src/test/java/org/avni/server/domain/factory/TestOrganisationBuilder.java b/avni-server-api/src/test/java/org/avni/server/domain/factory/TestOrganisationBuilder.java index 3071c7b5f..6729f5939 100644 --- a/avni-server-api/src/test/java/org/avni/server/domain/factory/TestOrganisationBuilder.java +++ b/avni-server-api/src/test/java/org/avni/server/domain/factory/TestOrganisationBuilder.java @@ -12,7 +12,7 @@ public class TestOrganisationBuilder { public TestOrganisationBuilder withMandatoryFields() { String placeholder = UUID.randomUUID().toString(); - return withUuid(placeholder).withDbUser("testDbUser").withName(placeholder).withSchemaName(placeholder).setCategory(OrganisationCategory.Production).withStatus(OrganisationStatus.Live); + return withUuid(placeholder).withDbUser("testDbUser").withName(placeholder).withSchemaName(placeholder); } public TestOrganisationBuilder setId(long id) { diff --git a/avni-server-api/src/test/java/org/avni/server/service/builder/TestDataSetupService.java b/avni-server-api/src/test/java/org/avni/server/service/builder/TestDataSetupService.java index 58d556696..d7822a58e 100644 --- a/avni-server-api/src/test/java/org/avni/server/service/builder/TestDataSetupService.java +++ b/avni-server-api/src/test/java/org/avni/server/service/builder/TestDataSetupService.java @@ -31,12 +31,20 @@ public class TestDataSetupService { private TestLocationService testLocationService; @Autowired private TestCatchmentService testCatchmentService; + @Autowired + private OrganisationCategoryRepository organisationCategoryRepository; + @Autowired + private OrganisationStatusRepository organisationStatusRepository; public TestOrganisationData setupOrganisation(String orgSuffix) { Group group = new TestGroupBuilder().withMandatoryFieldsForNewEntity().build(); User user1 = new UserBuilder().withDefaultValuesForNewEntity().userName(String.format("user@%s", orgSuffix)).withAuditUser(userRepository.getDefaultSuperAdmin()).build(); User user2 = new UserBuilder().withDefaultValuesForNewEntity().userName(String.format("user2@%s", orgSuffix)).withAuditUser(userRepository.getDefaultSuperAdmin()).build(); - Organisation organisation = new TestOrganisationBuilder().withMandatoryFields().withAccount(accountRepository.getDefaultAccount()).build(); + Organisation organisation = new TestOrganisationBuilder() + .setCategory(organisationCategoryRepository.findEntity(1L)) + .withStatus(organisationStatusRepository.findEntity(1L)) + .withMandatoryFields() + .withAccount(accountRepository.getDefaultAccount()).build(); testOrganisationService.createOrganisation(organisation, user1); testOrganisationService.createUser(organisation, user2); userRepository.save(new UserBuilder(user1).withAuditUser(user1).build()); diff --git a/avni-server-api/src/test/java/org/avni/server/service/builder/TestOrganisationSetupService.java b/avni-server-api/src/test/java/org/avni/server/service/builder/TestOrganisationSetupService.java index eef88ec57..4bfc44924 100644 --- a/avni-server-api/src/test/java/org/avni/server/service/builder/TestOrganisationSetupService.java +++ b/avni-server-api/src/test/java/org/avni/server/service/builder/TestOrganisationSetupService.java @@ -29,6 +29,10 @@ public class TestOrganisationSetupService { private AccountRepository accountRepository; @Autowired private UserRepository userRepository; + @Autowired + private OrganisationCategoryRepository organisationCategoryRepository; + @Autowired + private OrganisationStatusRepository organisationStatusRepository; private Group group; private User user; @@ -36,7 +40,11 @@ public class TestOrganisationSetupService { public void setupOrganisation(AbstractControllerIntegrationTest abstractControllerIntegrationTest) { group = new TestGroupBuilder().withMandatoryFieldsForNewEntity().build(); user = new UserBuilder().withDefaultValuesForNewEntity().userName("user@example").withAuditUser(userRepository.getDefaultSuperAdmin()).build(); - Organisation organisation = new TestOrganisationBuilder().withMandatoryFields().withAccount(accountRepository.getDefaultAccount()).build(); + Organisation organisation = new TestOrganisationBuilder() + .withMandatoryFields() + .setCategory(organisationCategoryRepository.findEntity(1L)) + .withStatus(organisationStatusRepository.findEntity(1L)) + .withAccount(accountRepository.getDefaultAccount()).build(); testOrganisationService.createOrganisation(organisation, user); userRepository.save(new UserBuilder(user).withAuditUser(user).build()); abstractControllerIntegrationTest.setUser(user.getUsername()); diff --git a/avni-server-api/src/test/resources/test-data-openchs-organisation.sql b/avni-server-api/src/test/resources/test-data-openchs-organisation.sql index 6bb9ab24e..07975de20 100644 --- a/avni-server-api/src/test/resources/test-data-openchs-organisation.sql +++ b/avni-server-api/src/test/resources/test-data-openchs-organisation.sql @@ -1,35 +1,67 @@ -DELETE FROM form_element; -DELETE FROM form_element_group; -DELETE FROM form_mapping; -DELETE FROM form; -DELETE FROM encounter; -DELETE FROM program_encounter; -DELETE FROM program_enrolment; -DELETE FROM individual; -DELETE FROM program; -DELETE FROM encounter_type; -DELETE FROM concept_answer; -DELETE FROM concept; -DELETE FROM individual_relationship; -DELETE FROM individual_relationship_type; -DELETE FROM individual_relation_gender_mapping; -DELETE FROM individual_relation; -DELETE FROM gender; -DELETE FROM catchment_address_mapping; -DELETE FROM address_level; -DELETE FROM catchment; -DELETE FROM account_admin; -delete from user_group; -DELETE FROM external_system_config; -DELETE FROM organisation_config; -DELETE from message_request_queue; -DELETE from message_receiver; -DELETE from message_rule; -DELETE FROM users; -DELETE FROM subject_type; -DELETE FROM groups; -DELETE FROM group_privilege; -DELETE FROM organisation; +DELETE +FROM form_element; +DELETE +FROM form_element_group; +DELETE +FROM form_mapping; +DELETE +FROM form; +DELETE +FROM encounter; +DELETE +FROM program_encounter; +DELETE +FROM program_enrolment; +DELETE +FROM individual; +DELETE +FROM program; +DELETE +FROM encounter_type; +DELETE +FROM concept_answer; +DELETE +FROM concept; +DELETE +FROM individual_relationship; +DELETE +FROM individual_relationship_type; +DELETE +FROM individual_relation_gender_mapping; +DELETE +FROM individual_relation; +DELETE +FROM gender; +DELETE +FROM catchment_address_mapping; +DELETE +FROM address_level; +DELETE +FROM catchment; +DELETE +FROM account_admin; +delete +from user_group; +DELETE +FROM external_system_config; +DELETE +FROM organisation_config; +DELETE +from message_request_queue; +DELETE +from message_receiver; +DELETE +from message_rule; +DELETE +FROM users; +DELETE +FROM subject_type; +DELETE +FROM groups; +DELETE +FROM group_privilege; +DELETE +FROM organisation; ALTER SEQUENCE form_element_id_seq RESTART WITH 1; ALTER SEQUENCE form_element_group_id_seq RESTART WITH 1; @@ -54,8 +86,8 @@ ALTER SEQUENCE individual_relation_gender_mapping_id_seq RESTART WITH 1; ALTER SEQUENCE individual_relationship_type_id_seq RESTART WITH 1; ALTER SEQUENCE individual_relationship_id_seq RESTART WITH 1; -INSERT INTO organisation (id, name, db_user, media_directory, uuid, schema_name) -VALUES (1, 'OpenCHS', 'openchs', 'openchs_impl', '3539a906-dfae-4ec3-8fbb-1b08f35c3884', 'openchs'); +INSERT INTO organisation (id, name, db_user, media_directory, uuid, schema_name, category_id, status_id) +VALUES (1, 'OpenCHS', 'openchs', 'openchs_impl', '3539a906-dfae-4ec3-8fbb-1b08f35c3884', 'openchs', 1, 1); INSERT INTO users (id, username, uuid, organisation_id, operating_individual_scope, name) VALUES (1, 'admin', '5fed2907-df3a-4867-aef5-c87f4c78a31a', 1, 'None', 'admin'); diff --git a/avni-server-api/src/test/resources/test-data.sql b/avni-server-api/src/test/resources/test-data.sql index 8c58b2fc8..f9e4b2d94 100644 --- a/avni-server-api/src/test/resources/test-data.sql +++ b/avni-server-api/src/test/resources/test-data.sql @@ -67,14 +67,14 @@ ALTER SEQUENCE message_receiver_id_seq RESTART WITH 1; ALTER SEQUENCE message_request_queue_id_seq RESTART WITH 1; ALTER SEQUENCE message_rule_id_seq RESTART WITH 1; -INSERT into organisation(id, name, db_user, uuid, media_directory, parent_organisation_id, schema_name) -values (1, 'OpenCHS', 'openchs', '3539a906-dfae-4ec3-8fbb-1b08f35c3884', 'openchs_impl', null, 'openchs') +INSERT into organisation(id, name, db_user, uuid, media_directory, parent_organisation_id, schema_name, category_id, status_id) +values (1, 'OpenCHS', 'openchs', '3539a906-dfae-4ec3-8fbb-1b08f35c3884', 'openchs_impl', null, 'openchs', 1, 1) ON CONFLICT (uuid) DO NOTHING; select create_db_user('demo', 'password'); -INSERT INTO organisation(id, name, db_user, media_directory, uuid, parent_organisation_id, schema_name) -VALUES (2, 'demo', 'demo', 'demo', 'ae0e4ac4-681d-45f2-8bdd-2b09a5a1a6e5', 1, 'demo') +INSERT INTO organisation(id, name, db_user, media_directory, uuid, parent_organisation_id, schema_name, category_id, status_id) +VALUES (2, 'demo', 'demo', 'demo', 'ae0e4ac4-681d-45f2-8bdd-2b09a5a1a6e5', 1, 'demo', 1, 1) ON CONFLICT (uuid) DO NOTHING; insert into organisation_config (uuid, organisation_id, settings, version, is_voided, worklist_updation_rule, created_by_id, last_modified_by_id, created_date_time, last_modified_date_time) @@ -82,8 +82,8 @@ values ('5bd9c67e-c949-4872-9763-daeab7b48b1b', 1, '{"enableMessaging": true}', select create_db_user('a_demo', 'password'); -INSERT INTO organisation (id, name, db_user, media_directory, uuid, parent_organisation_id, schema_name) -VALUES (3, 'a-demo', 'a_demo', 'a-demo', '2734f2ba-610b-49f8-b8d3-4196a460e325', 1, 'a_demo') +INSERT INTO organisation (id, name, db_user, media_directory, uuid, parent_organisation_id, schema_name, category_id, status_id) +VALUES (3, 'a-demo', 'a_demo', 'a-demo', '2734f2ba-610b-49f8-b8d3-4196a460e325', 1, 'a_demo', 1, 1) ON CONFLICT (uuid) DO NOTHING; insert into subject_type(id, uuid, name, organisation_id, created_by_id, last_modified_by_id, created_date_time, last_modified_date_time)