diff --git a/.github/workflows/swagger-json.yml b/.github/workflows/swagger-json.yml
new file mode 100644
index 000000000..2c2fb910a
--- /dev/null
+++ b/.github/workflows/swagger-json.yml
@@ -0,0 +1,106 @@
+name: Sync Swagger to AMRIT-Docs
+
+on:
+ push:
+ branches: [ main ]
+ workflow_dispatch:
+
+jobs:
+ swagger-sync:
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+
+ steps:
+ - name: Checkout API repo
+ uses: actions/checkout@v4
+
+ - name: Set up Java 17
+ uses: actions/setup-java@v4
+ with:
+ distribution: temurin
+ java-version: 17
+ cache: maven
+
+ - name: Build API (skip tests)
+ run: mvn -B clean package -DskipTests -DENV_VAR=local -Pswagger
+
+ - name: Install jq
+ run: sudo apt-get update && sudo apt-get install -y jq
+
+ - name: Run API in swagger profile
+ run: |
+ nohup java -jar target/flw-api-*.war \
+ --spring.profiles.active=swagger \
+ --server.port=9090 \
+ > app.log 2>&1 &
+ echo $! > api_pid.txt
+
+ - name: Wait for API & fetch Swagger
+ run: |
+ for i in {1..40}; do
+ CODE=$(curl --connect-timeout 2 --max-time 5 -s -o swagger_raw.json -w "%{http_code}" http://localhost:9090/v3/api-docs || true)
+
+ if [ "$CODE" = "200" ]; then
+ jq . swagger_raw.json > flw-api.json || {
+ echo "Swagger JSON invalid"
+ cat swagger_raw.json
+ exit 1
+ }
+
+ if [ "$(jq '.paths | length' flw-api.json)" -eq 0 ]; then
+ echo "Swagger paths empty – failing"
+ exit 1
+ fi
+
+ echo "Swagger generated successfully"
+ exit 0
+ fi
+
+ echo "Waiting for API... ($i)"
+ sleep 4
+ done
+
+ echo "Swagger not generated"
+ cat app.log || true
+ exit 1
+
+ - name: Stop API
+ if: always()
+ run: |
+ # Kill the process directly by PID (process-group kill is unreliable in CI)
+ sleep 5
+ if [ -f api_pid.txt ]; then
+ PID=$(cat api_pid.txt)
+ kill -TERM "$PID" 2>/dev/null || true
+ sleep 2
+ kill -9 "$PID" 2>/dev/null || true
+ fi
+ # Fallback: kill any remaining java process on port 9090
+ fuser -k 9090/tcp 2>/dev/null || true
+
+ - name: Checkout AMRIT-Docs
+ uses: actions/checkout@v4
+ with:
+ repository: PSMRI/AMRIT-Docs
+ token: ${{ secrets.DOCS_REPO_TOKEN }}
+ path: amrit-docs
+ fetch-depth: 0
+
+ - name: Copy Swagger JSON
+ run: |
+ mkdir -p amrit-docs/docs/swagger
+ cp flw-api.json amrit-docs/docs/swagger/flw-api.json
+
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@v8
+ with:
+ token: ${{ secrets.DOCS_REPO_TOKEN }}
+ path: amrit-docs
+ branch: auto/swagger-update-flw-api
+ base: main
+ commit-message: "chore(docs): auto-update FLW-API swagger"
+ title: "chore(docs): auto-update FLW-API swagger"
+ delete-branch: true
+ body: |
+ This PR automatically updates FLW-API Swagger JSON
+ from the latest main branch build.
diff --git a/.github/workflows/testcase-coverage.yml b/.github/workflows/testcase-coverage.yml
new file mode 100644
index 000000000..5e71c85c6
--- /dev/null
+++ b/.github/workflows/testcase-coverage.yml
@@ -0,0 +1,44 @@
+name: TestCase Coverage Check
+
+on:
+ pull_request:
+ types: [opened, synchronize]
+
+permissions: {}
+
+jobs:
+ build_and_check_coverage:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+
+ - name: Cache Maven dependencies
+ uses: actions/cache@v3
+ with:
+ path: ~/.m2
+ key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
+ restore-keys: |
+ ${{ runner.os }}-m2-
+
+ - name: Build with Maven
+ run: mvn clean verify
+
+ - name: Run Coverage Check
+ uses: madrapps/jacoco-report@v1.7.2
+ with:
+ paths: target/site/jacoco/jacoco.xml
+ token: ${{ secrets.GITHUB_TOKEN }}
+ min-coverage-overall: 40
+ min-coverage-changed-files: 60
+ title: Code Coverage Report
+ comment-type: pr_comment
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 5a1e6d24a..a4786a90b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,4 +32,3 @@ mvnw.cmd
.mvn
/logs/
src/main/environment/common_local.properties
-node_modules
diff --git a/README.md b/README.md
index 5c992214d..7f8d7e052 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,7 @@
# Frontline Health Workers (FLW) Mobile App API Module
+[](https://deepwiki.com/PSMRI/FLW-API)
+
+
### Introduction
Frontline Health Workers (FLW) Mobile App is known with brand name _SAKHI_ App. Currently this _SAKHI_ App is designed for Accredited Social Health Activist (ASHA).
diff --git a/pom.xml b/pom.xml
index 5fc0bc731..63e8f2ff9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,7 +30,7 @@
${ENV_VAR}
target/classes/application.properties
target/classes/common_${environment}.properties
- true
+ false
target
@@ -218,11 +218,6 @@
org.slf4j
slf4j-api
-
- org.jacoco
- jacoco-maven-plugin
- 0.8.11
-
org.springframework
spring-web
@@ -262,6 +257,17 @@
+
+ swagger
+
+
+
+ com.h2database
+ h2
+ runtime
+
+
+
1097_flw
@@ -281,15 +287,30 @@
${artifactId}-${version}
-
- org.apache.maven.plugins
- maven-jar-plugin
- 3.0.2
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 3.0.2
+
+
+ org.jacoco
+ jacoco-maven-plugin
+ 0.8.8
+
+
+
+ prepare-agent
+
+
+
+ report
+ test
+
+ report
+
+
+
+
org.apache.maven.plugins
maven-compiler-plugin
diff --git a/src/main/environment/common_ci.properties b/src/main/environment/common_ci.properties
index ad996282d..b778ecfff 100644
--- a/src/main/environment/common_ci.properties
+++ b/src/main/environment/common_ci.properties
@@ -1,6 +1,7 @@
fhir-url = @env.FHIR_API@
tm-url = @env.TM_API@
+common-api-base-url=@env.COMMON_API@
##--------------------------------------------## Primary db-------------------------------------------------------------------
@@ -27,11 +28,6 @@ jwt.secret=@env.JWT_SECRET_KEY@
# Redis Config
spring.redis.host=@env.REDIS_HOST@
-# Stop TB: when true, saves fail with an error if camp (vanID) is not configured
-stoptb.enforce.vanid=@env.STOPTB_ENFORCE_VANID@
-# Stop TB: this deployment's van/camp ID, replacing the old Redis camp:vanID lookup
-stoptb.van.id=@env.STOPTB_VAN_ID@
-
cors.allowed-origins=@env.CORS_ALLOWED_ORIGINS@
#### SMS Configuration
@@ -85,10 +81,14 @@ diagnostic.emrlite.truenat.password=@env.DIAGNOSTIC_EMRLITE_TRUENAT_PASSWORD@
diagnostic.emrlite.token-ttl-seconds=@env.DIAGNOSTIC_EMRLITE_TOKEN_TTL_SECONDS@
diagnostic.emrlite.refresh-ttl-seconds=@env.DIAGNOSTIC_EMRLITE_REFRESH_TTL_SECONDS@
-
+diagnostic.documents.storage-root=@env.DIAGNOSTIC_DOCUMENTS_STORAGE_ROOT@
diagnostic.poll.xray.tick-ms=@env.DIAGNOSTIC_POLL_XRAY_TICK_MS@
diagnostic.poll.truenat.tick-ms=@env.DIAGNOSTIC_POLL_TRUENAT_TICK_MS@
# Daily cutoff (cron expression) after which all outstanding PENDING/IN_PROGRESS orders are marked EXPIRED
diagnostic.poll.expiry-cron=@env.DIAGNOSTIC_POLL_EXPIRY_CRON@
-diagnostic.documents.storage-root=@env.DIAGNOSTIC_DOCUMENTS_STORAGE_ROOT@
+stoptb.enforce.vanid=@env.STOPTB_ENFORCE_VANID@
+# Stop TB: this deployment's van/camp ID, replacing the old Redis camp:vanID lookup
+stoptb.van.id=@env.STOPTB_VAN_ID@
+
+
diff --git a/src/main/environment/common_docker.properties b/src/main/environment/common_docker.properties
index b37a8e00e..e38175a51 100644
--- a/src/main/environment/common_docker.properties
+++ b/src/main/environment/common_docker.properties
@@ -1,5 +1,8 @@
fhir-url = ${FHIR_API}
tm-url = ${TM_API}
+common-api-base-url=${COMMON_API}
+
+
##--------------------------------------------## Primary db-------------------------------------------------------------------
diff --git a/src/main/java/com/iemr/flw/config/SwaggerConfig.java b/src/main/java/com/iemr/flw/config/SwaggerConfig.java
index 1052c2af7..f551de7c5 100644
--- a/src/main/java/com/iemr/flw/config/SwaggerConfig.java
+++ b/src/main/java/com/iemr/flw/config/SwaggerConfig.java
@@ -23,21 +23,35 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
+import io.swagger.v3.oas.models.servers.Server;
+import java.util.List;
@Configuration
public class SwaggerConfig {
+ private static final String DEFAULT_SERVER_URL = "http://localhost:9090";
+ private static final String BEARER_AUTH_SCHEME = "bearerAuth";
+
@Bean
- OpenAPI customOpenAPI() {
- return new OpenAPI().info(new
- Info().title("FLW API").version("version").description("A microservice for the creation and management of beneficiaries."))
- .addSecurityItem(new SecurityRequirement().addList("my security"))
- .components(new Components().addSecuritySchemes("my security",
- new SecurityScheme().name("my security").type(SecurityScheme.Type.HTTP).scheme("bearer")));
- }
+ public OpenAPI customOpenAPI(Environment env) {
+ String devUrl = env.getProperty("api.dev.url", DEFAULT_SERVER_URL);
+ String uatUrl = env.getProperty("api.uat.url", DEFAULT_SERVER_URL);
+ String demoUrl = env.getProperty("api.demo.url", DEFAULT_SERVER_URL);
+ return new OpenAPI()
+ .info(new Info().title("FLW API").version("3.1.0").description("A microservice for the creation and management of Field Level Workers (FLW) in the AMRIT ecosystem."))
+ .addSecurityItem(new SecurityRequirement().addList(BEARER_AUTH_SCHEME))
+ .components(new Components().addSecuritySchemes(BEARER_AUTH_SCHEME,
+ new SecurityScheme().name(BEARER_AUTH_SCHEME).type(SecurityScheme.Type.HTTP).scheme("bearer")))
+ .servers(List.of(
+ new Server().url(devUrl).description("Dev"),
+ new Server().url(uatUrl).description("UAT"),
+ new Server().url(demoUrl).description("Demo")
+ ));
+ }
}
diff --git a/src/main/java/com/iemr/flw/controller/AdolescentHealthController.java b/src/main/java/com/iemr/flw/controller/AdolescentHealthController.java
index 11cc5e577..3b7dfe9ae 100644
--- a/src/main/java/com/iemr/flw/controller/AdolescentHealthController.java
+++ b/src/main/java/com/iemr/flw/controller/AdolescentHealthController.java
@@ -1,5 +1,6 @@
package com.iemr.flw.controller;
+import com.google.gson.Gson;
import com.iemr.flw.domain.iemr.AdolescentHealth;
import com.iemr.flw.dto.identity.GetBenRequestHandler;
import com.iemr.flw.dto.iemr.AdolescentHealthDTO;
@@ -8,10 +9,7 @@
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
@@ -27,7 +25,7 @@ public class AdolescentHealthController {
private AdolescentHealthService adolescentHealthService;
@RequestMapping(value = "/saveAll", method = RequestMethod.POST, headers = "Authorization")
- public ResponseEntity