Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,8 @@ src/main/environment/admin_local.properties
node_modules

# Logs
logs/
logs/
*.api-results.csv
test-results/
playwright-report/
playwright/.cache/
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.iemr.admin</groupId>
<artifactId>admin-api</artifactId>
<version>3.12.0</version>
<version>3.13.0</version>
<packaging>war</packaging>
<name>Admin-API</name>
<description>Admin Page</description>
Expand Down
6 changes: 6 additions & 0 deletions src/main/environment/admin_ci.properties
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@ springdoc.api-docs.enabled=@env.SWAGGER_DOC_ENABLED@
springdoc.swagger-ui.enabled=@env.SWAGGER_DOC_ENABLED@

cors.allowed-origins=@env.CORS_ALLOWED_ORIGINS@

# Ni-kshay device PHI password encryption key (Base64, 32 bytes); MMU-API must use the same key
nikshay.device.aes-key=@env.NIKSHAY_DEVICE_AES_KEY@
nikshay.portal.env=@env.NIKSHAY_PORTAL_ENV@
nikshay.job.cron=${NIKSHAY_JOB_CRON}
nikshay.phase.batch-size=${NIKSHAY_PHASE_BATCH_SIZE:50}
54 changes: 30 additions & 24 deletions src/main/environment/admin_docker.properties
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
# local env
# DB Connections
spring.datasource.url=${DATABASE_URL}
spring.datasource.username=${DATABASE_USERNAME}
spring.datasource.password=${DATABASE_PASSWORD}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

callcentre-server-ip=${CALLCENTRE_SERVER_IP}

videoConsultation-apikey=${SWYMED_APIKEY}
videoConsultation-base-url=${SWYMED_BASE_URL}

### Redis IP
spring.redis.host=${REDIS_HOST}
spring.main.allow-bean-definition-overriding=true
jwt.secret=${JWT_SECRET_KEY}
#ELK logging file name
logging.path=logs/
logging.file.name=${ADMIN_API_LOGGING_FILE_NAME}

common-url=${COMMON_API}

springdoc.api-docs.enabled=${SWAGGER_DOC_ENABLED}
springdoc.swagger-ui.enabled=${SWAGGER_DOC_ENABLED}
# local env
# DB Connections
spring.datasource.url=${DATABASE_URL}
spring.datasource.username=${DATABASE_USERNAME}
spring.datasource.password=${DATABASE_PASSWORD}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

callcentre-server-ip=${CALLCENTRE_SERVER_IP}

videoConsultation-apikey=${SWYMED_APIKEY}
videoConsultation-base-url=${SWYMED_BASE_URL}

### Redis IP
spring.redis.host=${REDIS_HOST}
spring.main.allow-bean-definition-overriding=true
jwt.secret=${JWT_SECRET_KEY}
#ELK logging file name
logging.path=logs/
logging.file.name=${ADMIN_API_LOGGING_FILE_NAME}

common-url=${COMMON_API}

springdoc.api-docs.enabled=${SWAGGER_DOC_ENABLED}
springdoc.swagger-ui.enabled=${SWAGGER_DOC_ENABLED}

# Ni-kshay device PHI password encryption key (Base64, 32 bytes); MMU-API must use the same key
nikshay.device.aes-key=${NIKSHAY_DEVICE_AES_KEY:}
nikshay.portal.env=${NIKSHAY_PORTAL_ENV:uat}
nikshay.job.cron=${NIKSHAY_JOB_CRON}
nikshay.phase.batch-size=${NIKSHAY_PHASE_BATCH_SIZE:50}
5 changes: 5 additions & 0 deletions src/main/environment/admin_example.properties
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,8 @@ logging.file.name=logs/admin-api.log
jwt.secret=my-32-character-ultra-secure-and-ultra-long-secret

cors.allowed-origins=http://localhost:*

nikshay.device.aes-key=${NIKSHAY_DEVICE_AES_KEY:}
nikshay.portal.env=uat
nikshay.job.cron=${NIKSHAY_JOB_CRON}
nikshay.phase.batch-size=${NIKSHAY_PHASE_BATCH_SIZE:50}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* AMRIT – Accessible Medical Records via Integrated Technologies
* Integrated EHR (Electronic Health Records) Solution
*
* Copyright (C) "Piramal Swasthya Management and Research Institute"
*
* This file is part of AMRIT.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
package com.iemr.admin.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronExpression;

import com.iemr.admin.service.nikshayphasestatus.NikshayPhaseJob;

/**
* Schedules the one Ni-kshay job (NikshayPhaseJob) with the cron expression in
* nikshay.job.cron (env NIKSHAY_JOB_CRON; Spring format: second minute hour day month
* weekday, e.g. 0 0 2 * * * for 02:00 every day). The application does not start when the
* value is missing, blank or not a valid cron expression. "-" turns the job off. A change
* needs a restart. Runs on one thread, so a run never overlaps the previous one.
*/
@Configuration
@EnableScheduling
public class NikshayJobSchedulingConfig implements SchedulingConfigurer {
private static final Logger logger = LoggerFactory.getLogger(NikshayJobSchedulingConfig.class);

static final String CRON_PROPERTY = "nikshay.job.cron";

// Spring's value for "no schedule"
private static final String CRON_DISABLED = "-";

// No default: a missing NIKSHAY_JOB_CRON stops the application at startup
@Value("${" + CRON_PROPERTY + "}")
private String cron;

@Autowired
private NikshayPhaseJob nikshayPhaseJob;

@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
String expression = cron == null ? "" : cron.trim();
if (expression.isEmpty()) {
throw new IllegalStateException(CRON_PROPERTY + " (env NIKSHAY_JOB_CRON) is not set. Set a cron expression, "
+ "e.g. 0 0 2 * * *, or - to turn the Ni-kshay job off");
}
if (CRON_DISABLED.equals(expression)) {
logger.info("{} is '-': the automatic Ni-kshay job is off", CRON_PROPERTY);
return;
}
if (!CronExpression.isValidExpression(expression)) {
throw new IllegalStateException(CRON_PROPERTY + " (env NIKSHAY_JOB_CRON) '" + expression
+ "' is not a valid cron expression (second minute hour day month weekday)");
}
taskRegistrar.addCronTask(nikshayPhaseJob::runAutomaticPhases, expression);
logger.info("Automatic Ni-kshay job scheduled with {} '{}'", CRON_PROPERTY, expression);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package com.iemr.admin.controller.nikshay;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.iemr.admin.model.nikshay.NikshayActivateRequest;
import com.iemr.admin.model.nikshay.NikshayDesignatedPhiRequest;
import com.iemr.admin.service.nikshay.NikshayDesignatedPhiService;
import com.iemr.admin.utils.response.OutputResponse;

import io.swagger.v3.oas.annotations.Operation;

/**
* Designated PHI of each Ni-kshay village, used by the transfer out phase of
* the Ni-kshay job (Module 1 of the Ni-kshay integration). Responses keep null
* fields (e.g. designationHierarchyId) so every row has the same keys.
*/
@RestController
@RequestMapping(value = "/nikshay/designatedPhi")
public class NikshayDesignatedPhiController {
private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());

private static final Gson GSON = new GsonBuilder().serializeNulls().create();

@Autowired
private NikshayDesignatedPhiService nikshayDesignatedPhiService;

@Operation(summary = "Save a designated PHI for a village (a village can have several); saving the same village, TBU and PHI again updates it")
@PostMapping(value = "/save", produces = "application/json", headers = "Authorization")
public String saveDesignatedPhi(@RequestBody NikshayDesignatedPhiRequest request) {
OutputResponse response = new OutputResponse();
try {
response.setResponse(GSON.toJson(nikshayDesignatedPhiService.saveDesignatedPhi(request)));
} catch (Exception e) {
logger.error("saveDesignatedPhi failed: " + e.getMessage(), e);
response.setError(e);
}
return response.toStringWithSerialization();
}

@Operation(summary = "Update a designated PHI mapping by id; only the fields sent (not null) are changed")
@PostMapping(value = "/update", produces = "application/json", headers = "Authorization")
public String updateDesignatedPhi(@RequestBody NikshayDesignatedPhiRequest request) {
OutputResponse response = new OutputResponse();
try {
response.setResponse(GSON.toJson(nikshayDesignatedPhiService.updateDesignatedPhi(request)));
} catch (Exception e) {
logger.error("updateDesignatedPhi failed: " + e.getMessage(), e);
response.setError(e);
}
return response.toStringWithSerialization();
}

@Operation(summary = "Activate / deactivate a designated PHI mapping")
@PostMapping(value = "/activate", produces = "application/json", headers = "Authorization")
public String setActive(@RequestBody NikshayActivateRequest request) {
OutputResponse response = new OutputResponse();
try {
response.setResponse(GSON.toJson(nikshayDesignatedPhiService.setActive(request)));
} catch (Exception e) {
logger.error("setActive designated PHI failed: " + e.getMessage(), e);
response.setError(e);
}
return response.toStringWithSerialization();
}

@Operation(summary = "Mark a designated PHI mapping inactive by id (body: id, updatedBy)")
@PostMapping(value = "/markInactive", produces = "application/json", headers = "Authorization")
public String markInactive(@RequestBody NikshayActivateRequest request) {
OutputResponse response = new OutputResponse();
try {
response.setResponse(GSON.toJson(nikshayDesignatedPhiService.markInactive(request)));
} catch (Exception e) {
logger.error("markInactive designated PHI failed: " + e.getMessage(), e);
response.setError(e);
}
return response.toStringWithSerialization();
}

@Operation(summary = "Get designated PHI by village, TBU or district. unmappedOnly=true lists villages "
+ "without an active designated PHI; activeOnly=false includes inactive rows")
@GetMapping(value = "/get", produces = "application/json", headers = "Authorization")
public String getDesignatedPhi(@RequestParam(value = "villageId", required = false) Integer villageId,
@RequestParam(value = "tbuId", required = false) Integer tbuId,
@RequestParam(value = "districtId", required = false) Integer districtId,
@RequestParam(value = "activeOnly", required = false, defaultValue = "true") Boolean activeOnly,
@RequestParam(value = "unmappedOnly", required = false, defaultValue = "false") Boolean unmappedOnly) {
OutputResponse response = new OutputResponse();
try {
response.setResponse(GSON.toJson(
nikshayDesignatedPhiService.getDesignatedPhi(villageId, tbuId, districtId, activeOnly, unmappedOnly)));
} catch (Exception e) {
logger.error("getDesignatedPhi failed: " + e.getMessage(), e);
response.setError(e);
}
return response.toStringWithSerialization();
}

@Operation(summary = "Get all designated PHI mappings; activeOnly=true leaves out inactive rows")
@GetMapping(value = "/getAll", produces = "application/json", headers = "Authorization")
public String getAllDesignatedPhi(
@RequestParam(value = "activeOnly", required = false, defaultValue = "false") Boolean activeOnly) {
OutputResponse response = new OutputResponse();
try {
response.setResponse(GSON.toJson(nikshayDesignatedPhiService.getAllDesignatedPhi(activeOnly)));
} catch (Exception e) {
logger.error("getAllDesignatedPhi failed: " + e.getMessage(), e);
response.setError(e);
}
return response.toStringWithSerialization();
}
}
Loading
Loading