diff --git a/build/build-config.yml b/build/build-config.yml index 981c3dd7dff..8bbde05a800 100644 --- a/build/build-config.yml +++ b/build/build-config.yml @@ -36,6 +36,13 @@ config: dockerfile: "build/maven/Dockerfile" - work-dir: "health-services/project/src/main/resources/db" image-name: "project-db" + - name: "builds/health-campaign-services/health-services/health-project" + build: + - work-dir: "health-services/project" + image-name: "health-project" + dockerfile: "build/maven/Dockerfile" + - work-dir: "health-services/project/src/main/resources/db" + image-name: "health-project-db" - name: "builds/health-campaign-services/health-services/referralmanagement" build: - work-dir: "health-services/referralmanagement" @@ -57,6 +64,20 @@ config: dockerfile: "build/maven/Dockerfile" - work-dir: "health-services/individual/src/main/resources/db" image-name: "individual-db" + - name: "builds/health-campaign-services/health-services/health-individual" + build: + - work-dir: "health-services/individual" + image-name: "health-individual" + dockerfile: "build/maven/Dockerfile" + - work-dir: "health-services/individual/src/main/resources/db" + image-name: "health-individual-db" + - name: "builds/health-campaign-services/health-services/health-attendance" + build: + - work-dir: "health-services/attendance" + image-name: "health-attendance" + dockerfile: "build/maven/Dockerfile" + - work-dir: "health-services/attendance/src/main/resources/db" + image-name: "health-attendance-db" - name: "builds/health-campaign-services/health-services/household" build: - work-dir: "health-services/household" @@ -68,7 +89,7 @@ config: build: - work-dir: "core-services/error-handler" image-name: "error-handler" - dockerfile: "build/maven/Dockerfile" + dockerfile: "build/maven/Dockerfile" - name: "builds/health-campaign-services/core-services/dashboard-analytics" build: - work-dir: "core-services/dashboard-analytics" @@ -118,6 +139,13 @@ config: dockerfile: "build/maven/Dockerfile" - work-dir: "core-services/pgr-services/src/main/resources/db" image-name: "pgr-services-db" + - name: "builds/health-campaign-services/core-services/health-pgr-services" + build: + - work-dir: "core-services/pgr-services" + image-name: "health-pgr-services" + dockerfile: "build/maven/Dockerfile" + - work-dir: "core-services/pgr-services/src/main/resources/db" + image-name: "health-pgr-services-db" - name: "builds/health-campaign-services/core-services/user-otp" build: - work-dir: "core-services/user-otp" @@ -126,3 +154,17 @@ config: build: - work-dir: "core-services/egov-notification-mail" image-name: "egov-notification-mail" + - name: "builds/health-campaign-services/core-services/attendance" + build: + - work-dir: "core-services/attendance" + image-name: "attendance" + dockerfile: "build/maven/Dockerfile" + - work-dir: "core-services/attendance/src/main/resources/db" + image-name: "attendance-db" + - name: "builds/health-campaign-services/core-services/health-hrms" + build: + - work-dir: "core-services/egov-hrms" + image-name: "health-hrms" + dockerfile: "build/maven/Dockerfile" + - work-dir: "core-services/egov-hrms/src/main/resources/db" + image-name: "health-hrms-db" \ No newline at end of file diff --git a/docs/health-api-specs/contracts/stock.yml b/docs/health-api-specs/contracts/stock.yml index d2df236940d..2ee5512df51 100644 --- a/docs/health-api-specs/contracts/stock.yml +++ b/docs/health-api-specs/contracts/stock.yml @@ -504,6 +504,7 @@ definitions: - LOST_IN_TRANSIT - DAMAGED_IN_STORAGE - DAMAGED_IN_TRANSIT + description: This field accepts values from enum and if an invalid value is provided, it will default to null. wayBillNumber: type: string minLength: 2 diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/bulk_create.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/bulk_create.puml new file mode 100644 index 00000000000..031f8b42e19 --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/bulk_create.puml @@ -0,0 +1,140 @@ +@startuml +title HFReferral - Bulk Create +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant FacilityService as fs +participant ProjectService as ps +participant RedisCache as rc +queue Kafka as k +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el +database Database as db + +c -> rm : /referralmanagement/hf-referral/v1/bulk/_create +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: HFReferral Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +loop for each hfReferral + alt record already exists + alt record found in cache + rm -> rc: Check using clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 1 row + deactivate rc + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_ALREADY_EXISTS + end note + end + rm -> rc: Check using clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Check if record already exists + activate db + db -> rm: 1 row + deactivate db + rm -> rc: Put data in cache using clientReferenceId/serverGeneratedId + activate rc + deactivate rc + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_ALREADY_EXISTS + end note + end + alt projectId invalid + rm -> ps: Check if projectId exists + activate ps + ps -> db: Check if projectId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + rm -> ps: Check if projectId exists + activate ps + ps -> db: Check if projectId exists + activate db + db -> ps: n row + deactivate db + ps -> rm: n row + deactivate ps + alt projectFacilityId invalid + rm -> ps: Check if projectFacilityId exists + activate ps + ps -> db: Check if projectFacilityId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + rm -> ps: Check if projectFacilityId exists + activate ps + ps -> db: Check if projectFacilityId exists + activate db + db -> ps: n row + deactivate db + ps -> rm: n row + deactivate ps + rm -> k: HFReferral Data /persist_topic + activate k + rm -> rc: Put HFReferral Data against clientReferenceId/serverGeneratedId in cache + activate rc + deactivate rc + group async + prs -> k: Consume HFReferral Data + activate prs + idx -> k: Consume HFReferral Data + activate idx + idx -> el: Store HFReferral Data + activate el + deactivate el + deactivate idx + prs -> db: Persist HFReferral Data + activate db + deactivate db + deactivate prs + end + deactivate k +end + +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/bulk_delete.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/bulk_delete.puml new file mode 100644 index 00000000000..0f8eab2fa9b --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/bulk_delete.puml @@ -0,0 +1,153 @@ +@startuml +title HFReferral - Bulk Delete +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant RedisCache as rc +queue Kafka as k +database Database as db +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant UserService as us +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el + +c -> rm : /referralmanagement/hf-referral/v1/bulk/_delete +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: HFReferral Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +loop for each hfReferral + alt id is null + rm -> rm: Check if HFReferral object id is null + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: NULL_ID + end note + end + rm -> rm: Check if HFReferral id is not null + alt record doesn't exist + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 0 row + deactivate db + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + rm -> k: HFReferral Data /error_topic + activate k + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + s -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_NOT_FOUND + end note + end + alt record doesn't exists in cache + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 1 row + deactivate db + rm -> rc: 1 record + activate rc + deactivate rc + end + rm -> rc: Fetch the existing record + activate rc + rc -> rm: 1 row + deactivate rc + alt Duplicate Entry is present [Unique entity validation failed] + rm -> rm: Check if HFReferral object isDeleted is true + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: IS_DELETED_TRUE + end note + end + rm -> rm: Duplicate Entry is not present [Unique entity validation successful] + alt incorrect rowVersion + s -> s: Compare rowVersion between request and db + s -> s: Incorrect rowVersion [request: should be +1 only] + s -> k: HFReferral Data /error_topic + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + s -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: BAD_REQUEST + end note + end + s -> s: Compare rowVersion between request and db + s -> s: rowVersion in request = rowVersion in db + 1 + rm -> k: HFReferral Data /persist_topic + activate k + rm -> rc: Put HFReferral Data against clientReferenceId/serverGeneratedId in cache + activate rc + deactivate rc + group async + prs -> k: Consume HFReferral Data + activate prs + idx -> k: Consume HFReferral Data + activate idx + idx -> el: Store HFReferral Data + activate el + deactivate el + deactivate idx + prs -> db: Persist HFReferral Data + activate db + deactivate db + deactivate prs + end + deactivate k +end +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/bulk_update.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/bulk_update.puml new file mode 100644 index 00000000000..693993065b6 --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/bulk_update.puml @@ -0,0 +1,205 @@ +@startuml +title HFReferral - Bulk Update +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant RedisCache as rc +queue Kafka as k +database Database as db +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant UserService as us +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el + +c -> rm : /referralmanagement/hf-referral/v1/bulk/_update +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: HFReferral Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +loop for each hfReferral + alt id is null + rm -> rm: Check if HFReferral object id is null + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: NULL_ID + end note + end + rm -> rm: Check if HFReferral id is not null + alt isDeleted is true + rm -> rm: Check if HFReferral object isDeleted is true + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: IS_DELETED_TRUE + end note + end + rm -> rm: Check if HFReferral object isDeleted is not true + alt record doesn't exist + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 0 row + deactivate db + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + rm -> k: HFReferral Data /error_topic + activate k + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_NOT_FOUND + end note + end + alt record doesn't exists in cache + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: n row + deactivate db + rm -> rc: n record + activate rc + deactivate rc + end + rm -> rc: Fetch the existing record + activate rc + rc -> rm: n row + deactivate rc + alt projectId invalid + rm -> ps: Check if projectId exists + activate ps + ps -> db: Check if projectId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + rm -> ps: Check if projectId exists + activate ps + ps -> db: Check if projectId exists + activate db + db -> ps: n row + deactivate db + ps -> rm: n row + deactivate ps + alt projectFacilityId invalid + rm -> ps: Check if projectFacilityId exists + activate ps + ps -> db: Check if projectFacilityId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + rm -> ps: Check if projectFacilityId exists + activate ps + ps -> db: Check if projectFacilityId exists + activate db + db -> ps: n row + deactivate db + ps -> rm: n row + deactivate ps + alt Duplicate Entry is present [Unique entity validation failed] + rm -> rm: Check if HFReferral object isDeleted is true + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: IS_DELETED_TRUE + end note + end + rm -> rm: Duplicate Entry is not present [Unique entity validation successful] + alt incorrect rowVersion + s -> s: Compare rowVersion between request and db + s -> s: Incorrect rowVersion [request: should be +1 only] + s -> k: HFReferral Data /error_topic + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + s -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: BAD_REQUEST + end note + end + s -> s: Compare rowVersion between request and db + s -> s: rowVersion in request = rowVersion in db + 1 + rm -> k: HFReferral Data /persist_topic + activate k + rm -> rc: Put HFReferral Data against clientReferenceId/serverGeneratedId in cache + activate rc + deactivate rc + group async + prs -> k: Consume HFReferral Data + activate prs + idx -> k: Consume HFReferral Data + activate idx + idx -> el: Store HFReferral Data + activate el + deactivate el + deactivate idx + prs -> db: Persist HFReferral Data + activate db + deactivate db + deactivate prs + end + deactivate k +end +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/create.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/create.puml new file mode 100644 index 00000000000..b83117a4e43 --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/create.puml @@ -0,0 +1,137 @@ +@startuml +title HFReferral - Create +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant FacilityService as fs +participant ProjectService as ps +participant RedisCache as rc +queue Kafka as k +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el +database Database as db + +c -> rm : /referralmanagement/hf-referral/v1/_create +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: HFReferral Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +alt record already exists + alt record found in cache + rm -> rc: Check using clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 1 row + deactivate rc + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_ALREADY_EXISTS + end note + end + rm -> rc: Check using clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Check if record already exists + activate db + db -> rm: 1 row + deactivate db + rm -> rc: Put data in cache using clientReferenceId/serverGeneratedId + activate rc + deactivate rc + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_ALREADY_EXISTS + end note +end +alt projectId invalid + rm -> ps: Check if projectId exists + activate ps + ps -> db: Check if projectId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +rm -> ps: Check if projectId exists +activate ps +ps -> db: Check if projectId exists +activate db +db -> ps: 1 row +deactivate db +ps -> rm: 1 row +deactivate ps +alt projectFacilityId invalid + rm -> ps: Check if projectFacilityId exists + activate ps + ps -> db: Check if projectFacilityId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +rm -> ps: Check if projectFacilityId exists +activate ps +ps -> db: Check if projectFacilityId exists +activate db +db -> ps: 1 row +deactivate db +ps -> rm: 1 row +deactivate ps +rm -> k: HFReferral Data /persist_topic +activate k +rm -> rc: Put HFReferral Data against clientReferenceId/serverGeneratedId in cache +activate rc +deactivate rc +group async + prs -> k: Consume HFReferral Data + activate prs + idx -> k: Consume HFReferral Data + activate idx + idx -> el: Store HFReferral Data + activate el + deactivate el + deactivate idx + prs -> db: Persist HFReferral Data + activate db + deactivate db + deactivate prs +end +deactivate k +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/delete.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/delete.puml new file mode 100644 index 00000000000..e5d460e53b0 --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/delete.puml @@ -0,0 +1,143 @@ +@startuml +title HFReferral - Delete +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant RedisCache as rc +queue Kafka as k +database Database as db +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant UserService as us +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el + +c -> rm : /referralmanagement/hf-referral/v1/_delete +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: HFReferral Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +alt id is null + rm -> rm: Check if HFReferral object id is null + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: NULL_ID + end note +end +rm -> rm: Check if HFReferral id is not null +alt record doesn't exist + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 0 row + deactivate db + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + rm -> k: HFReferral Data /error_topic + activate k + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + s -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_NOT_FOUND + end note +end +alt record doesn't exists in cache + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 1 row + deactivate db + rm -> rc: 1 record + activate rc + deactivate rc +end +rm -> rc: Fetch the existing record +activate rc +rc -> rm: 1 row +deactivate rc +alt incorrect rowVersion + s -> s: Compare rowVersion between request and db + s -> s: Incorrect rowVersion [request: should be +1 only] + s -> k: HFReferral Data /error_topic + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + s -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: BAD_REQUEST + end note +end +s -> s: Compare rowVersion between request and db +s -> s: rowVersion in request = rowVersion in db + 1 +rm -> k: HFReferral Data /persist_topic +activate k +rm -> rc: Put HFReferral Data against clientReferenceId/serverGeneratedId in cache +activate rc +deactivate rc +group async + prs -> k: Consume HFReferral Data + activate prs + idx -> k: Consume HFReferral Data + activate idx + idx -> el: Store HFReferral Data + activate el + deactivate el + deactivate idx + prs -> db: Persist HFReferral Data + activate db + deactivate db + deactivate prs +end +deactivate k +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/update.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/update.puml new file mode 100644 index 00000000000..b9db19c7578 --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/hfreferral/update.puml @@ -0,0 +1,196 @@ +@startuml +title HFReferral - Update +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant RedisCache as rc +queue Kafka as k +database Database as db +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant UserService as us +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el + +c -> rm : /referralmanagement/hf-referral/v1/_update +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: HFReferral Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +alt id is null + rm -> rm: Check if HFReferral object id is null + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: NULL_ID + end note +end +rm -> rm: Check if HFReferral id is not null +alt isDeleted is true + rm -> rm: Check if HFReferral object isDeleted is true + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: IS_DELETED_TRUE + end note +end +rm -> rm: Check if HFReferral object isDeleted is not true +alt record doesn't exist + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 0 row + deactivate db + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + rm -> k: HFReferral Data /error_topic + activate k + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_NOT_FOUND + end note +end +alt record doesn't exists in cache + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 1 row + deactivate db + rm -> rc: 1 record + activate rc + deactivate rc +end +rm -> rc: Fetch the existing record +activate rc +rc -> rm: 1 row +deactivate rc +alt projectId invalid + rm -> ps: Check if projectId exists + activate ps + ps -> db: Check if projectId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +rm -> ps: Check if projectId exists +activate ps +ps -> db: Check if projectId exists +activate db +db -> ps: n row +deactivate db +ps -> rm: n row +deactivate ps +alt projectFacilityId invalid + rm -> ps: Check if projectFacilityId exists + activate ps + ps -> db: Check if projectFacilityId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +rm -> ps: Check if projectFacilityId exists +activate ps +ps -> db: Check if projectFacilityId exists +activate db +db -> ps: n row +deactivate db +ps -> rm: n row +deactivate ps +alt incorrect rowVersion + s -> s: Compare rowVersion between request and db + s -> s: Incorrect rowVersion [request: should be +1 only] + s -> k: HFReferral Data /error_topic + group async + es -> k: Consume HFReferral Data + activate es + deactivate k + es -> db: Persist HFReferral Data /error_table + activate db + deactivate db + deactivate es + end + s -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: BAD_REQUEST + end note +end +s -> s: Compare rowVersion between request and db +s -> s: rowVersion in request = rowVersion in db + 1 +rm -> k: HFReferral Data /persist_topic +activate k +rm -> rc: Put HFReferral Data against clientReferenceId/serverGeneratedId in cache +activate rc +deactivate rc +group async + prs -> k: Consume HFReferral Data + activate prs + idx -> k: Consume HFReferral Data + activate idx + idx -> el: Store HFReferral Data + activate el + deactivate el + deactivate idx + prs -> db: Persist HFReferral Data + activate db + deactivate db + deactivate prs +end +deactivate k + +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/bulk_create.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/bulk_create.puml new file mode 100644 index 00000000000..ad7d70f7540 --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/bulk_create.puml @@ -0,0 +1,204 @@ +@startuml +title Referral - Bulk Create +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant UserService as us +participant RedisCache as rc +queue Kafka as k +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el +database Database as db + +c -> rm : /referralmanagement/v1/bulk/_create +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: Referral Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume Referral Data + activate es + deactivate k + es -> db: Persist Referral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +loop for each referral + alt record already exists + alt record found in cache + rm -> rc: Check using clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 1 row + deactivate rc + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_ALREADY_EXISTS + end note + end + rm -> rc: Check using clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Check if record already exists + activate db + db -> rm: 1 row + deactivate db + rm -> rc: Put data in cache using clientReferenceId/serverGeneratedId + activate rc + deactivate rc + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_ALREADY_EXISTS + end note + end + alt projectBeneficiaryId invalid + rm -> ps: Check if projectBeneficiaryId exists + activate ps + ps -> db: Check if projectBeneficiaryId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + rm -> ps: Check if projectBeneficiaryId exists + activate ps + ps -> db: Check if projectBeneficiaryId exists + activate db + db -> ps: 1 row + deactivate db + ps -> rm: 1 row + deactivate ps + alt referrerId invalid + rm -> us: Check if referrerId exists + activate us + us -> db: Check if referrerId exists + activate db + db -> us: 0 rows + deactivate db + us -> rm: 0 rows + deactivate us + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + rm -> us: Check if referrerId exists + activate us + us -> db: Check if referrerId exists + activate db + db -> us: 1 row + deactivate db + us -> rm: 1 row + deactivate us + alt recipientId invalid + alt recipientType is STAFF + rm -> us: Check if recipientId exists + activate us + us -> db: Check if recipientId exists + activate db + db -> us: 0 rows + deactivate db + us -> rm: 0 rows + deactivate us + end + alt recipientType is FACILITY + rm -> fs: Check if recipientId exists + activate fs + fs -> db: Check if recipientId exists + activate db + db -> fs: 0 rows + deactivate db + fs -> rm: 0 rows + deactivate fs + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + alt recipientType is STAFF + rm -> us: Check if recipientId exists + activate us + us -> db: Check if recipientId exists + activate db + db -> us: 1 row + deactivate db + us -> rm: 1 row + deactivate us + end + alt recipientType is FACILITY + rm -> fs: Check if recipientId exists + activate fs + fs -> db: Check if recipientId exists + activate db + db -> fs: 1 row + deactivate db + fs -> rm: 1 row + deactivate fs + end + alt sideEffectId invalid + rm -> db: Check if sideEffectId exists + activate db + db -> rm: 0 rows + deactivate db + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + rm -> db: Check if referrerId exists + activate db + db -> rm: 1 row + deactivate db + + rm -> k: Referral Data /persist_topic + activate k + rm -> rc: Put Referral Data against clientReferenceId/serverGeneratedId in cache + activate rc + deactivate rc + group async + prs -> k: Consume Referral Data + activate prs + idx -> k: Consume Referral Data + activate idx + idx -> el: Store Referral Data + activate el + deactivate el + deactivate idx + prs -> db: Persist Referral Data + activate db + deactivate db + deactivate prs + end + deactivate k +end + +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/bulk_delete.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/bulk_delete.puml new file mode 100644 index 00000000000..38aae93d8b3 --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/bulk_delete.puml @@ -0,0 +1,133 @@ +@startuml +title Referral - Bulk Delete +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant RedisCache as rc +queue Kafka as k +database Database as db +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant UserService as us +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el + +c -> rm : /referralmanagement/v1/bulk/_delete +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: Referral Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume Referral Data + activate es + deactivate k + es -> db: Persist Referral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +loop for each referral + alt id is null + rm -> rm: Check if Referral object id is null + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: NULL_ID + end note + end + rm -> rm: Check if Referral id is not null + alt record doesn't exist + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 0 row + deactivate db + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + rm -> k: Referral Data /error_topic + activate k + group async + es -> k: Consume Referral Data + activate es + deactivate k + es -> db: Persist Referral Data /error_table + activate db + deactivate db + deactivate es + end + s -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_NOT_FOUND + end note + end + alt record doesn't exists in cache + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 1 row + deactivate db + rm -> rc: 1 record + activate rc + deactivate rc + end + rm -> rc: Fetch the existing record + activate rc + rc -> rm: 1 row + deactivate rc + alt Duplicate Entry is present [Unique entity validation failed] + rm -> rm: Check if Side Effect object isDeleted is true + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: IS_DELETED_TRUE + end note + end + rm -> rm: Duplicate Entry is not present [Unique entity validation successful] + rm -> k: Referral Data /persist_topic + activate k + rm -> rc: Put Referral Data against clientReferenceId/serverGeneratedId in cache + activate rc + deactivate rc + group async + prs -> k: Consume Referral Data + activate prs + idx -> k: Consume Referral Data + activate idx + idx -> el: Store Referral Data + activate el + deactivate el + deactivate idx + prs -> db: Persist Referral Data + activate db + deactivate db + deactivate prs + end + deactivate k +end +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/bulk_update.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/bulk_update.puml new file mode 100644 index 00000000000..10d2b662106 --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/bulk_update.puml @@ -0,0 +1,245 @@ +@startuml +title Referral - Bulk Update +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant RedisCache as rc +queue Kafka as k +database Database as db +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant UserService as us +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el + +c -> rm : /referralmanagement/v1/bulk/_update +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: Referral Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume Referral Data + activate es + deactivate k + es -> db: Persist Referral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +loop for each referral + alt id is null + rm -> rm: Check if Referral object id is null + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: NULL_ID + end note + end + rm -> rm: Check if Referral id is not null + alt isDeleted is true + rm -> rm: Check if Referral object isDeleted is true + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: IS_DELETED_TRUE + end note + end + rm -> rm: Check if Referral object isDeleted is not true + alt record doesn't exist + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 0 row + deactivate db + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + rm -> k: Referral Data /error_topic + activate k + group async + es -> k: Consume Referral Data + activate es + deactivate k + es -> db: Persist Referral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_NOT_FOUND + end note + end + alt record doesn't exists in cache + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 1 row + deactivate db + rm -> rc: 1 record + activate rc + deactivate rc + end + rm -> rc: Fetch the existing record + activate rc + rc -> rm: 1 row + deactivate rc + alt projectBeneficiaryId invalid + rm -> ps: Check if projectBeneficiaryId exists + activate ps + ps -> db: Check if projectBeneficiaryId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + rm -> ps: Check if projectBeneficiaryId exists + activate ps + ps -> db: Check if projectBeneficiaryId exists + activate db + db -> ps: 1 row + deactivate db + ps -> rm: 1 row + deactivate ps + alt referrerId invalid + rm -> us: Check if referrerId exists + activate us + us -> db: Check if referrerId exists + activate db + db -> us: 0 rows + deactivate db + us -> rm: 0 rows + deactivate us + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + rm -> us: Check if referrerId exists + activate us + us -> db: Check if referrerId exists + activate db + db -> us: 1 row + deactivate db + us -> rm: 1 row + deactivate us + alt recipientId invalid + alt recipientType is STAFF + rm -> us: Check if recipientId exists + activate us + us -> db: Check if recipientId exists + activate db + db -> us: 0 rows + deactivate db + us -> rm: 0 rows + deactivate us + end + alt recipientType is FACILITY + rm -> fs: Check if recipientId exists + activate fs + fs -> db: Check if recipientId exists + activate db + db -> fs: 0 rows + deactivate db + fs -> rm: 0 rows + deactivate fs + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + alt recipientType is STAFF + rm -> us: Check if recipientId exists + activate us + us -> db: Check if recipientId exists + activate db + db -> us: 1 row + deactivate db + us -> rm: 1 row + deactivate us + end + alt recipientType is FACILITY + rm -> fs: Check if recipientId exists + activate fs + fs -> db: Check if recipientId exists + activate db + db -> fs: 1 row + deactivate db + fs -> rm: 1 row + deactivate fs + end + alt sideEffectId invalid + rm -> db: Check if sideEffectId exists + activate db + db -> rm: 0 rows + deactivate db + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + rm -> db: Check if referrerId exists + activate db + db -> rm: 1 row + deactivate db + alt Duplicate Entry is present [Unique entity validation failed] + rm -> rm: Check if Side Effect object isDeleted is true + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: IS_DELETED_TRUE + end note + end + rm -> rm: Duplicate Entry is not present [Unique entity validation successful] + rm -> k: Referral Data /persist_topic + activate k + rm -> rc: Put Referral Data against clientReferenceId/serverGeneratedId in cache + activate rc + deactivate rc + group async + prs -> k: Consume Referral Data + activate prs + idx -> k: Consume Referral Data + activate idx + idx -> el: Store Referral Data + activate el + deactivate el + deactivate idx + prs -> db: Persist Referral Data + activate db + deactivate db + deactivate prs + end + deactivate k +end +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/create.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/create.puml new file mode 100644 index 00000000000..b3437b4a49c --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/create.puml @@ -0,0 +1,201 @@ +@startuml +title Referral - Create +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant UserService as us +participant RedisCache as rc +queue Kafka as k +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el +database Database as db + +c -> rm : /referralmanagement/v1/_create +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: Referral Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume Referral Data + activate es + deactivate k + es -> db: Persist Referral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +alt record already exists + alt record found in cache + rm -> rc: Check using clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 1 row + deactivate rc + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_ALREADY_EXISTS + end note + end + rm -> rc: Check using clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Check if record already exists + activate db + db -> rm: 1 row + deactivate db + rm -> rc: Put data in cache using clientReferenceId/serverGeneratedId + activate rc + deactivate rc + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_ALREADY_EXISTS + end note +end +alt projectBeneficiaryId invalid + rm -> ps: Check if projectBeneficiaryId exists + activate ps + ps -> db: Check if projectBeneficiaryId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +rm -> ps: Check if projectBeneficiaryId exists +activate ps +ps -> db: Check if projectBeneficiaryId exists +activate db +db -> ps: 1 row +deactivate db +ps -> rm: 1 row +deactivate ps +alt referrerId invalid + rm -> us: Check if referrerId exists + activate us + us -> db: Check if referrerId exists + activate db + db -> us: 0 rows + deactivate db + us -> rm: 0 rows + deactivate us + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +rm -> us: Check if referrerId exists +activate us +us -> db: Check if referrerId exists +activate db +db -> us: 1 row +deactivate db +us -> rm: 1 row +deactivate us +alt recipientId invalid + alt recipientType is STAFF + rm -> us: Check if recipientId exists + activate us + us -> db: Check if recipientId exists + activate db + db -> us: 0 rows + deactivate db + us -> rm: 0 rows + deactivate us + end + alt recipientType is FACILITY + rm -> fs: Check if recipientId exists + activate fs + fs -> db: Check if recipientId exists + activate db + db -> fs: 0 rows + deactivate db + fs -> rm: 0 rows + deactivate fs + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +alt recipientType is STAFF + rm -> us: Check if recipientId exists + activate us + us -> db: Check if recipientId exists + activate db + db -> us: 1 row + deactivate db + us -> rm: 1 row + deactivate us +end +alt recipientType is FACILITY + rm -> fs: Check if recipientId exists + activate fs + fs -> db: Check if recipientId exists + activate db + db -> fs: 1 row + deactivate db + fs -> rm: 1 row + deactivate fs +end +alt sideEffectId invalid + rm -> db: Check if sideEffectId exists + activate db + db -> rm: 0 rows + deactivate db + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +rm -> db: Check if referrerId exists +activate db +db -> rm: 1 row +deactivate db + +rm -> k: Referral Data /persist_topic +activate k +rm -> rc: Put Referral Data against clientReferenceId/serverGeneratedId in cache +activate rc +deactivate rc +group async + prs -> k: Consume Referral Data + activate prs + idx -> k: Consume Referral Data + activate idx + idx -> el: Store Referral Data + activate el + deactivate el + deactivate idx + prs -> db: Persist Referral Data + activate db + deactivate db + deactivate prs +end +deactivate k +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/delete.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/delete.puml new file mode 100644 index 00000000000..6e67539432a --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/delete.puml @@ -0,0 +1,124 @@ +@startuml +title Referral - Delete +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant RedisCache as rc +queue Kafka as k +database Database as db +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant UserService as us +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el + +c -> rm : /referralmanagement/v1/_delete +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: Referral Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume Referral Data + activate es + deactivate k + es -> db: Persist Referral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +alt id is null + rm -> rm: Check if Referral object id is null + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: NULL_ID + end note +end +rm -> rm: Check if Referral id is not null +alt record doesn't exist + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 0 row + deactivate db + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + rm -> k: Referral Data /error_topic + activate k + group async + es -> k: Consume Referral Data + activate es + deactivate k + es -> db: Persist Referral Data /error_table + activate db + deactivate db + deactivate es + end + s -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_NOT_FOUND + end note +end +alt record doesn't exists in cache + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 1 row + deactivate db + rm -> rc: 1 record + activate rc + deactivate rc +end +rm -> rc: Fetch the existing record +activate rc +rc -> rm: 1 row +deactivate rc + +rm -> k: Referral Data /persist_topic +activate k +rm -> rc: Put Referral Data against clientReferenceId/serverGeneratedId in cache +activate rc +deactivate rc +group async + prs -> k: Consume Referral Data + activate prs + idx -> k: Consume Referral Data + activate idx + idx -> el: Store Referral Data + activate el + deactivate el + deactivate idx + prs -> db: Persist Referral Data + activate db + deactivate db + deactivate prs +end +deactivate k +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/update.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/update.puml new file mode 100644 index 00000000000..e08b8b98607 --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/referral/update.puml @@ -0,0 +1,237 @@ +@startuml +title Referral - Update +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant RedisCache as rc +queue Kafka as k +database Database as db +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant UserService as us +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el + +c -> rm : /referralmanagement/v1/_update +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: Referral Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume Referral Data + activate es + deactivate k + es -> db: Persist Referral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +alt id is null + rm -> rm: Check if Referral object id is null + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: NULL_ID + end note +end +rm -> rm: Check if Referral id is not null +alt isDeleted is true + rm -> rm: Check if Referral object isDeleted is true + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: IS_DELETED_TRUE + end note +end +rm -> rm: Check if Referral object isDeleted is not true +alt record doesn't exist + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 0 row + deactivate db + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + rm -> k: Referral Data /error_topic + activate k + group async + es -> k: Consume Referral Data + activate es + deactivate k + es -> db: Persist Referral Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_NOT_FOUND + end note +end +alt record doesn't exists in cache + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 1 row + deactivate db + rm -> rc: 1 record + activate rc + deactivate rc +end +rm -> rc: Fetch the existing record +activate rc +rc -> rm: 1 row +deactivate rc +alt projectBeneficiaryId invalid + rm -> ps: Check if projectBeneficiaryId exists + activate ps + ps -> db: Check if projectBeneficiaryId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +rm -> ps: Check if projectBeneficiaryId exists +activate ps +ps -> db: Check if projectBeneficiaryId exists +activate db +db -> ps: 1 row +deactivate db +ps -> rm: 1 row +deactivate ps +alt referrerId invalid + rm -> us: Check if referrerId exists + activate us + us -> db: Check if referrerId exists + activate db + db -> us: 0 rows + deactivate db + us -> rm: 0 rows + deactivate us + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +rm -> us: Check if referrerId exists +activate us +us -> db: Check if referrerId exists +activate db +db -> us: 1 row +deactivate db +us -> rm: 1 row +deactivate us +alt recipientId invalid + alt recipientType is STAFF + rm -> us: Check if recipientId exists + activate us + us -> db: Check if recipientId exists + activate db + db -> us: 0 rows + deactivate db + us -> rm: 0 rows + deactivate us + end + alt recipientType is FACILITY + rm -> fs: Check if recipientId exists + activate fs + fs -> db: Check if recipientId exists + activate db + db -> fs: 0 rows + deactivate db + fs -> rm: 0 rows + deactivate fs + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +alt recipientType is STAFF + rm -> us: Check if recipientId exists + activate us + us -> db: Check if recipientId exists + activate db + db -> us: 1 row + deactivate db + us -> rm: 1 row + deactivate us +end +alt recipientType is FACILITY + rm -> fs: Check if recipientId exists + activate fs + fs -> db: Check if recipientId exists + activate db + db -> fs: 1 row + deactivate db + fs -> rm: 1 row + deactivate fs +end +alt sideEffectId invalid + rm -> db: Check if sideEffectId exists + activate db + db -> rm: 0 rows + deactivate db + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +rm -> db: Check if referrerId exists +activate db +db -> rm: 1 row +deactivate db + +rm -> k: Referral Data /persist_topic +activate k +rm -> rc: Put Referral Data against clientReferenceId/serverGeneratedId in cache +activate rc +deactivate rc +group async + prs -> k: Consume Referral Data + activate prs + idx -> k: Consume Referral Data + activate idx + idx -> el: Store Referral Data + activate el + deactivate el + deactivate idx + prs -> db: Persist Referral Data + activate db + deactivate db + deactivate prs +end +deactivate k + +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/bulk_create.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/bulk_create.puml new file mode 100644 index 00000000000..9808045815c --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/bulk_create.puml @@ -0,0 +1,141 @@ +@startuml +title Side Effect - Bulk Create +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant RedisCache as rc +queue Kafka as k +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el +database Database as db + +c -> rm : /referralmanagement/side-effect/v1/bulk/_create +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: Side Effect Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume Side Effect Data + activate es + deactivate k + es -> db: Persist Side Effect Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +loop for each side-effect + alt record already exists + alt record found in cache + rm -> rc: Check using clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 1 row + deactivate rc + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_ALREADY_EXISTS + end note + end + rm -> rc: Check using clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Check if record already exists + activate db + db -> rm: 1 row + deactivate db + rm -> rc: Put data in cache using clientReferenceId/serverGeneratedId + activate rc + deactivate rc + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_ALREADY_EXISTS + end note + end + alt projectTaskId invalid + rm -> ps: Check if projectTaskId exists + activate ps + ps -> db: Check if projectTaskId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: BAD_REQUEST + end note + end + rm -> ps: Check if projectTaskId exists + activate ps + ps -> db: Check if projectTaskId exists + activate db + db -> ps: 1 row + deactivate db + ps -> rm: 1 row + deactivate ps + alt projectBeneficiaryId invalid + rm -> ps: Check if projectBeneficiaryId exists + activate ps + ps -> db: Check if projectBeneficiaryId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + rm -> ps: Check if projectBeneficiaryId exists + activate ps + ps -> db: Check if projectBeneficiaryId exists + activate db + db -> ps: 1 row + deactivate db + ps -> rm: 1 row + deactivate ps + rm -> k: Side Effect Data /persist_topic + activate k + rm -> rc: Put Side Effect Data against clientReferenceId/serverGeneratedId in cache + activate rc + deactivate rc + group async + prs -> k: Consume Side Effect Data + activate prs + idx -> k: Consume Side Effect Data + activate idx + idx -> el: Store Side Effect Data + activate el + deactivate el + deactivate idx + prs -> db: Persist Side Effect Data + activate db + deactivate db + deactivate prs + end + deactivate k +end +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/bulk_delete.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/bulk_delete.puml new file mode 100644 index 00000000000..1d95721ab4c --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/bulk_delete.puml @@ -0,0 +1,125 @@ +@startuml +title Side Effect - Bulk Delete +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant RedisCache as rc +queue Kafka as k +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el +database Database as db + +c -> rm : /referralmanagement/side-effect/v1/bulk/_delete +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: Side Effect Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume Side Effect Data + activate es + deactivate k + es -> db: Persist Side Effect Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +loop for each side-effect + alt id is null + rm -> rm: Check if Side Effect object id is null + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: NULL_ID + end note + end + rm -> rm: Check if Side Effect id is not null + alt record doesn't exist + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 0 row + deactivate db + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + rm -> k: Side Effect Data /error_topic + activate k + group async + es -> k: Consume Side Effect Data + activate es + deactivate k + es -> db: Persist Side Effect Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_NOT_FOUND + end note + end + alt record doesn't exists in cache + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 1 row + deactivate db + rm -> rc: 1 record + activate rc + deactivate rc + end + rm -> rc: Fetch the existing record + activate rc + rc -> rm: 1 row + deactivate rc + rm -> k: Side Effect Data /persist_topic + activate k + rm -> rc: Put Side Effect Data against clientReferenceId/serverGeneratedId in cache + activate rc + deactivate rc + group async + prs -> k: Consume Side Effect Data + activate prs + idx -> k: Consume Side Effect Data + activate idx + idx -> el: Store Side Effect Data + activate el + deactivate el + deactivate idx + prs -> db: Persist Side Effect Data + activate db + deactivate db + deactivate prs + end + deactivate k +end + +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/bulk_update.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/bulk_update.puml new file mode 100644 index 00000000000..85606389c27 --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/bulk_update.puml @@ -0,0 +1,177 @@ +@startuml +title Side Effect - Bulk Update +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant RedisCache as rc +queue Kafka as k +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el +database Database as db + +c -> rm : /referralmanagement/side-effect/v1/bulk/_update +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: Side Effect Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume Side Effect Data + activate es + deactivate k + es -> db: Persist Side Effect Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +loop for each side-effect + alt id is null + rm -> rm: Check if Side Effect object id is null + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: NULL_ID + end note + end + rm -> rm: Check if Side Effect id is not null + alt isDeleted is true + rm -> rm: Check if Side Effect object isDeleted is true + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: IS_DELETED_TRUE + end note + end + rm -> rm: Check if Side Effect object isDeleted is not true + alt record doesn't exist + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 0 row + deactivate db + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + rm -> k: Side Effect Data /error_topic + activate k + group async + es -> k: Consume Side Effect Data + activate es + deactivate k + es -> db: Persist Side Effect Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_NOT_FOUND + end note + end + alt record doesn't exists in cache + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 1 row + deactivate db + rm -> rc: 1 record + activate rc + deactivate rc + end + rm -> rc: Fetch the existing record + activate rc + rc -> rm: 1 row + deactivate rc + alt projectTaskId invalid + rm -> ps: Check if projectTaskId exists + activate ps + ps -> db: Check if projectTaskId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: BAD_REQUEST + end note + end + rm -> ps: Check if projectTaskId exists + activate ps + ps -> db: Check if projectTaskId exists + activate db + db -> ps: 1 row + deactivate db + ps -> rm: 1 row + deactivate ps + alt projectBeneficiaryId invalid + rm -> ps: Check if projectBeneficiaryId exists + activate ps + ps -> db: Check if projectBeneficiaryId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note + end + rm -> ps: Check if projectBeneficiaryId exists + activate ps + ps -> db: Check if projectBeneficiaryId exists + activate db + db -> ps: 1 row + deactivate db + ps -> rm: 1 row + deactivate ps + rm -> k: Side Effect Data /persist_topic + activate k + rm -> rc: Put Side Effect Data against clientReferenceId/serverGeneratedId in cache + activate rc + deactivate rc + group async + prs -> k: Consume Side Effect Data + activate prs + idx -> k: Consume Side Effect Data + activate idx + idx -> el: Store Side Effect Data + activate el + deactivate el + deactivate idx + prs -> db: Persist Side Effect Data + activate db + deactivate db + deactivate prs + end + deactivate k +end + +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/create.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/create.puml new file mode 100644 index 00000000000..94d0a3b95ca --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/create.puml @@ -0,0 +1,140 @@ +@startuml +title Side Effect - Create +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant RedisCache as rc +queue Kafka as k +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el +database Database as db + +c -> rm : /referralmanagement/side-effect/v1/_create +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: Side Effect Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume Side Effect Data + activate es + deactivate k + es -> db: Persist Side Effect Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +alt record already exists + alt record found in cache + rm -> rc: Check using clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 1 row + deactivate rc + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_ALREADY_EXISTS + end note + end + rm -> rc: Check using clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Check if record already exists + activate db + db -> rm: 1 row + deactivate db + rm -> rc: Put data in cache using clientReferenceId/serverGeneratedId + activate rc + deactivate rc + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_ALREADY_EXISTS + end note +end +alt projectTaskId invalid + rm -> ps: Check if projectTaskId exists + activate ps + ps -> db: Check if projectTaskId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: BAD_REQUEST + end note +end +rm -> ps: Check if projectTaskId exists +activate ps +ps -> db: Check if projectTaskId exists +activate db +db -> ps: 1 row +deactivate db +ps -> rm: 1 row +deactivate ps +alt projectBeneficiaryId invalid + rm -> ps: Check if projectBeneficiaryId exists + activate ps + ps -> db: Check if projectBeneficiaryId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +rm -> ps: Check if projectBeneficiaryId exists +activate ps +ps -> db: Check if projectBeneficiaryId exists +activate db +db -> ps: 1 row +deactivate db +ps -> rm: 1 row +deactivate ps +rm -> k: Side Effect Data /persist_topic +activate k +rm -> rc: Put Side Effect Data against clientReferenceId/serverGeneratedId in cache +activate rc +deactivate rc +group async + prs -> k: Consume Side Effect Data + activate prs + idx -> k: Consume Side Effect Data + activate idx + idx -> el: Store Side Effect Data + activate el + deactivate el + deactivate idx + prs -> db: Persist Side Effect Data + activate db + deactivate db + deactivate prs +end +deactivate k + +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/delete.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/delete.puml new file mode 100644 index 00000000000..77727af23d2 --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/delete.puml @@ -0,0 +1,123 @@ +@startuml +title Side Effect - Delete +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant RedisCache as rc +queue Kafka as k +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el +database Database as db + +c -> rm : /referralmanagement/side-effect/v1/_delete +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: Side Effect Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume Side Effect Data + activate es + deactivate k + es -> db: Persist Side Effect Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +alt id is null + rm -> rm: Check if Side Effect object id is null + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: NULL_ID + end note +end +rm -> rm: Check if Side Effect id is not null +alt record doesn't exist + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 0 row + deactivate db + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + rm -> k: Side Effect Data /error_topic + activate k + group async + es -> k: Consume Side Effect Data + activate es + deactivate k + es -> db: Persist Side Effect Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_NOT_FOUND + end note +end +alt record doesn't exists in cache + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 1 row + deactivate db + rm -> rc: 1 record + activate rc + deactivate rc +end +rm -> rc: Fetch the existing record +activate rc +rc -> rm: 1 row +deactivate rc +rm -> k: Side Effect Data /persist_topic +activate k +rm -> rc: Put Side Effect Data against clientReferenceId/serverGeneratedId in cache +activate rc +deactivate rc +group async + prs -> k: Consume Side Effect Data + activate prs + idx -> k: Consume Side Effect Data + activate idx + idx -> el: Store Side Effect Data + activate el + deactivate el + deactivate idx + prs -> db: Persist Side Effect Data + activate db + deactivate db + deactivate prs +end +deactivate k + +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/update.puml b/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/update.puml new file mode 100644 index 00000000000..896e5d40fbc --- /dev/null +++ b/docs/health-api-specs/sequence-diagrams/referralmanagement/side-effect/update.puml @@ -0,0 +1,175 @@ +@startuml +title Side Effect - Update +!theme vibrant +participant Client as c +participant ReferralManagement as rm +participant FacilityService as fs +participant HouseholdService as hs +participant IndividualService as inds +participant ProjectService as ps +participant RedisCache as rc +queue Kafka as k +participant PersisterService as prs +participant IndexerService as idx +participant ErrorService as es +participant ElasticSearch as el +database Database as db + +c -> rm : /referralmanagement/side-effect/v1/_update +activate rm +rm -> rm : Validate request body + +alt request validation fails + rm -> rm: Request validation failed + rm -> k: Side Effect Data /error_topic + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + activate k + group async + es -> k: Consume Side Effect Data + activate es + deactivate k + es -> db: Persist Side Effect Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: REQUEST_VALIDATION_FAILED + end note +end +rm -> rm: Request validation successful +alt id is null + rm -> rm: Check if Side Effect object id is null + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: NULL_ID + end note +end +rm -> rm: Check if Side Effect id is not null +alt isDeleted is true + rm -> rm: Check if Side Effect object isDeleted is true + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: IS_DELETED_TRUE + end note +end +rm -> rm: Check if Side Effect object isDeleted is not true +alt record doesn't exist + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 0 row + deactivate db + note left + This will be marked as unrecoverable right away + and require manual intervention + end note + rm -> k: Side Effect Data /error_topic + activate k + group async + es -> k: Consume Side Effect Data + activate es + deactivate k + es -> db: Persist Side Effect Data /error_table + activate db + deactivate db + deactivate es + end + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: RECORD_NOT_FOUND + end note +end +alt record doesn't exists in cache + rm -> rc: Search record based on clientReferenceId/serverGeneratedId + activate rc + rc -> rm: 0 rows + deactivate rc + rm -> db: Search record based on clientReferenceId/serverGeneratedId + activate db + db -> rm: 1 row + deactivate db + rm -> rc: 1 record + activate rc + deactivate rc +end +rm -> rc: Fetch the existing record +activate rc +rc -> rm: 1 row +deactivate rc +alt projectTaskId invalid + rm -> ps: Check if projectTaskId exists + activate ps + ps -> db: Check if projectTaskId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: BAD_REQUEST + end note +end +rm -> ps: Check if projectTaskId exists +activate ps +ps -> db: Check if projectTaskId exists +activate db +db -> ps: 1 row +deactivate db +ps -> rm: 1 row +deactivate ps +alt projectBeneficiaryId invalid + rm -> ps: Check if projectBeneficiaryId exists + activate ps + ps -> db: Check if projectBeneficiaryId exists + activate db + db -> ps: 0 rows + deactivate db + ps -> rm: 0 rows + deactivate ps + rm -> c: HttpStatus: 400 with appropriate error code + note left + Error Code: DEPENDENCY_ERROR + end note +end +rm -> ps: Check if projectBeneficiaryId exists +activate ps +ps -> db: Check if projectBeneficiaryId exists +activate db +db -> ps: 1 row +deactivate db +ps -> rm: 1 row +deactivate ps +rm -> k: Side Effect Data /persist_topic +activate k +rm -> rc: Put Side Effect Data against clientReferenceId/serverGeneratedId in cache +activate rc +deactivate rc +group async + prs -> k: Consume Side Effect Data + activate prs + idx -> k: Consume Side Effect Data + activate idx + idx -> el: Store Side Effect Data + activate el + deactivate el + deactivate idx + prs -> db: Persist Side Effect Data + activate db + deactivate db + deactivate prs +end +deactivate k + +rm -> c : HttpStatus: 202 ACCEPTED +deactivate rm + +@enduml \ No newline at end of file diff --git a/health-services/household/CHANGELOG.md b/health-services/household/CHANGELOG.md index 11569f76ee5..0cb9052cea7 100644 --- a/health-services/household/CHANGELOG.md +++ b/health-services/household/CHANGELOG.md @@ -1,9 +1,9 @@ All notable changes to this module will be documented in this file. -## 1.1.1 +## 1.1.1 - 2023-11-15 - Added total count for household -- Added a field for HouseholdMember : clientReferenceId +- Added a field for HouseholdMember-clientReferenceId ## 1.1.1-beta diff --git a/health-services/individual/CHANGELOG.md b/health-services/individual/CHANGELOG.md index 6e8364117b0..5dbb29c3029 100644 --- a/health-services/individual/CHANGELOG.md +++ b/health-services/individual/CHANGELOG.md @@ -1,5 +1,8 @@ All notable changes to this module will be documented in this file. +## 1.1.3 +- Search by uuid added for individual search + ## 1.1.2 - upgraded version from beta diff --git a/health-services/individual/src/main/java/org/egov/individual/repository/IndividualRepository.java b/health-services/individual/src/main/java/org/egov/individual/repository/IndividualRepository.java index 4362e1f1811..eecf48c03d7 100644 --- a/health-services/individual/src/main/java/org/egov/individual/repository/IndividualRepository.java +++ b/health-services/individual/src/main/java/org/egov/individual/repository/IndividualRepository.java @@ -269,12 +269,21 @@ private String getQueryForIndividual(IndividualSearch searchObject, Integer limi query = query + "AND userId=:userId "; paramsMap.put("userId", String.valueOf(searchObject.getUserId())); } + + if (searchObject.getUserUuid() != null) { + query = query + "AND userUuid in (:userUuid) "; + paramsMap.put("userUuid", searchObject.getUserUuid()); + } + query = query + "ORDER BY id ASC LIMIT :limit OFFSET :offset"; paramsMap.put("tenantId", tenantId); paramsMap.put("isDeleted", includeDeleted); paramsMap.put("lastModifiedTime", lastChangedSince); paramsMap.put("limit", limit); paramsMap.put("offset", offset); + + log.info("query-------------------------->"); + log.info(query); return query; } diff --git a/health-services/individual/src/main/java/org/egov/individual/web/models/IndividualSearch.java b/health-services/individual/src/main/java/org/egov/individual/web/models/IndividualSearch.java index 397b60304ce..35d1ffdc6a7 100644 --- a/health-services/individual/src/main/java/org/egov/individual/web/models/IndividualSearch.java +++ b/health-services/individual/src/main/java/org/egov/individual/web/models/IndividualSearch.java @@ -99,6 +99,10 @@ public class IndividualSearch { @JsonProperty("userId") private Long userId; + @Exclude + @JsonProperty("userUuid") + private List userUuid; + @Exclude @JsonProperty("latitude") @DecimalMin("-90") diff --git a/health-services/individual/src/test/java/org/egov/individual/helper/IndividualSearchTestBuilder.java b/health-services/individual/src/test/java/org/egov/individual/helper/IndividualSearchTestBuilder.java index 6db1b119462..ed10e84d6c5 100644 --- a/health-services/individual/src/test/java/org/egov/individual/helper/IndividualSearchTestBuilder.java +++ b/health-services/individual/src/test/java/org/egov/individual/helper/IndividualSearchTestBuilder.java @@ -53,7 +53,17 @@ public IndividualSearchTestBuilder byClientReferenceId(String... args) { this.builder.clientReferenceId(ids); return this; } + public IndividualSearchTestBuilder byUserUUID(String... args) { + ArrayList ids = new ArrayList<>(); + if (args != null && args.length > 0) { + ids.add(args[0]); + } else { + ids.add("some-user-uuid"); + } + this.builder.userUuid(ids); + return this; + } public IndividualSearchTestBuilder byName() { this.builder.name(Name.builder() diff --git a/health-services/individual/src/test/java/org/egov/individual/repository/IndividualRepositoryTest.java b/health-services/individual/src/test/java/org/egov/individual/repository/IndividualRepositoryTest.java index 3e73c932c08..8167285ff87 100644 --- a/health-services/individual/src/test/java/org/egov/individual/repository/IndividualRepositoryTest.java +++ b/health-services/individual/src/test/java/org/egov/individual/repository/IndividualRepositoryTest.java @@ -88,6 +88,7 @@ void shouldFindOtherParamsFromDbAndReturnAllTheDependentEntitiesAsWellIfPresent( IndividualSearch individualSearch = IndividualSearchTestBuilder.builder() .byId() .byClientReferenceId() + .byUserUUID() .byGender() .byName() .byDateOfBirth() @@ -145,6 +146,7 @@ void shouldFindOtherParamsAndIdentifierFromDbAndReturnAllTheDependentEntitiesAsW IndividualSearch individualSearch = IndividualSearchTestBuilder.builder() .byId() .byClientReferenceId() + .byUserUUID() .byGender() .byName() .byDateOfBirth() diff --git a/health-services/libraries/health-services-models/CHANGELOG.md b/health-services/libraries/health-services-models/CHANGELOG.md index ebef76b1fd0..5b463165a95 100644 --- a/health-services/libraries/health-services-models/CHANGELOG.md +++ b/health-services/libraries/health-services-models/CHANGELOG.md @@ -1,6 +1,13 @@ All notable changes to this module will be documented in this file. -## 1.0.11 +## 1.0.19 - 2024-02-26 +- Project staff search staffId changed to a list +- Stock senderid and receiver id is added. + +## 1.0.18 - 2024-02-13 +- Adding user uuid in individual search + +## 1.0.11 - 2023-11-15 - Client reference id added for member of household - revert of household search change diff --git a/health-services/libraries/health-services-models/pom.xml b/health-services/libraries/health-services-models/pom.xml index 683fa9392f1..3dafc7c24a0 100644 --- a/health-services/libraries/health-services-models/pom.xml +++ b/health-services/libraries/health-services-models/pom.xml @@ -5,7 +5,7 @@ 4.0.0 org.egov.common health-services-models - 1.0.11-SNAPSHOT + 1.0.19-SNAPSHOT 8 8 @@ -28,6 +28,11 @@ digit-models 1.0.0-SNAPSHOT + + org.egov.services + tracer + 2.1.4-SNAPSHOT + diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/core/validator/CustomIntegerDeserializer.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/core/validator/CustomIntegerDeserializer.java new file mode 100644 index 00000000000..b5cb00eac27 --- /dev/null +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/core/validator/CustomIntegerDeserializer.java @@ -0,0 +1,43 @@ +package org.egov.common.models.core.validator; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; +import org.egov.tracer.model.CustomException; + +// Custom deserializer for Integer values +public class CustomIntegerDeserializer extends StdDeserializer { + + public CustomIntegerDeserializer() { + this(null); + } + + public CustomIntegerDeserializer(Class vc) { + super(vc); + } + + @Override + public Integer deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + + // Read the JSON tree from the parser + JsonNode node = jsonParser.getCodec().readTree(jsonParser); + System.out.println(node.toString()); + if(node.asLong() > Integer.MAX_VALUE){ + throw new CustomException("INVALID_INPUT","Value must be an Integer"); + } + + // Parse the quantity as an integer + int quantity = node.asInt(); + + // Check if the parsed quantity matches the original string representation + if ((double) quantity != Double.parseDouble(node.asText())) { + throw new CustomException("INVALID_INPUT", "Quantity must be an integer"); + } + + // Return the parsed quantity + return quantity; + } +} diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/facility/Field.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/facility/Field.java index e836f7dcc4b..78218ccbf63 100644 --- a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/facility/Field.java +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/facility/Field.java @@ -1,5 +1,8 @@ package org.egov.common.models.facility; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; @@ -8,9 +11,6 @@ import lombok.NoArgsConstructor; import org.springframework.validation.annotation.Validated; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - /** * Field */ @@ -30,7 +30,7 @@ public class Field { @JsonProperty("value") @NotNull - @Size(min = 2, max = 10000) + @Size(min = 1, max = 10000) private String value = null; diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/household/Field.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/household/Field.java index ba8246ab184..bb53d162286 100644 --- a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/household/Field.java +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/household/Field.java @@ -1,5 +1,8 @@ package org.egov.common.models.household; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; @@ -8,9 +11,6 @@ import lombok.NoArgsConstructor; import org.springframework.validation.annotation.Validated; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - /** * Field */ @@ -22,23 +22,16 @@ @AllArgsConstructor @Builder @JsonIgnoreProperties(ignoreUnknown = true) -public class Field { - @JsonProperty("key") - @NotNull - - - @Size(min=2,max=64) - +public class Field { + @JsonProperty("key") + @NotNull + @Size(min = 2, max = 64) private String key = null; - @JsonProperty("value") - @NotNull - - - @Size(min=2,max=10000) - + @JsonProperty("value") + @NotNull + @Size(min = 1, max = 10000) private String value = null; - } diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/household/HouseholdSearch.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/household/HouseholdSearch.java index 8adfbfeee88..6e31a74c882 100644 --- a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/household/HouseholdSearch.java +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/household/HouseholdSearch.java @@ -33,9 +33,6 @@ public class HouseholdSearch { @JsonProperty("clientReferenceId") private List clientReferenceId = null; -// @JsonProperty("memberCount") -// private Integer memberCount = null; - @JsonProperty("boundaryCode") private String localityCode = null; } diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/individual/Field.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/individual/Field.java index 62cc4f84377..b189fbe154e 100644 --- a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/individual/Field.java +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/individual/Field.java @@ -1,5 +1,8 @@ package org.egov.common.models.individual; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; @@ -8,9 +11,6 @@ import lombok.NoArgsConstructor; import org.springframework.validation.annotation.Validated; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - /** * Field */ @@ -22,23 +22,16 @@ @AllArgsConstructor @Builder @JsonIgnoreProperties(ignoreUnknown = true) -public class Field { - @JsonProperty("key") - @NotNull - - - @Size(min=2,max=64) - +public class Field { + @JsonProperty("key") + @NotNull + @Size(min = 2, max = 64) private String key = null; - @JsonProperty("value") - @NotNull - - - @Size(min=2,max=10000) - + @JsonProperty("value") + @NotNull + @Size(min = 1, max = 10000) private String value = null; - } diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/individual/IndividualSearch.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/individual/IndividualSearch.java index 7dff5b261d7..90033f3414b 100644 --- a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/individual/IndividualSearch.java +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/individual/IndividualSearch.java @@ -82,5 +82,8 @@ public class IndividualSearch { @JsonProperty("userId") private Long userId; + + @JsonProperty("userUuid") + private List userUuid; } diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/product/Field.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/product/Field.java index 2c2f099f003..828a1cad303 100644 --- a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/product/Field.java +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/product/Field.java @@ -1,5 +1,8 @@ package org.egov.common.models.product; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; @@ -8,9 +11,6 @@ import lombok.NoArgsConstructor; import org.springframework.validation.annotation.Validated; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - /** * Field */ @@ -22,23 +22,16 @@ @AllArgsConstructor @Builder @JsonIgnoreProperties(ignoreUnknown = true) -public class Field { - @JsonProperty("key") - @NotNull - - - @Size(min=2,max=64) - +public class Field { + @JsonProperty("key") + @NotNull + @Size(min = 2, max = 64) private String key = null; - @JsonProperty("value") - @NotNull - - - @Size(min=2,max=10000) - + @JsonProperty("value") + @NotNull + @Size(min = 1, max = 10000) private String value = null; - } diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/project/Field.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/project/Field.java index 33a82b187b7..c4f47fe7a7e 100644 --- a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/project/Field.java +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/project/Field.java @@ -1,5 +1,8 @@ package org.egov.common.models.project; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; @@ -8,9 +11,6 @@ import lombok.NoArgsConstructor; import org.springframework.validation.annotation.Validated; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - /** * Field */ @@ -22,8 +22,7 @@ @AllArgsConstructor @Builder @JsonIgnoreProperties(ignoreUnknown = true) -public class Field { - +public class Field { @JsonProperty("key") @NotNull @Size(min = 2, max = 64) @@ -31,7 +30,8 @@ public class Field { @JsonProperty("value") @NotNull - @Size(min = 2, max = 10000) + @Size(min = 1, max = 10000) private String value = null; + } diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/project/ProjectStaffSearch.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/project/ProjectStaffSearch.java index f32cc34aa7d..940ec9bfb63 100644 --- a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/project/ProjectStaffSearch.java +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/project/ProjectStaffSearch.java @@ -13,9 +13,9 @@ import java.util.List; /** -* This object defines the mapping of a system staff user to a project for a certain period. -*/ - @ApiModel(description = "This object defines the mapping of a system staff user to a project for a certain period.") + * This object defines the mapping of a system staff user to a project for a certain period. + */ +@ApiModel(description = "This object defines the mapping of a system staff user to a project for a certain period.") @Validated @javax.annotation.Generated(value = "org.egov.codegen.SpringBootCodegen", date = "2022-12-02T17:32:25.406+05:30") @@ -23,23 +23,23 @@ @NoArgsConstructor @AllArgsConstructor @Builder - @JsonIgnoreProperties(ignoreUnknown = true) -public class ProjectStaffSearch { +@JsonIgnoreProperties(ignoreUnknown = true) +public class ProjectStaffSearch { @JsonProperty("id") private List id = null; @JsonProperty("tenantId") - @Size(min=2,max=1000) + @Size(min = 2, max = 1000) private String tenantId = null; @JsonProperty("staffId") - @Size(min=2,max=64) - private String staffId = null; + @Size(min = 2, max = 64) + private List staffId = null; @JsonProperty("projectId") - @Size(min=2,max=64) + @Size(min = 2, max = 64) private String projectId = null; @JsonProperty("startDate") diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferral.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferral.java new file mode 100644 index 00000000000..330b437df95 --- /dev/null +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferral.java @@ -0,0 +1,84 @@ +package org.egov.common.models.referralmanagement.hfreferral; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import digit.models.coremodels.AuditDetails; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.egov.common.models.project.AdditionalFields; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class HFReferral { + + @JsonProperty("id") + @Size(min = 2, max = 64) + private String id; + + @JsonProperty("clientReferenceId") + @Size(min = 2, max = 64) + private String clientReferenceId; + + @JsonProperty("tenantId") + @NotNull + @Size(min=2, max = 1000) + private String tenantId; + + @JsonProperty("projectId") + @Size(min = 2, max = 64) + private String projectId; + + @JsonProperty("projectFacilityId") + @Size(min = 2, max = 64) + private String projectFacilityId; + + @JsonProperty("symptom") + @NotNull + @Size(min = 2, max = 256) + private String symptom; + + @JsonProperty("symptomSurveyId") + @Size(min = 2, max = 100) + private String symptomSurveyId; + + @JsonProperty("beneficiaryId") + @Size(max=100) + private String beneficiaryId; + + @JsonProperty("referralCode") + @Size(max=100) + private String referralCode; + + @JsonProperty("nationalLevelId") + @Size(max=100) + private String nationalLevelId; + + @JsonProperty("isDeleted") + private Boolean isDeleted = Boolean.FALSE; + + @JsonProperty("rowVersion") + private Integer rowVersion; + + @JsonProperty("auditDetails") + @Valid + private AuditDetails auditDetails; + + @JsonProperty("clientAuditDetails") + @Valid + private AuditDetails clientAuditDetails; + + @JsonProperty("additionalFields") + @Valid + private AdditionalFields additionalFields; + + @JsonIgnore + private Boolean hasErrors = Boolean.FALSE; +} diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralBulkRequest.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralBulkRequest.java new file mode 100644 index 00000000000..358cb03135c --- /dev/null +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralBulkRequest.java @@ -0,0 +1,46 @@ +package org.egov.common.models.referralmanagement.hfreferral; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.egov.common.contract.request.RequestInfo; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class HFReferralBulkRequest { + @JsonProperty("RequestInfo") + @NotNull + @Valid + private RequestInfo requestInfo; + + @JsonProperty("HFReferrals") + @NotNull + @Valid + @Size(min = 1) + private List hfReferrals; + + /** + * Add a HfReferral item to the list of HfReferrals in the bulk request. + * + * @param hfReferralItem The HfReferral item to add to the request. + * @return The updated HFReferralBulkRequest. + */ + public HFReferralBulkRequest addHFReferralItem(HFReferral hfReferralItem) { + if(Objects.isNull(hfReferrals)) + hfReferrals = new ArrayList<>(); + if(Objects.nonNull(hfReferralItem)) + hfReferrals.add(hfReferralItem); + return this; + } +} diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralBulkResponse.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralBulkResponse.java new file mode 100644 index 00000000000..a0f1c04b090 --- /dev/null +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralBulkResponse.java @@ -0,0 +1,44 @@ +package org.egov.common.models.referralmanagement.hfreferral; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.egov.common.contract.response.ResponseInfo; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class HFReferralBulkResponse { + @JsonProperty("ResponseInfo") + @NotNull + @Valid + private ResponseInfo responseInfo; + + @JsonProperty("HFReferrals") + @NotNull + @Valid + private List hfReferrals; + + /** + * Add a HfReferral item to the list of HfReferrals in the bulk response. + * + * @param hfReferralItem The HfReferral item to add to the response. + * @return The updated HFReferralBulkRequest. + */ + public HFReferralBulkResponse addReferralItem(HFReferral hfReferralItem) { + if(Objects.isNull(hfReferrals)) + hfReferrals = new ArrayList<>(); + if(Objects.nonNull(hfReferralItem)) + hfReferrals.add(hfReferralItem); + return this; + } +} diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralRequest.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralRequest.java new file mode 100644 index 00000000000..3adc90053b6 --- /dev/null +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralRequest.java @@ -0,0 +1,27 @@ +package org.egov.common.models.referralmanagement.hfreferral; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.egov.common.contract.request.RequestInfo; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class HFReferralRequest { + @JsonProperty("RequestInfo") + @NotNull + @Valid + private RequestInfo requestInfo; + + @JsonProperty("HFReferral") + @NotNull + @Valid + private HFReferral hfReferral; +} diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralResponse.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralResponse.java new file mode 100644 index 00000000000..24471207656 --- /dev/null +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralResponse.java @@ -0,0 +1,27 @@ +package org.egov.common.models.referralmanagement.hfreferral; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.egov.common.contract.response.ResponseInfo; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class HFReferralResponse { + @JsonProperty("ResponseInfo") + @NotNull + @Valid + private ResponseInfo responseInfo; + + @JsonProperty("HFReferral") + @NotNull + @Valid + private HFReferral hfReferral; +} diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralSearch.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralSearch.java new file mode 100644 index 00000000000..02dbfdf899a --- /dev/null +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralSearch.java @@ -0,0 +1,45 @@ +package org.egov.common.models.referralmanagement.hfreferral; + +import java.util.List; + +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class HFReferralSearch { + @JsonProperty("id") + private List id; + + @JsonProperty("clientReferenceId") + private List clientReferenceId; + + @JsonProperty("facilityId") + private List facilityId; + + @JsonProperty("projectId") + private String projectId; + + @JsonProperty("symptom") + private List symptom; + + @JsonProperty("symptomSurveyId") + private List symptomSurveyId; + + @JsonProperty("beneficiaryId") + private List beneficiaryId; + + @JsonProperty("referralCode") + private List referralCode; + + @JsonProperty("nationalLevelId") + private List nationalLevelId; +} diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralSearchRequest.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralSearchRequest.java new file mode 100644 index 00000000000..4784f9fbdad --- /dev/null +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/referralmanagement/hfreferral/HFReferralSearchRequest.java @@ -0,0 +1,26 @@ +package org.egov.common.models.referralmanagement.hfreferral; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.egov.common.contract.request.RequestInfo; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class HFReferralSearchRequest { + @JsonProperty("RequestInfo") + @NotNull + @Valid + private RequestInfo requestInfo; + + @JsonProperty("HFReferral") + @Valid + private HFReferralSearch hfReferral; +} diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/Field.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/Field.java index 73dab0bcb93..4994957dd27 100644 --- a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/Field.java +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/Field.java @@ -1,5 +1,8 @@ package org.egov.common.models.stock; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; @@ -8,9 +11,6 @@ import lombok.NoArgsConstructor; import org.springframework.validation.annotation.Validated; -import javax.validation.constraints.NotNull; -import javax.validation.constraints.Size; - /** * Field */ @@ -22,23 +22,16 @@ @AllArgsConstructor @Builder @JsonIgnoreProperties(ignoreUnknown = true) -public class Field { - @JsonProperty("key") - @NotNull - - - @Size(min=2,max=64) - +public class Field { + @JsonProperty("key") + @NotNull + @Size(min = 2, max = 64) private String key = null; - @JsonProperty("value") - @NotNull - - - @Size(min=1,max=10000) - + @JsonProperty("value") + @NotNull + @Size(min = 1, max = 10000) private String value = null; - } diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/ReferenceIdType.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/ReferenceIdType.java new file mode 100644 index 00000000000..7b5943c3493 --- /dev/null +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/ReferenceIdType.java @@ -0,0 +1,32 @@ +package org.egov.common.models.stock; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonValue; + +@JsonIgnoreProperties(ignoreUnknown = true) +public enum ReferenceIdType { + PROJECT("PROJECT"), + OTHER("OTHER"); + private String value; + + ReferenceIdType(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static ReferenceIdType fromValue(String text) { + for (ReferenceIdType b : ReferenceIdType.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } +} diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/SenderReceiverType.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/SenderReceiverType.java new file mode 100644 index 00000000000..e5b1924574a --- /dev/null +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/SenderReceiverType.java @@ -0,0 +1,34 @@ +package org.egov.common.models.stock; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonValue; + +@JsonIgnoreProperties(ignoreUnknown = true) +public enum SenderReceiverType { + WAREHOUSE("WAREHOUSE"), + + STAFF("STAFF"); + + private String value; + + SenderReceiverType(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static SenderReceiverType fromValue(String text) { + for (SenderReceiverType b : SenderReceiverType.values()) { + if (String.valueOf(b.value).equals(text)) { + return b; + } + } + return null; + } +} diff --git a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/Stock.java b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/Stock.java index a08748daf49..c53164b370c 100644 --- a/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/Stock.java +++ b/health-services/libraries/health-services-models/src/main/java/org/egov/common/models/stock/Stock.java @@ -1,21 +1,21 @@ package org.egov.common.models.stock; import javax.validation.Valid; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; -import org.springframework.validation.annotation.Validated; - import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; - import digit.models.coremodels.AuditDetails; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Builder.Default; import lombok.Data; import lombok.NoArgsConstructor; +import org.springframework.validation.annotation.Validated; /** * Stock @@ -51,6 +51,8 @@ public class Stock { @JsonProperty("quantity") @NotNull + @Min(value = 1, message = "Minimum value cannot be less than 1") + @Max(value = Integer.MAX_VALUE, message = "Value exceeds maximum allowable limit") private Integer quantity; /* project id in-case of health */ @@ -58,12 +60,13 @@ public class Stock { private String referenceId; @JsonProperty("referenceIdType") - @Size(min=2, max=64) - private String referenceIdType; + @NotNull(message = "referenceIdType must be PROJECT or OTHER") + @Valid + private ReferenceIdType referenceIdType; // transaction fields @JsonProperty("transactionType") - @NotNull + @NotNull(message = "transactionType must be either RECEIVED or DISPATCHED") @Valid private TransactionType transactionType; @@ -77,9 +80,9 @@ public class Stock { private String senderId; @JsonProperty("senderType") - @NotNull - @Size(min=2, max=64) - private String senderType; + @NotNull(message = "Sender Type can be either WAREHOUSE or STAFF") + @Valid + private SenderReceiverType senderType; @JsonProperty("receiverId") @NotNull @@ -87,9 +90,9 @@ public class Stock { private String receiverId; @JsonProperty("receiverType") - @NotNull - @Size(min=2, max=64) - private String receiverType; + @NotNull(message = "Receiver Type can be either WAREHOUSE or STAFF") + @Valid + private SenderReceiverType receiverType; @JsonProperty("wayBillNumber") @Size(min = 2, max = 200) diff --git a/health-services/project/CHANGELOG.md b/health-services/project/CHANGELOG.md index 4f8ef2bc6ca..0cd43b1c827 100644 --- a/health-services/project/CHANGELOG.md +++ b/health-services/project/CHANGELOG.md @@ -1,6 +1,9 @@ All notable changes to this module will be documented in this file. -## 1.1.1 +## 1.1.2 - 2024-02-26 +- Added Project start date and end date update validation + +## 1.1.1 - 2023-11-15 - Added tag in project beneficiary ## 1.1.1-beta 19-10-2023 diff --git a/health-services/project/src/main/java/org/egov/project/config/ProjectConfiguration.java b/health-services/project/src/main/java/org/egov/project/config/ProjectConfiguration.java index fe9291ab137..34308dd587f 100644 --- a/health-services/project/src/main/java/org/egov/project/config/ProjectConfiguration.java +++ b/health-services/project/src/main/java/org/egov/project/config/ProjectConfiguration.java @@ -183,4 +183,7 @@ public class ProjectConfiguration { @Value("${egov.user.id.validator}") private String egovUserIdValidator; + @Value("${project.staff.attendance.topic}") + private String projectStaffAttendanceTopic; + } diff --git a/health-services/project/src/main/java/org/egov/project/service/ProjectStaffService.java b/health-services/project/src/main/java/org/egov/project/service/ProjectStaffService.java index 3c299826c90..4d0a276c552 100644 --- a/health-services/project/src/main/java/org/egov/project/service/ProjectStaffService.java +++ b/health-services/project/src/main/java/org/egov/project/service/ProjectStaffService.java @@ -6,6 +6,7 @@ import org.egov.common.models.project.ProjectStaff; import org.egov.common.models.project.ProjectStaffBulkRequest; import org.egov.common.models.project.ProjectStaffRequest; +import org.egov.common.producer.Producer; import org.egov.common.service.IdGenService; import org.egov.common.service.UserService; import org.egov.common.utils.CommonUtils; @@ -26,7 +27,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.lang.reflect.Type; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Predicate; @@ -60,6 +63,8 @@ public class ProjectStaffService { private final List> validators; + private final Producer producer; + private final Predicate> isApplicableForCreate = validator -> validator.getClass().equals(PsUserIdValidator.class) || validator.getClass().equals(PsProjectIdValidator.class) @@ -86,7 +91,8 @@ public ProjectStaffService( ProjectService projectService, UserService userService, ProjectConfiguration projectConfiguration, - ProjectStaffEnrichmentService enrichmentService, List> validators) { + ProjectStaffEnrichmentService enrichmentService, + Producer producer, List> validators) { this.idGenService = idGenService; this.projectStaffRepository = projectStaffRepository; this.projectService = projectService; @@ -94,6 +100,7 @@ public ProjectStaffService( this.projectConfiguration = projectConfiguration; this.enrichmentService = enrichmentService; this.validators = validators; + this.producer = producer; } public ProjectStaff create(ProjectStaffRequest request) { @@ -117,6 +124,7 @@ public List create(ProjectStaffBulkRequest request, boolean isBulk if (!validEntities.isEmpty()) { log.info("processing {} valid entities", validEntities.size()); enrichmentService.create(validEntities, request); + producer.push(projectConfiguration.getProjectStaffAttendanceTopic(), new ProjectStaffBulkRequest(request.getRequestInfo(),validEntities)); projectStaffRepository.save(validEntities, projectConfiguration.getCreateProjectStaffTopic()); log.info("successfully created project staff"); } diff --git a/health-services/project/src/main/java/org/egov/project/util/MDMSUtils.java b/health-services/project/src/main/java/org/egov/project/util/MDMSUtils.java index 950985ac246..27300bff902 100644 --- a/health-services/project/src/main/java/org/egov/project/util/MDMSUtils.java +++ b/health-services/project/src/main/java/org/egov/project/util/MDMSUtils.java @@ -1,5 +1,10 @@ package org.egov.project.util; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; + import digit.models.coremodels.mdms.MasterDetail; import digit.models.coremodels.mdms.MdmsCriteria; import digit.models.coremodels.mdms.MdmsCriteriaReq; @@ -14,16 +19,13 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; - +import static org.egov.project.util.ProjectConstants.MASTER_ATTENDANCE_SESSION; import static org.egov.project.util.ProjectConstants.MASTER_DEPARTMENT; import static org.egov.project.util.ProjectConstants.MASTER_NATUREOFWORK; import static org.egov.project.util.ProjectConstants.MASTER_PROJECTTYPE; import static org.egov.project.util.ProjectConstants.MASTER_TENANTS; import static org.egov.project.util.ProjectConstants.MDMS_COMMON_MASTERS_MODULE_NAME; +import static org.egov.project.util.ProjectConstants.MDMS_HCM_ATTENDANCE_MODULE_NAME; import static org.egov.project.util.ProjectConstants.MDMS_TENANT_MODULE_NAME; @Component @@ -58,11 +60,13 @@ public MdmsCriteriaReq getMDMSRequest(RequestInfo requestInfo, String tenantId, ModuleDetail projectMDMSModuleDetail = getMDMSModuleRequestData(request); ModuleDetail projectDepartmentModuleDetail = getDepartmentModuleRequestData(request); ModuleDetail projectTenantModuleDetail = getTenantModuleRequestData(request); + ModuleDetail attendanceModuleDetail = getAttendanceModuleRequestData(request); List moduleDetails = new LinkedList<>(); moduleDetails.add(projectMDMSModuleDetail); moduleDetails.add(projectDepartmentModuleDetail); moduleDetails.add(projectTenantModuleDetail); + moduleDetails.add(attendanceModuleDetail); MdmsCriteria mdmsCriteria = MdmsCriteria.builder().moduleDetails(moduleDetails).tenantId(tenantId) .build(); @@ -123,4 +127,19 @@ private ModuleDetail getTenantModuleRequestData(ProjectRequest request) { return tenantModuleDetail; } -} + private ModuleDetail getAttendanceModuleRequestData(ProjectRequest request) { + List attendanceMasterDetails = new ArrayList<>(); + + MasterDetail attendanceSessionsMasterDetails = MasterDetail.builder().name(MASTER_ATTENDANCE_SESSION) + .filter(filterCode) + .build(); + + attendanceMasterDetails.add(attendanceSessionsMasterDetails); + + ModuleDetail attendanceModuleDetail = ModuleDetail.builder().masterDetails(attendanceMasterDetails) + .moduleName(MDMS_HCM_ATTENDANCE_MODULE_NAME).build(); + + return attendanceModuleDetail; + } + +} \ No newline at end of file diff --git a/health-services/project/src/main/java/org/egov/project/util/ProjectConstants.java b/health-services/project/src/main/java/org/egov/project/util/ProjectConstants.java index 5a431833f41..b314eb59fbf 100644 --- a/health-services/project/src/main/java/org/egov/project/util/ProjectConstants.java +++ b/health-services/project/src/main/java/org/egov/project/util/ProjectConstants.java @@ -7,10 +7,12 @@ public class ProjectConstants { public static final String MASTER_TENANTS = "tenants"; public static final String MDMS_TENANT_MODULE_NAME = "tenant"; public static final String MDMS_COMMON_MASTERS_MODULE_NAME = "common-masters"; + public static final String MDMS_HCM_ATTENDANCE_MODULE_NAME = "HCM-ATTENDANCE"; public static final String MASTER_DEPARTMENT = "Department"; public static final String MASTER_PROJECTTYPE = "ProjectType"; //location public static final String MASTER_NATUREOFWORK = "NatureOfWork"; + public static final String MASTER_ATTENDANCE_SESSION = "AttendanceSessions"; public static final String CODE = "code"; //General public static final String SEMICOLON = ":"; @@ -19,6 +21,8 @@ public class ProjectConstants { public static final String TASK_NOT_ALLOWED = "TASK_NOT_ALLOWED"; public static final String TASK_NOT_ALLOWED_BENEFICIARY_REFUSED_RESOURCE_EMPTY_ERROR_MESSAGE = "Task not allowed as resources can not be provided when " + TaskStatus.BENEFICIARY_REFUSED; public static final String TASK_NOT_ALLOWED_RESOURCE_CANNOT_EMPTY_ERROR_MESSAGE = "Task not allowed as resources can not be empty when "; + public static final String NUMBER_OF_SESSIONS = "numberOfSessions"; + public enum TaskStatus { BENEFICIARY_REFUSED("BENEFICIARY_REFUSED"); private String value; diff --git a/health-services/project/src/main/java/org/egov/project/validator/beneficiary/PbVoucherTagUniqueForUpdateValidator.java b/health-services/project/src/main/java/org/egov/project/validator/beneficiary/PbVoucherTagUniqueForUpdateValidator.java index be699f6b145..8450427492f 100644 --- a/health-services/project/src/main/java/org/egov/project/validator/beneficiary/PbVoucherTagUniqueForUpdateValidator.java +++ b/health-services/project/src/main/java/org/egov/project/validator/beneficiary/PbVoucherTagUniqueForUpdateValidator.java @@ -20,9 +20,9 @@ import static org.egov.common.utils.CommonUtils.notHavingErrors; import static org.egov.common.utils.CommonUtils.populateErrorDetails; -import static org.egov.common.utils.ValidatorUtils.getErrorForUniqueEntity; /** + * @author kanishq-egov * This class, PbVoucherTagUniqueValidator, is a Spring component that serves as a validator for ensuring the uniqueness * of voucher tags within a list of project beneficiaries. It implements the Validator interface, which allows it to * validate a BeneficiaryBulkRequest containing a list of ProjectBeneficiary objects. Any duplicate voucher tags within @@ -110,11 +110,11 @@ private void validateAndPopulateErrors(List validProjectBene populateErrors(invalidEntities, errorDetailsMap); - List existingVoucherTags = existingProjectBeneficiaries.stream().map(ProjectBeneficiary::getTag).collect(Collectors.toList()); + Map existingProjectBeneficiaryVoucherTagMap = existingProjectBeneficiaries.stream().filter(projectBeneficiary -> projectBeneficiary.getTag() != null).collect(Collectors.toMap(ProjectBeneficiary::getTag, projectBeneficiary -> projectBeneficiary)); invalidEntities = validProjectBeneficiaries.stream() .filter(notHavingErrors()) - .filter(projectBeneficiary -> !existingProjectBeneficiaryMap.get(projectBeneficiary.getId()).getTag().equals(projectBeneficiary.getTag())) - .filter(projectBeneficiary -> isInvalid(projectBeneficiary, existingVoucherTags)) + .filter(projectBeneficiary -> isUpdated(projectBeneficiary, existingProjectBeneficiaryMap)) + .filter(projectBeneficiary -> isInvalid(projectBeneficiary, existingProjectBeneficiaryVoucherTagMap)) .collect(Collectors.toList()); populateErrors(invalidEntities, errorDetailsMap); @@ -129,7 +129,7 @@ private void validateAndPopulateErrors(List validProjectBene private void populateErrors(List invalidEntities, Map> errorDetailsMap) { // For each invalid entity, create an error and populate error details invalidEntities.forEach(projectBeneficiary -> { - Error error = getErrorForUniqueEntity(); + Error error = Error.builder().errorMessage("Project Beneficiary Tag Validation Failed").errorCode("INVALID_TAG").type(Error.ErrorType.NON_RECOVERABLE).exception(new CustomException("INVALID_TAG", "Project Beneficiary Tag Validation Failed")).build(); populateErrorDetails(projectBeneficiary, error, errorDetailsMap); }); } @@ -137,16 +137,38 @@ private void populateErrors(List invalidEntities, Map existingVoucherTags) { + private boolean isInvalid(ProjectBeneficiary entity, Map existingProjectBeneficiaryVoucherTagMap) { String id = entity.getId(); String tag = entity.getTag(); // Check if an entity with the same ID exists in the map and has a different tag - return existingVoucherTags.contains(tag); + return existingProjectBeneficiaryVoucherTagMap.keySet().contains(tag) && !existingProjectBeneficiaryVoucherTagMap.get(tag).getId().equals(id); } + /** + * Checks if a ProjectBeneficiary entity is considered as updated based on its tag. + * + * @param entity The ProjectBeneficiary entity to check. + * @param existingProjectBeneficiaryMap A map containing existing ProjectBeneficiary entities based on their IDs. + * @return true if the entity is updated, false otherwise. + */ + private boolean isUpdated(ProjectBeneficiary entity, Map existingProjectBeneficiaryMap) { + String id = entity.getId(); + String tag = entity.getTag(); + + // Retrieve the existing ProjectBeneficiary object to compare + ProjectBeneficiary projectBeneficiaryFromSearch = existingProjectBeneficiaryMap.get(id); + + // check if existing ProjectBeneficiary Tag is null or not and if it is null whether it is updated or not + if(projectBeneficiaryFromSearch.getTag() == null) return tag != null; + + // Check if the tag of the current entity is equal to the tag of the existing entity + return ( !projectBeneficiaryFromSearch.getTag().equals(tag) + || ( tag != null && !tag.equals(projectBeneficiaryFromSearch.getTag()) )); + } } diff --git a/health-services/project/src/main/java/org/egov/project/validator/project/ProjectValidator.java b/health-services/project/src/main/java/org/egov/project/validator/project/ProjectValidator.java index 9082f5a36a8..754fbc26fbe 100644 --- a/health-services/project/src/main/java/org/egov/project/validator/project/ProjectValidator.java +++ b/health-services/project/src/main/java/org/egov/project/validator/project/ProjectValidator.java @@ -1,5 +1,17 @@ package org.egov.project.validator.project; +import java.time.Duration; +import java.time.Instant; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; import com.jayway.jsonpath.JsonPath; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -13,23 +25,17 @@ import org.egov.project.util.MDMSUtils; import org.egov.tracer.model.CustomException; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; - +import static org.egov.project.util.ProjectConstants.MASTER_ATTENDANCE_SESSION; import static org.egov.project.util.ProjectConstants.MASTER_DEPARTMENT; import static org.egov.project.util.ProjectConstants.MASTER_NATUREOFWORK; import static org.egov.project.util.ProjectConstants.MASTER_PROJECTTYPE; import static org.egov.project.util.ProjectConstants.MASTER_TENANTS; import static org.egov.project.util.ProjectConstants.MDMS_COMMON_MASTERS_MODULE_NAME; +import static org.egov.project.util.ProjectConstants.MDMS_HCM_ATTENDANCE_MODULE_NAME; import static org.egov.project.util.ProjectConstants.MDMS_TENANT_MODULE_NAME; @Component @@ -45,6 +51,10 @@ public class ProjectValidator { @Autowired ProjectConfiguration config; + @Autowired + @Qualifier("objectMapper") + ObjectMapper mapper; + /* Validates create Project request body */ public void validateCreateProjectRequest(ProjectRequest request) { Map errorMap = new HashMap<>(); @@ -61,6 +71,7 @@ public void validateCreateProjectRequest(ProjectRequest request) { //Verify MDMS Data // TODO: Uncomment and fix as per HCM once we get clarity // validateRequestMDMSData(request, tenantId, errorMap); + validateAttendanceSessionAgainstMDMS(request,errorMap,tenantId); //Get boundaries in list from all Projects in request body for validation Map> boundariesForValidation = getBoundaryForValidation(request.getProjects()); @@ -183,6 +194,11 @@ private void validateProjectRequest(List projects) { log.error("Start date should be less than end date"); errorMap.put("INVALID_DATE", "Start date should be less than end date"); } + if (project.getStartDate() != null && project.getEndDate() != null && project.getEndDate() != 0 + && project.getEndDate().compareTo(Instant.ofEpochMilli(project.getStartDate()).plus(Duration.ofDays(1)).toEpochMilli()) < 0) { + log.error("Start date and end date difference should at least be 1 day."); + errorMap.put("INVALID_DATE", "Start date and end date difference should at least be 1 day."); + } if (project.getAddress() != null && StringUtils.isNotBlank(project.getAddress().getBoundary()) && StringUtils.isBlank(project.getAddress().getBoundaryType()) ) { log.error("Boundary Type is mandatory if boundary is present in Project request body"); errorMap.put("BOUNDARY", "Boundary Type is mandatory if boundary is present in Project request body"); @@ -303,6 +319,51 @@ private void validateMDMSData(List projects, Object mdmsData, Map errorMap, String tenantId) { + String rootTenantId = tenantId.split("\\.")[0]; + ObjectMapper objectMapper = new ObjectMapper(); + String numberOfSessions = null; + + //Get MDMS data using create project request and tenantId + Object mdmsData = mdmsUtils.mDMSCall(projectRequest, rootTenantId); + final String jsonPathForAttendanceSession = "$.MdmsRes." + MDMS_HCM_ATTENDANCE_MODULE_NAME + "." + MASTER_ATTENDANCE_SESSION + ".*"; + List attendanceRes = null; + try { + attendanceRes = JsonPath.read(mdmsData, jsonPathForAttendanceSession); + } catch (Exception e) { + log.error(e.getMessage()); + throw new CustomException("JSONPATH_ERROR", "Failed to parse mdms response"); + } + + for (Project project : projectRequest.getProjects()) { + JsonNode additionalDetails = null; + try { + Object additionalDetailsObj = project.getAdditionalDetails(); + String additionalDetailsStr = objectMapper.writeValueAsString(additionalDetailsObj); + additionalDetails = objectMapper.readTree(additionalDetailsStr); + + JsonNode numberOfSessionsNode = additionalDetails.get("numberOfSessions"); + if (numberOfSessionsNode != null && numberOfSessionsNode.isTextual()) { + numberOfSessions = numberOfSessionsNode.asText(); + log.info("Number of sessions: " + numberOfSessions); + } else { + log.info("numberOfSessions field not found in project's additonal Details"); + } + + } catch (ClassCastException e) { + log.error("Not able to parse additional details object", e); + } catch (Exception e) { + log.error("An unexpected error occurred while getting AdditionalDetails", e); + } + + // Validate numberOfSessions + if (!StringUtils.isBlank(numberOfSessions) && !attendanceRes.contains(numberOfSessions)) { + log.error("The number of attendance sessions " + numberOfSessions + " is not present in MDMS"); + errorMap.put("INVALID_NUMBER_OF_ATTENDANCE_SESSIONS", "The number of attendance sessions: " + numberOfSessions + " is not present in MDMS"); + } + } + } + /* Validate Project Request MDMS data */ private void validateRequestMDMSData(ProjectRequest request, String tenantId, Map errorMap) { String rootTenantId = tenantId.split("\\.")[0]; @@ -350,7 +411,17 @@ public void validateUpdateAgainstDB(List projectsFromRequest, List p.getId().equals(project.getId())).findFirst().orElse(null); @@ -359,6 +430,8 @@ public void validateUpdateAgainstDB(List projectsFromRequest, List projectsFromRequest, List projects, List parent } log.info("Parent projects validated against DB"); } -} +} \ No newline at end of file diff --git a/health-services/project/src/main/java/org/egov/project/web/models/ProjectStaffSearch.java b/health-services/project/src/main/java/org/egov/project/web/models/ProjectStaffSearch.java index d5440bf84d5..c2279738914 100644 --- a/health-services/project/src/main/java/org/egov/project/web/models/ProjectStaffSearch.java +++ b/health-services/project/src/main/java/org/egov/project/web/models/ProjectStaffSearch.java @@ -37,8 +37,7 @@ public class ProjectStaffSearch { private String tenantId = null; @JsonProperty("staffId") - @Size(min=2,max=64) - private String staffId = null; + private List staffId = null; @JsonProperty("projectId") @Size(min=2,max=64) diff --git a/health-services/project/src/main/resources/application.properties b/health-services/project/src/main/resources/application.properties index 81fc4cd7f12..8364f5f71da 100644 --- a/health-services/project/src/main/resources/application.properties +++ b/health-services/project/src/main/resources/application.properties @@ -163,3 +163,7 @@ project.resource.consumer.bulk.delete.topic=delete-project-resource-bulk-topic project.mdms.module=HCM-PROJECT-TYPES egov.location.hierarchy.type=ADMIN + +#---------Attendance-----------# +project.staff.attendance.topic=project-staff-attendance-health-topic + diff --git a/health-services/project/src/test/java/org/egov/project/service/ProjectStaffServiceSearchTest.java b/health-services/project/src/test/java/org/egov/project/service/ProjectStaffServiceSearchTest.java index 5f8a6461f88..522b79708d3 100644 --- a/health-services/project/src/test/java/org/egov/project/service/ProjectStaffServiceSearchTest.java +++ b/health-services/project/src/test/java/org/egov/project/service/ProjectStaffServiceSearchTest.java @@ -50,7 +50,7 @@ void shouldNotRaiseExceptionIfNoProjectStaffFound() throws Exception { any(Integer.class), any(String.class), eq(null), any(Boolean.class))) .thenReturn(Collections.emptyList()); ProjectStaffSearch projectStaffSearch = ProjectStaffSearch.builder() - .id(Collections.singletonList("ID101")).staffId("some-user-id").build(); + .id(Collections.singletonList("ID101")).staffId(Collections.singletonList("some-user-id")).build(); ProjectStaffSearchRequest projectStaffSearchRequest = ProjectStaffSearchRequest.builder() .projectStaff(projectStaffSearch).requestInfo(RequestInfoTestBuilder.builder() .withCompleteRequestInfo().build()).build(); diff --git a/health-services/referralmanagement/CHANGELOG.md b/health-services/referralmanagement/CHANGELOG.md index b2b3b4325f0..266f4ddf3f5 100644 --- a/health-services/referralmanagement/CHANGELOG.md +++ b/health-services/referralmanagement/CHANGELOG.md @@ -1,10 +1,9 @@ # Changelog All notable changes to this module will be documented in this file. -## 1.0.0 +## 1.0.0 - 2023-11-15 - Added Downsync Feature - ## 1.0.0-beta - Base version - Added functionality for Side-Effects and Refferal management diff --git a/health-services/referralmanagement/pom.xml b/health-services/referralmanagement/pom.xml index 5ef135c8553..bc143e9633b 100644 --- a/health-services/referralmanagement/pom.xml +++ b/health-services/referralmanagement/pom.xml @@ -50,7 +50,7 @@ org.egov.common health-services-models - 1.0.11-SNAPSHOT + 1.0.14-SNAPSHOT compile diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/Constants.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/Constants.java index 7bd29b61cc1..f33a82c8bea 100644 --- a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/Constants.java +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/Constants.java @@ -5,6 +5,8 @@ public interface Constants { String GET_SIDE_EFFECTS = "getSideEffects"; String SET_REFERRALS = "setReferrals"; String GET_REFERRALS = "getReferrals"; + String SET_HF_REFERRALS = "setHfReferrals"; + String GET_HF_REFERRALS = "getHfReferrals"; String VALIDATION_ERROR = "VALIDATION_ERROR"; String PROJECT_TYPES = "projectTypes"; String MDMS_RESPONSE = "MdmsRes"; diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/config/ReferralManagementConfiguration.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/config/ReferralManagementConfiguration.java index e529c27a4f2..1113ac58efb 100644 --- a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/config/ReferralManagementConfiguration.java +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/config/ReferralManagementConfiguration.java @@ -61,9 +61,33 @@ public class ReferralManagementConfiguration { @Value("${referralmanagement.referral.consumer.bulk.delete.topic}") private String deleteReferralBulkTopic; + @Value("${referralmanagement.hfreferral.kafka.create.topic}") + private String createHFReferralTopic; + + @Value("${referralmanagement.hfreferral.kafka.update.topic}") + private String updateHFReferralTopic; + + @Value("${referralmanagement.hfreferral.kafka.delete.topic}") + private String deleteHFReferralTopic; + + @Value("${referralmanagement.hfreferral.consumer.bulk.create.topic}") + private String createHFReferralBulkTopic; + + @Value("${referralmanagement.hfreferral.consumer.bulk.update.topic}") + private String updateHFReferralBulkTopic; + + @Value("${referralmanagement.hfreferral.consumer.bulk.delete.topic}") + private String deleteHFReferralBulkTopic; + @Value("${egov.search.project.staff.url}") private String projectStaffSearchUrl; + @Value("${egov.search.project.facility.url}") + private String projectFacilitySearchUrl; + + @Value("${egov.search.project.url}") + private String projectSearchUrl; + @Value("${egov.facility.host}") private String facilityHost; diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/consumer/HFReferralConsumer.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/consumer/HFReferralConsumer.java new file mode 100644 index 00000000000..d4b4469df52 --- /dev/null +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/consumer/HFReferralConsumer.java @@ -0,0 +1,110 @@ +package org.egov.referralmanagement.consumer; + +import java.util.Map; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.exception.ExceptionUtils; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralBulkRequest; +import org.egov.referralmanagement.service.HFReferralService; +import org.egov.tracer.model.CustomException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.kafka.support.KafkaHeaders; +import org.springframework.messaging.handler.annotation.Header; +import org.springframework.stereotype.Component; + +/** + * Kafka Consumer for handling HFReferral-related messages. + * Author: kanishq-egov + */ +@Component +@Slf4j +public class HFReferralConsumer { + + private final HFReferralService hfReferralService; + private final ObjectMapper objectMapper; + + @Autowired + public HFReferralConsumer(HFReferralService hfReferralService, + @Qualifier("objectMapper") ObjectMapper objectMapper) { + this.hfReferralService = hfReferralService; + this.objectMapper = objectMapper; + } + + /** + * Kafka listener method to handle bulk creation of HFReferrals. + * Author: kanishq-egov + * + * @param consumerRecord The Kafka message payload. + * @param topic The Kafka topic from which the message is received. + */ + @KafkaListener(topics = "${referralmanagement.hfreferral.consumer.bulk.create.topic}") + public void bulkCreate(Map consumerRecord, + @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) { + try { + // Convert the Kafka message payload to HFReferralBulkRequest + HFReferralBulkRequest request = objectMapper.convertValue(consumerRecord, HFReferralBulkRequest.class); + + // Invoke the HFReferralService to handle bulk creation + hfReferralService.create(request, true); + } catch (Exception exception) { + log.error("Error in HFReferral consumer bulk create", exception); + log.error("Exception trace: ", ExceptionUtils.getStackTrace(exception)); + + // Throw a CustomException in case of an error during bulk creation + throw new CustomException("HCM_REFERRAL_MANAGEMENT_REFERRAL_CREATE", exception.getMessage()); + } + } + + /** + * Kafka listener method to handle bulk update of HFReferrals. + * Author: kanishq-egov + * + * @param consumerRecord The Kafka message payload. + * @param topic The Kafka topic from which the message is received. + */ + @KafkaListener(topics = "${referralmanagement.hfreferral.consumer.bulk.update.topic}") + public void bulkUpdate(Map consumerRecord, + @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) { + try { + // Convert the Kafka message payload to HFReferralBulkRequest + HFReferralBulkRequest request = objectMapper.convertValue(consumerRecord, HFReferralBulkRequest.class); + + // Invoke the HFReferralService to handle bulk update + hfReferralService.update(request, true); + } catch (Exception exception) { + log.error("Error in HFReferral consumer bulk update", exception); + log.error("Exception trace: ", ExceptionUtils.getStackTrace(exception)); + + // Throw a CustomException in case of an error during bulk update + throw new CustomException("HCM_REFERRAL_MANAGEMENT_REFERRAL_UPDATE", exception.getMessage()); + } + } + + /** + * Kafka listener method to handle bulk deletion of HFReferrals. + * Author: kanishq-egov + * + * @param consumerRecord The Kafka message payload. + * @param topic The Kafka topic from which the message is received. + */ + @KafkaListener(topics = "${referralmanagement.hfreferral.consumer.bulk.delete.topic}") + public void bulkDelete(Map consumerRecord, + @Header(KafkaHeaders.RECEIVED_TOPIC) String topic) { + try { + // Convert the Kafka message payload to HFReferralBulkRequest + HFReferralBulkRequest request = objectMapper.convertValue(consumerRecord, HFReferralBulkRequest.class); + + // Invoke the HFReferralService to handle bulk deletion + hfReferralService.delete(request, true); + } catch (Exception exception) { + log.error("Error in HFReferral consumer bulk delete", exception); + log.error("Exception trace: ", ExceptionUtils.getStackTrace(exception)); + + // Throw a CustomException in case of an error during bulk deletion + throw new CustomException("HCM_REFERRAL_MANAGEMENT_REFERRAL_DELETE", exception.getMessage()); + } + } +} diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/repository/HFReferralRepository.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/repository/HFReferralRepository.java new file mode 100644 index 00000000000..f3b05004718 --- /dev/null +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/repository/HFReferralRepository.java @@ -0,0 +1,151 @@ +package org.egov.referralmanagement.repository; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import lombok.extern.slf4j.Slf4j; +import org.egov.common.data.query.builder.GenericQueryBuilder; +import org.egov.common.data.query.builder.QueryFieldChecker; +import org.egov.common.data.query.builder.SelectQueryBuilder; +import org.egov.common.data.repository.GenericRepository; +import org.egov.common.models.referralmanagement.hfreferral.HFReferral; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralSearch; +import org.egov.common.producer.Producer; +import org.egov.referralmanagement.repository.rowmapper.HFReferralRowMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; +import org.springframework.util.ReflectionUtils; + +import static org.egov.common.utils.CommonUtils.getIdMethod; + +/** + * Repository class for managing the persistence and retrieval of HFReferral entities. + * This class extends GenericRepository for common CRUD operations. + * + * @author kanishq-egov + */ +@Repository +@Slf4j +public class HFReferralRepository extends GenericRepository { + + @Autowired + private HFReferralRowMapper rowMapper; + + /** + * Constructor for HFReferralRepository. + * + * @param producer The producer for publishing messages. + * @param namedParameterJdbcTemplate JDBC template for named parameters. + * @param redisTemplate Template for Redis operations. + * @param selectQueryBuilder Builder for creating SELECT queries. + * @param rowMapper Mapper for converting rows to HFReferral objects. + */ + @Autowired + protected HFReferralRepository(Producer producer, NamedParameterJdbcTemplate namedParameterJdbcTemplate, + RedisTemplate redisTemplate, SelectQueryBuilder selectQueryBuilder, + HFReferralRowMapper rowMapper) { + // Call the constructor of the GenericRepository with necessary parameters. + super(producer, namedParameterJdbcTemplate, redisTemplate, selectQueryBuilder, rowMapper, Optional.of("hf_referral")); + } + + /** + * Retrieves a list of HFReferrals based on the provided search criteria. + * + * @param searchObject The search criteria for filtering HFReferrals. + * @param limit The maximum number of records to retrieve. + * @param offset The offset for pagination. + * @param tenantId The tenant ID for filtering. + * @param lastChangedSince Timestamp for filtering records changed since this time. + * @param includeDeleted Flag indicating whether to include deleted records. + * @return A list of HFReferral entities matching the search criteria. + */ + public List find(HFReferralSearch searchObject, Integer limit, Integer offset, String tenantId, + Long lastChangedSince, Boolean includeDeleted) { + // Initial query to select HFReferral fields from the table. + String query = "SELECT hf.id, hf.clientreferenceid, hf.tenantid, hf.projectid, hf.projectfacilityid, hf.symptom, hf.symptomsurveyid, hf.beneficiaryid, hf.referralcode, hf.nationallevelid, hf.createdby, hf.createdtime, hf.lastmodifiedby, hf.lastmodifiedtime, hf.clientcreatedby, hf.clientcreatedtime, hf.clientlastmodifiedby, hf.clientlastmodifiedtime, hf.rowversion, hf.isdeleted, hf.additionaldetails from hf_referral hf"; + Map paramsMap = new HashMap<>(); + + // Generate WHERE conditions based on non-null fields in the search object. + List whereFields = GenericQueryBuilder.getFieldsWithCondition(searchObject, + QueryFieldChecker.isNotNull, paramsMap); + + // Apply the WHERE conditions to the query. + query = GenericQueryBuilder.generateQuery(query, whereFields).toString(); + query = query.replace("id IN (:id)", "hf.id IN (:id)"); + query = query.replace("clientReferenceId IN (:clientReferenceId)", "hf.clientReferenceId IN (:clientReferenceId)"); + + // Add additional conditions based on tenant ID, includeDeleted, and lastChangedSince. + query = query + " and hf.tenantId=:tenantId "; + if (Boolean.FALSE.equals(includeDeleted)) { + query = query + "and hf.isDeleted=:isDeleted "; + } + + if (lastChangedSince != null) { + query = query + "and hf.lastModifiedTime>=:lastModifiedTime "; + } + + // Add ORDER BY, LIMIT, and OFFSET clauses to the query. + query = query + "ORDER BY hf.id ASC LIMIT :limit OFFSET :offset"; + paramsMap.put("tenantId", tenantId); + paramsMap.put("isDeleted", includeDeleted); + paramsMap.put("lastModifiedTime", lastChangedSince); + paramsMap.put("limit", limit); + paramsMap.put("offset", offset); + + // Execute the query and retrieve the list of HFReferral entities. + List hfReferralList = this.namedParameterJdbcTemplate.query(query, paramsMap, this.rowMapper); + return hfReferralList; + } + + /** + * Retrieves a list of HFReferrals based on a list of IDs. + * + * @param ids The list of IDs to search for. + * @param includeDeleted Flag indicating whether to include deleted records. + * @param columnName The column name to search for IDs. + * @return A list of HFReferral entities matching the provided IDs. + */ + public List findById(List ids, Boolean includeDeleted, String columnName) { + // Find objects in the cache based on the provided IDs. + List objFound = findInCache(ids).stream() + .filter(entity -> entity.getIsDeleted().equals(includeDeleted)) + .collect(Collectors.toList()); + + // If objects are found in the cache, check if there are any IDs remaining to be retrieved. + if (!objFound.isEmpty()) { + Method idMethod = getIdMethod(objFound, columnName); + ids.removeAll(objFound.stream() + .map(obj -> (String) ReflectionUtils.invokeMethod(idMethod, obj)) + .collect(Collectors.toList())); + + // If no IDs are remaining, return the objects found in the cache. + if (ids.isEmpty()) { + return objFound; + } + } + + // Generate a SELECT query based on the provided IDs and column name. + String query = String.format("SELECT hf.id, hf.clientreferenceid, hf.tenantid, hf.projectid, hf.projectfacilityid, hf.symptom, hf.symptomsurveyid, hf.beneficiaryid, hf.referralcode, hf.nationallevelid, hf.createdby, hf.createdtime, hf.lastmodifiedby, hf.lastmodifiedtime, hf.clientcreatedby, hf.clientcreatedtime, hf.clientlastmodifiedby, hf.clientlastmodifiedtime, hf.rowversion, hf.isdeleted, hf.additionaldetails from hf_referral hf WHERE hf.%s IN (:ids) ", columnName); + + // Add conditions to exclude deleted records if includeDeleted is false. + if (includeDeleted == null || !includeDeleted) { + query += " AND hf.isDeleted = false "; + } + + // Create parameter map for the query and execute it to retrieve HFReferral entities. + Map paramMap = new HashMap<>(); + paramMap.put("ids", ids); + List hfReferralList = this.namedParameterJdbcTemplate.query(query, paramMap, this.rowMapper); + + // Add the retrieved entities to the cache. + objFound.addAll(hfReferralList); + putInCache(objFound); + return objFound; + } +} diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/repository/rowmapper/HFReferralRowMapper.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/repository/rowmapper/HFReferralRowMapper.java new file mode 100644 index 00000000000..3f9b5084872 --- /dev/null +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/repository/rowmapper/HFReferralRowMapper.java @@ -0,0 +1,78 @@ +package org.egov.referralmanagement.repository.rowmapper; + +import java.sql.ResultSet; +import java.sql.SQLException; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import digit.models.coremodels.AuditDetails; +import org.egov.common.models.project.AdditionalFields; +import org.egov.common.models.referralmanagement.hfreferral.HFReferral; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Component; + +/** + * RowMapper implementation for mapping ResultSet rows to HFReferral objects. + * This class is responsible for converting database query results into Java objects. + * + * @author kanishq-egov + */ +@Component +public class HFReferralRowMapper implements RowMapper { + + @Autowired + ObjectMapper objectMapper; + + /** + * Maps a ResultSet row to an HFReferral object. + * + * @param resultSet The result set containing the queried data. + * @param i The current row number. + * @return An HFReferral object mapped from the ResultSet row. + * @throws SQLException If there's an issue accessing ResultSet data. + */ + @Override + public HFReferral mapRow(ResultSet resultSet, int i) throws SQLException { + try { + // Create AuditDetails object from the ResultSet data. + AuditDetails auditDetails = AuditDetails.builder() + .createdBy(resultSet.getString("createdBy")) + .createdTime(resultSet.getLong("createdTime")) + .lastModifiedBy(resultSet.getString("lastModifiedBy")) + .lastModifiedTime(resultSet.getLong("lastModifiedTime")) + .build(); + + // Create clientAuditDetails object from the ResultSet data. + AuditDetails clientAuditDetails = AuditDetails.builder() + .createdBy(resultSet.getString("clientCreatedBy")) + .createdTime(resultSet.getLong("clientCreatedTime")) + .lastModifiedBy(resultSet.getString("clientLastModifiedBy")) + .lastModifiedTime(resultSet.getLong("clientLastModifiedTime")) + .build(); + + // Build and return HFReferral object using ResultSet data and ObjectMapper for additionalFields. + return HFReferral.builder() + .id(resultSet.getString("id")) + .clientReferenceId(resultSet.getString("clientreferenceid")) + .tenantId(resultSet.getString("tenantid")) + .projectId(resultSet.getString("projectid")) + .projectFacilityId(resultSet.getString("projectfacilityid")) + .symptom(resultSet.getString("symptom")) + .symptomSurveyId(resultSet.getString("symptomsurveyid")) + .beneficiaryId(resultSet.getString("beneficiaryid")) + .referralCode(resultSet.getString("referralcode")) + .nationalLevelId(resultSet.getString("nationallevelid")) + .additionalFields(resultSet.getString("additionalDetails") == null ? null : objectMapper + .readValue(resultSet.getString("additionalDetails"), AdditionalFields.class)) + .rowVersion(resultSet.getInt("rowversion")) + .isDeleted(resultSet.getBoolean("isdeleted")) + .auditDetails(auditDetails) + .clientAuditDetails(clientAuditDetails) + .build(); + } catch (JsonProcessingException e) { + // Wrap JsonProcessingException as a RuntimeException for simplicity. + throw new RuntimeException(e); + } + } +} diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/service/DownsyncService.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/service/DownsyncService.java index 4cb8d8be52b..23c5e2328a9 100644 --- a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/service/DownsyncService.java +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/service/DownsyncService.java @@ -137,7 +137,7 @@ private List searchHouseholds(DownsyncRequest downsyncRequest, Downsync StringBuilder householdUrl = new StringBuilder(configs.getHouseholdHost()) .append(configs.getHouseholdSearchUrl()); - householdUrl = appendUrlParams(householdUrl, criteria); + householdUrl = appendUrlParams(householdUrl, criteria, null, null); HouseholdSearch householdSearch = HouseholdSearch.builder() .localityCode(criteria.getLocality()) @@ -174,7 +174,7 @@ private List searchIndividuals(DownsyncRequest downsyncRequest, Downsync StringBuilder url = new StringBuilder(configs.getIndividualHost()) .append(configs.getIndividualSearchUrl()); - url = appendUrlParams(url, criteria); + url = appendUrlParams(url, criteria, 0, individualIds.size()); IndividualSearch individualSearch = IndividualSearch.builder() .id(new ArrayList<>(individualIds)) @@ -203,13 +203,12 @@ private Set searchMembers(DownsyncRequest downsyncRequest, Downsync down StringBuilder memberUrl = new StringBuilder(configs.getHouseholdHost()) .append(configs.getHouseholdMemberSearchUrl()); - appendUrlParams(memberUrl, downsyncRequest.getDownsyncCriteria()); - String memberIdsquery = "SELECT id from HOUSEHOLD_MEMBER where householdId IN (:householdIds)"; Map paramMap = new HashMap<>(); paramMap.put("householdIds", householdIds); - + appendUrlParams(memberUrl, downsyncRequest.getDownsyncCriteria(), 0, householdIds.size()); + /* FIXME SHOULD BE REMOVED AND SEARCH SHOULD BE enhanced with list of household ids*/ List memberids = jdbcTemplate.queryForList(memberIdsquery, paramMap, String.class); @@ -247,7 +246,7 @@ private List searchBeneficiaries(DownsyncRequest downsyncRequest, Downsy StringBuilder url = new StringBuilder(configs.getProjectHost()) .append(configs.getProjectBeneficiarySearchUrl()); - url = appendUrlParams(url, criteria); + url = appendUrlParams(url, criteria, 0, individualClientRefIds.size()); String beneficiaryIdQuery = "SELECT id from PROJECT_BENEFICIARY where beneficiaryclientreferenceid IN (:beneficiaryIds)"; @@ -291,7 +290,6 @@ private List searchTasks(DownsyncRequest downsyncRequest, Downsync downs StringBuilder url = new StringBuilder(configs.getProjectHost()) .append(configs.getProjectTaskSearchUrl()); - url = appendUrlParams(url, criteria); String taskIdQuery = "SELECT id from PROJECT_TASK where projectBeneficiaryClientReferenceId IN (:beneficiaryClientRefIds)"; @@ -300,7 +298,8 @@ private List searchTasks(DownsyncRequest downsyncRequest, Downsync downs /* FIXME SHOULD BE REMOVED AND TASK SEARCH SHOULD BE enhanced with list of client-ref-beneficiary ids*/ List taskIds = jdbcTemplate.queryForList(taskIdQuery, paramMap, String.class); - + url = appendUrlParams(url, criteria, 0, taskIds.size()); + if(CollectionUtils.isEmpty(taskIds)) return Collections.emptyList(); @@ -333,13 +332,13 @@ private void searchSideEffect(DownsyncRequest downsyncRequest, Downsync downsync RequestInfo requestInfo = downsyncRequest.getRequestInfo(); // search side effect FIXME - tasks id array search not available - String taskIdQuery = "SELECT id from SIDE_EFFECT where taskClientReferenceId IN (:taskClientRefIds)"; + String sEIdQuery = "SELECT id from SIDE_EFFECT where taskClientReferenceId IN (:taskClientRefIds)"; Map paramMap = new HashMap<>(); paramMap.put("taskClientRefIds", taskClientRefIds); /* FIXME SHOULD BE REMOVED AND TASK SEARCH SHOULD BE enhanced with list of client-ref-beneficiary ids*/ - List SEIds = jdbcTemplate.queryForList(taskIdQuery, paramMap, String.class); + List SEIds = jdbcTemplate.queryForList(sEIdQuery, paramMap, String.class); if(CollectionUtils.isEmpty(SEIds)) return; @@ -354,8 +353,8 @@ private void searchSideEffect(DownsyncRequest downsyncRequest, Downsync downsync List effects = sideEffectService.search( effectSearchRequest, - criteria.getLimit(), - criteria.getOffset(), + SEIds.size(), + 0, criteria.getTenantId(), criteria.getLastSyncedTime(), criteria.getIncludeDeleted()); @@ -380,8 +379,8 @@ private void referralSearch(DownsyncRequest downsyncRequest, Downsync downsync, List referrals = referralService.search( searchRequest, - criteria.getLimit(), - criteria.getOffset(), + beneficiaryClientRefIds.size(), + 0, criteria.getTenantId(), criteria.getLastSyncedTime(), criteria.getIncludeDeleted()); @@ -391,22 +390,34 @@ private void referralSearch(DownsyncRequest downsyncRequest, Downsync downsync, - /** - * append url params - * - * @param url - * @param criteria - * @return - */ - private StringBuilder appendUrlParams(StringBuilder url, DownsyncCriteria criteria) { - - return url.append("?tenantId=") - .append(criteria.getTenantId()) - .append("&offset=") - .append(criteria.getOffset()) - .append("&limit=") - .append(criteria.getLimit()) - .append("&includeDeleted=") - .append(criteria.getIncludeDeleted()); - } + /** + * append url params + * + * @param url + * @param criteria + * @param includeLimitOffset + * @return + */ + private StringBuilder appendUrlParams(StringBuilder url, DownsyncCriteria criteria, Integer offset, Integer limit) { + + url.append("?tenantId=") + .append(criteria.getTenantId()) + .append("&includeDeleted=") + .append(criteria.getIncludeDeleted()) + .append("&limit="); + + if (null != limit) + url.append(limit); + else + url.append(criteria.getLimit()); + + url.append("&offset="); + + if(null != offset) + url.append(offset); + else + url.append(criteria.getOffset()); + + return url; } +} diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/service/HFReferralService.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/service/HFReferralService.java new file mode 100644 index 00000000000..aaf317acafc --- /dev/null +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/service/HFReferralService.java @@ -0,0 +1,263 @@ +package org.egov.referralmanagement.service; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import lombok.extern.slf4j.Slf4j; +import org.egov.common.ds.Tuple; +import org.egov.common.models.ErrorDetails; +import org.egov.common.models.referralmanagement.hfreferral.HFReferral; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralBulkRequest; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralRequest; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralSearchRequest; +import org.egov.common.service.IdGenService; +import org.egov.common.utils.CommonUtils; +import org.egov.common.validator.Validator; +import org.egov.referralmanagement.Constants; +import org.egov.referralmanagement.config.ReferralManagementConfiguration; +import org.egov.referralmanagement.repository.HFReferralRepository; +import org.egov.referralmanagement.service.enrichment.HFReferralEnrichmentService; +import org.egov.referralmanagement.validator.hfreferral.HfrIsDeletedValidator; +import org.egov.referralmanagement.validator.hfreferral.HfrNonExistentEntityValidator; +import org.egov.referralmanagement.validator.hfreferral.HfrNullIdValidator; +import org.egov.referralmanagement.validator.hfreferral.HfrProjectFacilityIdValidator; +import org.egov.referralmanagement.validator.hfreferral.HfrProjectIdValidator; +import org.egov.referralmanagement.validator.hfreferral.HfrRowVersionValidator; +import org.egov.referralmanagement.validator.hfreferral.HfrUniqueEntityValidator; +import org.egov.tracer.model.CustomException; +import org.springframework.stereotype.Service; +import org.springframework.util.ReflectionUtils; + +import static org.egov.common.utils.CommonUtils.getIdFieldName; +import static org.egov.common.utils.CommonUtils.getIdMethod; +import static org.egov.common.utils.CommonUtils.handleErrors; +import static org.egov.common.utils.CommonUtils.havingTenantId; +import static org.egov.common.utils.CommonUtils.includeDeleted; +import static org.egov.common.utils.CommonUtils.isSearchByIdOnly; +import static org.egov.common.utils.CommonUtils.lastChangedSince; +import static org.egov.common.utils.CommonUtils.notHavingErrors; +import static org.egov.common.utils.CommonUtils.populateErrorDetails; + +/** + * Service class for handling operations related to HFReferral entities. + * Manages creation, updating, searching, and deletion of HFReferrals. + * Includes validation and enrichment of HFReferrals before interacting with the repository. + * Author: kanishq-egov + */ +@Service +@Slf4j +public class HFReferralService { + + private final IdGenService idGenService; + private final HFReferralRepository hfReferralRepository; + private final ReferralManagementConfiguration referralManagementConfiguration; + private final HFReferralEnrichmentService hfReferralEnrichmentService; + private final List> validators; + + // Predicates to determine which validators are applicable for create, update, and delete operations + private final Predicate> isApplicableForCreate = validator -> + validator.getClass().equals(HfrProjectIdValidator.class) + || validator.getClass().equals(HfrProjectFacilityIdValidator.class); + + private final Predicate> isApplicableForUpdate = validator -> + validator.getClass().equals(HfrProjectIdValidator.class) + || validator.getClass().equals(HfrProjectFacilityIdValidator.class) + || validator.getClass().equals(HfrNullIdValidator.class) + || validator.getClass().equals(HfrIsDeletedValidator.class) + || validator.getClass().equals(HfrUniqueEntityValidator.class) + || validator.getClass().equals(HfrNonExistentEntityValidator.class) + || validator.getClass().equals(HfrRowVersionValidator.class); + + private final Predicate> isApplicableForDelete = validator -> + validator.getClass().equals(HfrNullIdValidator.class) + || validator.getClass().equals(HfrNonExistentEntityValidator.class) + || validator.getClass().equals(HfrRowVersionValidator.class); + + /** + * Constructor to initialize the service with required dependencies. + * + * @param idGenService The IdGenService for generating IDs. + * @param hfReferralRepository The repository for HFReferral entities. + * @param referralManagementConfiguration The configuration for referral management. + * @param hfReferralEnrichmentService The service for enriching HFReferral entities. + * @param validators The list of validators for HFReferral entities. + */ + public HFReferralService(IdGenService idGenService, HFReferralRepository hfReferralRepository, + ReferralManagementConfiguration referralManagementConfiguration, + HFReferralEnrichmentService hfReferralEnrichmentService, + List> validators) { + this.idGenService = idGenService; + this.hfReferralRepository = hfReferralRepository; + this.referralManagementConfiguration = referralManagementConfiguration; + this.hfReferralEnrichmentService = hfReferralEnrichmentService; + this.validators = validators; + } + + // Method to create a single HFReferral + public HFReferral create(HFReferralRequest request) { + log.info("Received request to create a referral"); + HFReferralBulkRequest bulkRequest = HFReferralBulkRequest.builder().requestInfo(request.getRequestInfo()) + .hfReferrals(Collections.singletonList(request.getHfReferral())).build(); + log.info("Creating bulk request"); + return create(bulkRequest, false).get(0); + } + + // Method to create multiple HFReferrals in bulk + public List create(HFReferralBulkRequest hfReferralRequest, boolean isBulk) { + log.info("Received request to create bulk referrals"); + Tuple, Map> tuple = validate(validators, + isApplicableForCreate, hfReferralRequest, isBulk); + Map errorDetailsMap = tuple.getY(); + List validReferrals = tuple.getX(); + + try { + if (!validReferrals.isEmpty()) { + log.info("Processing {} valid entities", validReferrals.size()); + hfReferralEnrichmentService.create(validReferrals, hfReferralRequest); + hfReferralRepository.save(validReferrals, + referralManagementConfiguration.getCreateHFReferralTopic()); + log.info("Successfully created referrals"); + } + } catch (Exception exception) { + log.error("Error occurred while creating referrals: {}", exception.getMessage()); + populateErrorDetails(hfReferralRequest, errorDetailsMap, validReferrals, + exception, Constants.SET_HF_REFERRALS); + } + handleErrors(errorDetailsMap, isBulk, Constants.VALIDATION_ERROR); + + return validReferrals; + } + + // Method to update a single HFReferral + public HFReferral update(HFReferralRequest request) { + log.info("Received request to update a referral"); + HFReferralBulkRequest bulkRequest = HFReferralBulkRequest.builder().requestInfo(request.getRequestInfo()) + .hfReferrals(Collections.singletonList(request.getHfReferral())).build(); + log.info("Creating bulk request"); + return update(bulkRequest, false).get(0); + } + + // Method to update multiple HFReferrals in bulk + public List update(HFReferralBulkRequest hfReferralRequest, boolean isBulk) { + log.info("Received request to update bulk referrals"); + Tuple, Map> tuple = validate(validators, + isApplicableForUpdate, hfReferralRequest, isBulk); + Map errorDetailsMap = tuple.getY(); + List validReferrals = tuple.getX(); + + try { + if (!validReferrals.isEmpty()) { + log.info("Processing {} valid entities", validReferrals.size()); + hfReferralEnrichmentService.update(validReferrals, hfReferralRequest); + hfReferralRepository.save(validReferrals, + referralManagementConfiguration.getUpdateHFReferralTopic()); + log.info("Successfully updated bulk referrals"); + } + } catch (Exception exception) { + log.error("Error occurred while updating referrals", exception); + populateErrorDetails(hfReferralRequest, errorDetailsMap, validReferrals, + exception, Constants.SET_HF_REFERRALS); + } + handleErrors(errorDetailsMap, isBulk, Constants.VALIDATION_ERROR); + + return validReferrals; + } + + // Method to search for HFReferrals based on certain criteria + public List search(HFReferralSearchRequest referralSearchRequest, + Integer limit, + Integer offset, + String tenantId, + Long lastChangedSince, + Boolean includeDeleted) { + log.info("Received request to search referrals"); + String idFieldName = getIdFieldName(referralSearchRequest.getHfReferral()); + + // If searching by ID only, fetch referrals with specified IDs + if (isSearchByIdOnly(referralSearchRequest.getHfReferral(), idFieldName)) { + log.info("Searching referrals by ID"); + List ids = (List) ReflectionUtils.invokeMethod(getIdMethod(Collections + .singletonList(referralSearchRequest.getHfReferral())), + referralSearchRequest.getHfReferral()); + log.info("Fetching referrals with IDs: {}", ids); + + return hfReferralRepository.findById(ids, includeDeleted, idFieldName).stream() + .filter(lastChangedSince(lastChangedSince)) + .filter(havingTenantId(tenantId)) + .filter(includeDeleted(includeDeleted)) + .collect(Collectors.toList()); + } + + log.info("Searching referrals using criteria"); + return hfReferralRepository.find(referralSearchRequest.getHfReferral(), + limit, offset, tenantId, lastChangedSince, includeDeleted); + } + + // Method to delete a single HFReferral + public HFReferral delete(HFReferralRequest hfReferralRequest) { + log.info("Received request to delete a referral"); + HFReferralBulkRequest bulkRequest = HFReferralBulkRequest.builder().requestInfo(hfReferralRequest.getRequestInfo()) + .hfReferrals(Collections.singletonList(hfReferralRequest.getHfReferral())).build(); + log.info("Creating bulk request"); + return delete(bulkRequest, false).get(0); + } + + // Method to delete multiple HFReferrals in bulk + public List delete(HFReferralBulkRequest hfReferralRequest, boolean isBulk) { + Tuple, Map> tuple = validate(validators, + isApplicableForDelete, hfReferralRequest, isBulk); + Map errorDetailsMap = tuple.getY(); + List validReferrals = tuple.getX(); + + try { + if (!validReferrals.isEmpty()) { + log.info("Processing {} valid entities", validReferrals.size()); + List referralIds = validReferrals.stream().map(entity -> entity.getId()).collect(Collectors.toSet()).stream().collect(Collectors.toList()); + List existingReferrals = hfReferralRepository + .findById(referralIds, false); + hfReferralEnrichmentService.delete(existingReferrals, hfReferralRequest); + hfReferralRepository.save(existingReferrals, + referralManagementConfiguration.getDeleteHFReferralTopic()); + log.info("Successfully deleted entities"); + } + } catch (Exception exception) { + log.error("Error occurred while deleting entities: {}", exception); + populateErrorDetails(hfReferralRequest, errorDetailsMap, validReferrals, + exception, Constants.SET_HF_REFERRALS); + } + handleErrors(errorDetailsMap, isBulk, Constants.VALIDATION_ERROR); + + return validReferrals; + } + + // Method to put HFReferrals in cache + public void putInCache(List hfReferrals) { + log.info("Putting {} HFReferrals in cache", hfReferrals.size()); + hfReferralRepository.putInCache(hfReferrals); + log.info("Successfully put HFReferrals in cache"); + } + + // Method to validate HFReferralBulkRequest + private Tuple, Map> validate( + List> validators, + Predicate> isApplicable, + HFReferralBulkRequest request, + boolean isBulk + ) { + log.info("Validating request"); + Map errorDetailsMap = CommonUtils.validate(validators, + isApplicable, request, + Constants.SET_HF_REFERRALS); + if (!errorDetailsMap.isEmpty() && !isBulk) { + log.error("Validation error occurred. Error details: {}", errorDetailsMap.values()); + throw new CustomException(Constants.VALIDATION_ERROR, errorDetailsMap.values().toString()); + } + List validReferrals = request.getHfReferrals().stream() + .filter(notHavingErrors()).collect(Collectors.toList()); + log.info("Validation successful, found valid referrals"); + return new Tuple<>(validReferrals, errorDetailsMap); + } +} diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/service/enrichment/HFReferralEnrichmentService.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/service/enrichment/HFReferralEnrichmentService.java new file mode 100644 index 00000000000..158b17c126d --- /dev/null +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/service/enrichment/HFReferralEnrichmentService.java @@ -0,0 +1,57 @@ +package org.egov.referralmanagement.service.enrichment; + +import java.util.List; +import java.util.Map; + +import lombok.extern.slf4j.Slf4j; +import org.egov.common.models.referralmanagement.hfreferral.HFReferral; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralBulkRequest; +import org.egov.common.utils.CommonUtils; +import org.springframework.stereotype.Component; + +import static org.egov.common.utils.CommonUtils.enrichForCreate; +import static org.egov.common.utils.CommonUtils.enrichForDelete; +import static org.egov.common.utils.CommonUtils.enrichForUpdate; +import static org.egov.common.utils.CommonUtils.getIdToObjMap; + +@Component +@Slf4j +public class HFReferralEnrichmentService { + + /** + * + * @param entities + * @param request + */ + public void create(List entities, HFReferralBulkRequest request) { + log.info("starting the enrichment for create hfReferrals"); + log.info("generating IDs using UUID"); + List idList = CommonUtils.uuidSupplier().apply(entities.size()); + log.info("enriching referrals with generated IDs"); + enrichForCreate(entities, idList, request.getRequestInfo()); + log.info("enrichment done"); + } + + /** + * + * @param entities + * @param request + */ + public void update(List entities, HFReferralBulkRequest request) { + log.info("starting the enrichment for create hfReferrals"); + Map referralMap = getIdToObjMap(entities); + enrichForUpdate(referralMap, entities, request); + log.info("enrichment done"); + } + + /** + * + * @param entities + * @param request + */ + public void delete(List entities, HFReferralBulkRequest request) { + log.info("starting the enrichment for delete hfReferrals"); + enrichForDelete(entities, request.getRequestInfo(), true); + log.info("enrichment done"); + } +} diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrIsDeletedValidator.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrIsDeletedValidator.java new file mode 100644 index 00000000000..92a2fcfdd53 --- /dev/null +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrIsDeletedValidator.java @@ -0,0 +1,45 @@ +package org.egov.referralmanagement.validator.hfreferral; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import lombok.extern.slf4j.Slf4j; +import org.egov.common.models.Error; +import org.egov.common.models.referralmanagement.hfreferral.HFReferral; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralBulkRequest; +import org.egov.common.validator.Validator; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import static org.egov.common.utils.CommonUtils.populateErrorDetails; +import static org.egov.common.utils.ValidatorUtils.getErrorForIsDelete; + +/** + * Validator for checking the 'isDeleted' field in HFReferral entities. + * + * Author: kanishq-egov + */ +@Component +@Order(2) +@Slf4j +public class HfrIsDeletedValidator implements Validator { + + /** + * Validates the 'isDeleted' field for each HFReferral entity in the bulk request. + * + * @param request The HFReferralBulkRequest containing a list of HFReferral entities + * @return A Map containing HFReferral entities as keys and lists of errors as values + */ + @Override + public Map> validate(HFReferralBulkRequest request) { + log.info("validating isDeleted field"); + HashMap> errorDetailsMap = new HashMap<>(); + List validEntities = request.getHfReferrals(); + validEntities.stream().filter(HFReferral::getIsDeleted).forEach(hfReferral -> { + Error error = getErrorForIsDelete(); + populateErrorDetails(hfReferral, error, errorDetailsMap); + }); + return errorDetailsMap; + } +} diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrNonExistentEntityValidator.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrNonExistentEntityValidator.java new file mode 100644 index 00000000000..515d37624a4 --- /dev/null +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrNonExistentEntityValidator.java @@ -0,0 +1,80 @@ +package org.egov.referralmanagement.validator.hfreferral; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.egov.common.models.Error; +import org.egov.common.models.referralmanagement.hfreferral.HFReferral; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralBulkRequest; +import org.egov.common.validator.Validator; +import org.egov.referralmanagement.repository.HFReferralRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import static org.egov.common.utils.CommonUtils.checkNonExistentEntities; +import static org.egov.common.utils.CommonUtils.getIdFieldName; +import static org.egov.common.utils.CommonUtils.getIdToObjMap; +import static org.egov.common.utils.CommonUtils.getMethod; +import static org.egov.common.utils.CommonUtils.getObjClass; +import static org.egov.common.utils.CommonUtils.notHavingErrors; +import static org.egov.common.utils.CommonUtils.populateErrorDetails; +import static org.egov.common.utils.ValidatorUtils.getErrorForNonExistentEntity; +import static org.egov.referralmanagement.Constants.GET_ID; + +/** + * Validator for checking the existence of entities referred in HFReferral entities. + * + * Author: kanishq-egov + */ +@Component +@Order(value = 4) +@Slf4j +public class HfrNonExistentEntityValidator implements Validator { + + private final HFReferralRepository hfReferralRepository; + + private final ObjectMapper objectMapper; + + @Autowired + public HfrNonExistentEntityValidator(HFReferralRepository hfReferralRepository, ObjectMapper objectMapper) { + this.hfReferralRepository = hfReferralRepository; + this.objectMapper = objectMapper; + } + + /** + * Validates the existence of entities referred in HFReferral entities. + * + * @param request The HFReferralBulkRequest containing a list of HFReferral entities + * @return A Map containing HFReferral entities as keys and lists of errors as values + */ + @Override + public Map> validate(HFReferralBulkRequest request) { + log.info("validating for existence of entity"); + Map> errorDetailsMap = new HashMap<>(); + List hfReferrals = request.getHfReferrals(); + Class objClass = getObjClass(hfReferrals); + Method idMethod = getMethod(GET_ID, objClass); + Map iMap = getIdToObjMap(hfReferrals + .stream().filter(notHavingErrors()).collect(Collectors.toList()), idMethod); + if (!iMap.isEmpty()) { + List referralIds = new ArrayList<>(iMap.keySet()); + List existingReferrals = hfReferralRepository + .findById(referralIds, false, getIdFieldName(idMethod)); + List nonExistentReferrals = checkNonExistentEntities(iMap, + existingReferrals, idMethod); + nonExistentReferrals.forEach(sideEffect -> { + Error error = getErrorForNonExistentEntity(); + populateErrorDetails(sideEffect, error, errorDetailsMap); + }); + } + + return errorDetailsMap; + } +} diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrNullIdValidator.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrNullIdValidator.java new file mode 100644 index 00000000000..26defef4fa4 --- /dev/null +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrNullIdValidator.java @@ -0,0 +1,38 @@ +package org.egov.referralmanagement.validator.hfreferral; + +import java.util.List; +import java.util.Map; + +import lombok.extern.slf4j.Slf4j; +import org.egov.common.models.Error; +import org.egov.common.models.referralmanagement.hfreferral.HFReferral; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralBulkRequest; +import org.egov.common.validator.Validator; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import static org.egov.common.utils.CommonUtils.validateForNullId; +import static org.egov.referralmanagement.Constants.GET_HF_REFERRALS; + +/** + * Validator for checking null id in HFReferral entities. + * + * Author: kanishq-egov + */ +@Component +@Order(value = 1) +@Slf4j +public class HfrNullIdValidator implements Validator { + + /** + * Validates if HFReferral entities have null ids. + * + * @param request The HFReferralBulkRequest containing a list of HFReferral entities + * @return A Map containing HFReferral entities as keys and lists of errors as values + */ + @Override + public Map> validate(HFReferralBulkRequest request) { + log.info("validating for null id"); + return validateForNullId(request, GET_HF_REFERRALS); + } +} diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrProjectFacilityIdValidator.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrProjectFacilityIdValidator.java new file mode 100644 index 00000000000..82ac9dba00a --- /dev/null +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrProjectFacilityIdValidator.java @@ -0,0 +1,134 @@ +package org.egov.referralmanagement.validator.hfreferral; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import lombok.extern.slf4j.Slf4j; +import org.egov.common.http.client.ServiceRequestClient; +import org.egov.common.models.Error; +import org.egov.common.models.project.ProjectFacility; +import org.egov.common.models.project.ProjectFacilityBulkResponse; +import org.egov.common.models.project.ProjectFacilitySearch; +import org.egov.common.models.project.ProjectFacilitySearchRequest; +import org.egov.common.models.referralmanagement.hfreferral.HFReferral; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralBulkRequest; +import org.egov.common.validator.Validator; +import org.egov.referralmanagement.config.ReferralManagementConfiguration; +import org.egov.tracer.model.CustomException; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import static org.egov.common.utils.CommonUtils.notHavingErrors; +import static org.egov.common.utils.CommonUtils.populateErrorDetails; +import static org.egov.common.utils.ValidatorUtils.getErrorForNonExistentEntity; + +/** + * Validator for checking the existence of ProjectFacility entities based on their IDs in HFReferral objects. + * + * Author: kanishq-egov + */ +@Component +@Order(value = 3) +@Slf4j +public class HfrProjectFacilityIdValidator implements Validator { + + private final ServiceRequestClient serviceRequestClient; + private final ReferralManagementConfiguration referralManagementConfiguration; + + public HfrProjectFacilityIdValidator(ServiceRequestClient serviceRequestClient, ReferralManagementConfiguration referralManagementConfiguration) { + this.serviceRequestClient = serviceRequestClient; + this.referralManagementConfiguration = referralManagementConfiguration; + } + + /** + * Validates whether project facilities exist in the database or not using project facility IDs for HFReferral objects. + * + * @param request The HFReferralBulkRequest containing a list of HFReferral entities + * @return A Map containing HFReferral entities as keys and lists of errors as values + */ + @Override + public Map> validate(HFReferralBulkRequest request) { + log.info("Validating project facility IDs"); + Map> errorDetailsMap = new HashMap<>(); + List entities = request.getHfReferrals(); + + // Grouping HFReferrals by tenantId to fetch project facilities for each tenant + Map> tenantIdReferralMap = entities.stream().collect(Collectors.groupingBy(HFReferral::getTenantId)); + tenantIdReferralMap.forEach((tenantId, hfReferralList) -> { + // Get all the existing project facilities in the HFReferral list from Project Service + List existingProjectFacilities = getExistingProjects(tenantId, hfReferralList, request); + // Validate project facilities and populate error map if invalid entities are found + validateAndPopulateErrors(existingProjectFacilities, entities, errorDetailsMap); + }); + + return errorDetailsMap; + } + + // Helper method to add an item to a list if it is not null + private void addIgnoreNull(List list, String item) { + if(Objects.nonNull(item)) list.add(item); + } + + // Fetches existing project facilities from Project Service based on their IDs + private List getExistingProjects(String tenantId, List hfReferrals, HFReferralBulkRequest request) { + List existingProjectFacilities = new ArrayList<>(); + final List projectFacilityIdList = new ArrayList<>(); + + // Collecting project facility IDs from HFReferrals + hfReferrals.forEach(hfReferral -> { + addIgnoreNull(projectFacilityIdList, hfReferral.getProjectFacilityId()); + }); + + if(!projectFacilityIdList.isEmpty()) { + ProjectFacilitySearch projectFacilitySearch = ProjectFacilitySearch.builder() + .id(!projectFacilityIdList.isEmpty()? projectFacilityIdList : null) + .tenantId(tenantId) + .build(); + + try { + // Using project facility search and fetching the valid IDs. + ProjectFacilityBulkResponse projectFacilityBulkResponse = serviceRequestClient.fetchResult( + new StringBuilder(referralManagementConfiguration.getProjectHost() + + referralManagementConfiguration.getProjectFacilitySearchUrl() + +"?limit=" + hfReferrals.size() + + "&offset=0&tenantId=" + tenantId), + ProjectFacilitySearchRequest.builder() + .requestInfo(request.getRequestInfo()) + .projectFacility(projectFacilitySearch) + .build(), + ProjectFacilityBulkResponse.class + ); + existingProjectFacilities = projectFacilityBulkResponse.getProjectFacilities(); + } catch (Exception e) { + throw new CustomException("Project Facilities failed to fetch", "Exception : "+e.getMessage()); + } + } + + return existingProjectFacilities; + } + + // Validates project facilities and populates the error map if invalid entities are found + private void validateAndPopulateErrors(List existingProjectFacilities, List entities, Map> errorDetailsMap) { + final List existingProjectFacilityIds = new ArrayList<>(); + + // Extracting IDs from existing project facilities + existingProjectFacilities.forEach(projectFacility -> { + existingProjectFacilityIds.add(projectFacility.getId()); + }); + + // Filtering invalid entities + List invalidEntities = entities.stream().filter(notHavingErrors()).filter(entity -> + Objects.nonNull(entity.getProjectFacilityId()) && !existingProjectFacilityIds.contains(entity.getProjectFacilityId()) + ).collect(Collectors.toList()); + + // Populating error details for invalid entities + invalidEntities.forEach(hfReferral -> { + Error error = getErrorForNonExistentEntity(); + populateErrorDetails(hfReferral, error, errorDetailsMap); + }); + } +} diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrProjectIdValidator.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrProjectIdValidator.java new file mode 100644 index 00000000000..78fc23289c4 --- /dev/null +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrProjectIdValidator.java @@ -0,0 +1,131 @@ +package org.egov.referralmanagement.validator.hfreferral; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import lombok.extern.slf4j.Slf4j; +import org.egov.common.http.client.ServiceRequestClient; +import org.egov.common.models.Error; +import org.egov.common.models.project.Project; +import org.egov.common.models.project.ProjectRequest; +import org.egov.common.models.project.ProjectResponse; +import org.egov.common.models.referralmanagement.hfreferral.HFReferral; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralBulkRequest; +import org.egov.common.validator.Validator; +import org.egov.referralmanagement.config.ReferralManagementConfiguration; +import org.egov.tracer.model.CustomException; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import static org.egov.common.utils.CommonUtils.notHavingErrors; +import static org.egov.common.utils.CommonUtils.populateErrorDetails; +import static org.egov.common.utils.ValidatorUtils.getErrorForNonExistentEntity; + +/** + * Validator for checking the existence of Project entities based on their IDs in HFReferral objects. + * + * Author: kanishq-egov + */ +@Component +@Order(value = 3) +@Slf4j +public class HfrProjectIdValidator implements Validator { + + private final ServiceRequestClient serviceRequestClient; + private final ReferralManagementConfiguration referralManagementConfiguration; + + public HfrProjectIdValidator(ServiceRequestClient serviceRequestClient, ReferralManagementConfiguration referralManagementConfiguration) { + this.serviceRequestClient = serviceRequestClient; + this.referralManagementConfiguration = referralManagementConfiguration; + } + + /** + * Validates whether projects exist in the database or not using project IDs for HFReferral objects. + * + * @param request The HFReferralBulkRequest containing a list of HFReferral entities + * @return A Map containing HFReferral entities as keys and lists of errors as values + */ + @Override + public Map> validate(HFReferralBulkRequest request) { + log.info("Validating project IDs"); + Map> errorDetailsMap = new HashMap<>(); + List entities = request.getHfReferrals(); + + // Grouping HFReferrals by tenantId to fetch projects for each tenant + Map> tenantIdReferralMap = entities.stream().collect(Collectors.groupingBy(HFReferral::getTenantId)); + tenantIdReferralMap.forEach((tenantId, hfReferralList) -> { + // Get all the existing projects in the hfReferral list from Project Service + List existingProjects = getExistingProjects(tenantId, hfReferralList, request); + // Validate projects and populate error map if invalid entities are found + validateAndPopulateErrors(existingProjects, entities, errorDetailsMap); + }); + + return errorDetailsMap; + } + + // Helper method to add an item to a list if it is not null + private void addIgnoreNull(List list, String item) { + if (Objects.nonNull(item)) list.add(item); + } + + // Fetches existing projects from Project Service based on their IDs + private List getExistingProjects(String tenantId, List hfReferrals, HFReferralBulkRequest request) { + List existingProjects = null; + final List projectIdList = new ArrayList<>(); + + // Collecting project IDs from HFReferrals + hfReferrals.forEach(hfReferral -> { + addIgnoreNull(projectIdList, hfReferral.getProjectId()); + }); + + if (!projectIdList.isEmpty()) { + List projects = new ArrayList<>(); + projectIdList.forEach(projectId -> projects.add(Project.builder().id(projectId).tenantId(tenantId).build())); + + try { + // Using project search and fetching the valid IDs. + ProjectResponse projectResponse = serviceRequestClient.fetchResult( + new StringBuilder(referralManagementConfiguration.getProjectHost() + + referralManagementConfiguration.getProjectSearchUrl() + + "?limit=" + hfReferrals.size() + + "&offset=0&tenantId=" + tenantId), + ProjectRequest.builder() + .requestInfo(request.getRequestInfo()) + .projects(projects) + .build(), + ProjectResponse.class + ); + existingProjects = projectResponse.getProject(); + } catch (Exception e) { + throw new CustomException("Projects failed to fetch", "Exception : " + e.getMessage()); + } + } + + return existingProjects; + } + + // Validates projects and populates the error map if invalid entities are found + private void validateAndPopulateErrors(List existingProjects, List entities, Map> errorDetailsMap) { + final List existingProjectIds = new ArrayList<>(); + + // Extracting IDs from existing projects + existingProjects.forEach(project -> { + existingProjectIds.add(project.getId()); + }); + + // Filtering invalid entities + List invalidEntities = entities.stream().filter(notHavingErrors()).filter(entity -> + Objects.nonNull(entity.getProjectId()) && !existingProjectIds.contains(entity.getProjectId()) + ).collect(Collectors.toList()); + + // Populating error details for invalid entities + invalidEntities.forEach(hfReferral -> { + Error error = getErrorForNonExistentEntity(); + populateErrorDetails(hfReferral, error, errorDetailsMap); + }); + } +} diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrRowVersionValidator.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrRowVersionValidator.java new file mode 100644 index 00000000000..e5d62bfee0a --- /dev/null +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrRowVersionValidator.java @@ -0,0 +1,74 @@ +package org.egov.referralmanagement.validator.hfreferral; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import lombok.extern.slf4j.Slf4j; +import org.egov.common.models.Error; +import org.egov.common.models.referralmanagement.hfreferral.HFReferral; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralBulkRequest; +import org.egov.common.validator.Validator; +import org.egov.referralmanagement.repository.HFReferralRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import static org.egov.common.utils.CommonUtils.getEntitiesWithMismatchedRowVersion; +import static org.egov.common.utils.CommonUtils.getIdFieldName; +import static org.egov.common.utils.CommonUtils.getIdMethod; +import static org.egov.common.utils.CommonUtils.getIdToObjMap; +import static org.egov.common.utils.CommonUtils.notHavingErrors; +import static org.egov.common.utils.CommonUtils.populateErrorDetails; +import static org.egov.common.utils.ValidatorUtils.getErrorForRowVersionMismatch; + +/** + * + * Validator for checking row version mismatch in HFReferral entities during bulk processing. + * Ensures that the row version of existing entities matches the row version in the request. + * + * @author kanishq-egov + */ +@Component +@Order(value = 5) +@Slf4j +public class HfrRowVersionValidator implements Validator { + + private final HFReferralRepository hfReferralRepository; + + @Autowired + public HfrRowVersionValidator(HFReferralRepository hfReferralRepository) { + this.hfReferralRepository = hfReferralRepository; + } + + /** + * Validates row version for HFReferral entities in a bulk request. + * + * @param request The HFReferralBulkRequest containing a list of HFReferral entities + * @return A Map containing HFReferral entities as keys and lists of errors as values + */ + @Override + public Map> validate(HFReferralBulkRequest request) { + log.info("Validating row version"); + Map> errorDetailsMap = new HashMap<>(); + Method idMethod = getIdMethod(request.getHfReferrals()); + Map iMap = getIdToObjMap(request.getHfReferrals().stream() + .filter(notHavingErrors()) + .collect(Collectors.toList()), idMethod); + if (!iMap.isEmpty()) { + List hfReferralIds = new ArrayList<>(iMap.keySet()); + List existingHfReferrals = hfReferralRepository.findById(hfReferralIds, + false, getIdFieldName(idMethod)); + List entitiesWithMismatchedRowVersion = + getEntitiesWithMismatchedRowVersion(iMap, existingHfReferrals, idMethod); + entitiesWithMismatchedRowVersion.forEach(hfReferral -> { + Error error = getErrorForRowVersionMismatch(); + populateErrorDetails(hfReferral, error, errorDetailsMap); + }); + } + return errorDetailsMap; + } +} diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrUniqueEntityValidator.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrUniqueEntityValidator.java new file mode 100644 index 00000000000..42c84640201 --- /dev/null +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/validator/hfreferral/HfrUniqueEntityValidator.java @@ -0,0 +1,65 @@ +package org.egov.referralmanagement.validator.hfreferral; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import lombok.extern.slf4j.Slf4j; +import org.egov.common.models.Error; +import org.egov.common.models.referralmanagement.hfreferral.HFReferral; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralBulkRequest; +import org.egov.common.validator.Validator; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import static org.egov.common.utils.CommonUtils.getIdToObjMap; +import static org.egov.common.utils.CommonUtils.notHavingErrors; +import static org.egov.common.utils.CommonUtils.populateErrorDetails; +import static org.egov.common.utils.ValidatorUtils.getErrorForUniqueEntity; + +/** + * + * Validator for checking uniqueness of HFReferral entities in a bulk request. + * Ensures that there are no duplicate entities based on their IDs. + * + * Author: kanishq-egov + */ +@Component +@Order(value = 2) +@Slf4j +public class HfrUniqueEntityValidator implements Validator { + + /** + * Validates the uniqueness of HFReferral entities based on their IDs. + * + * @param request The HFReferralBulkRequest containing a list of HFReferral entities + * @return A Map containing HFReferral entities as keys and lists of errors as values + */ + @Override + public Map> validate(HFReferralBulkRequest request) { + log.info("Validating unique entity"); + Map> errorDetailsMap = new HashMap<>(); + List validEntities = request.getHfReferrals() + .stream().filter(notHavingErrors()).collect(Collectors.toList()); + if (!validEntities.isEmpty()) { + // Create a map of entity IDs to HFReferral objects + Map eMap = getIdToObjMap(validEntities); + + // Check for duplicate IDs + if (eMap.keySet().size() != validEntities.size()) { + List duplicates = eMap.keySet().stream().filter(id -> + validEntities.stream() + .filter(entity -> entity.getId().equals(id)).count() > 1 + ).collect(Collectors.toList()); + + // Populate errors for duplicate entities + for (String key : duplicates) { + Error error = getErrorForUniqueEntity(); + populateErrorDetails(eMap.get(key), error, errorDetailsMap); + } + } + } + return errorDetailsMap; + } +} diff --git a/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/web/controllers/HFReferralApiController.java b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/web/controllers/HFReferralApiController.java new file mode 100644 index 00000000000..97650777201 --- /dev/null +++ b/health-services/referralmanagement/src/main/java/org/egov/referralmanagement/web/controllers/HFReferralApiController.java @@ -0,0 +1,193 @@ +package org.egov.referralmanagement.web.controllers; + +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; + +import io.swagger.annotations.ApiParam; +import org.egov.common.contract.response.ResponseInfo; +import org.egov.common.models.referralmanagement.hfreferral.HFReferral; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralBulkRequest; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralBulkResponse; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralRequest; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralResponse; +import org.egov.common.models.referralmanagement.hfreferral.HFReferralSearchRequest; +import org.egov.common.producer.Producer; +import org.egov.common.utils.ResponseInfoFactory; +import org.egov.referralmanagement.config.ReferralManagementConfiguration; +import org.egov.referralmanagement.service.HFReferralService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.validation.annotation.Validated; +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.RequestParam; + +/** + * Controller class for managing HF Referrals. + * @author kanishq-egov + */ +@Controller +@RequestMapping("/hf-referral") +@Validated +public class HFReferralApiController { + private final HttpServletRequest httpServletRequest; + private final HFReferralService hfReferralService; + private final Producer producer; + private final ReferralManagementConfiguration referralManagementConfiguration; + + /** + * Constructor for HFReferralApiController. + * + * @param httpServletRequest The HTTP servlet request. + * @param hfReferralService The service for handling HFReferral operations. + * @param producer The Kafka producer. + * @param referralManagementConfiguration The configuration for referral management. + */ + public HFReferralApiController( + HttpServletRequest httpServletRequest, + HFReferralService hfReferralService, + Producer producer, + ReferralManagementConfiguration referralManagementConfiguration + ) { + this.httpServletRequest = httpServletRequest; + this.hfReferralService = hfReferralService; + this.producer = producer; + this.referralManagementConfiguration = referralManagementConfiguration; + } + + /** + * API endpoint to create a single HFReferral. + * + * @param request The HFReferralRequest containing referral details. + * @return ResponseEntity containing HFReferralResponse. + */ + @RequestMapping(value = "/v1/_create", method = RequestMethod.POST) + public ResponseEntity referralV1CreatePost(@ApiParam(value = "Capture details of HFReferral", required = true) @Valid @RequestBody HFReferralRequest request) { + + HFReferral hfReferral = hfReferralService.create(request); + HFReferralResponse response = HFReferralResponse.builder() + .hfReferral(hfReferral) + .responseInfo(ResponseInfoFactory + .createResponseInfo(request.getRequestInfo(), true)) + .build(); + + return ResponseEntity.status(HttpStatus.ACCEPTED).body(response); + } + + /** + * API endpoint to create multiple HFReferrals in bulk. + * + * @param request The HFReferralBulkRequest containing bulk referral details. + * @return ResponseEntity containing ResponseInfo. + */ + @RequestMapping(value = "/v1/bulk/_create", method = RequestMethod.POST) + public ResponseEntity referralBulkV1CreatePost(@ApiParam(value = "Capture details of HFReferral", required = true) @Valid @RequestBody HFReferralBulkRequest request) { + request.getRequestInfo().setApiId(httpServletRequest.getRequestURI()); + hfReferralService.putInCache(request.getHfReferrals()); + producer.push(referralManagementConfiguration.getCreateHFReferralBulkTopic(), request); + + return ResponseEntity.status(HttpStatus.ACCEPTED).body(ResponseInfoFactory + .createResponseInfo(request.getRequestInfo(), true)); + } + + /** + * API endpoint to search for HFReferrals based on certain criteria. + * + * @param request The HFReferralSearchRequest containing search criteria. + * @param limit Pagination - limit records in response. + * @param offset Pagination - offset from which records should be returned in response. + * @param tenantId Unique id for a tenant. + * @param lastChangedSince Epoch of the time since when the changes on the object should be picked up. + * @param includeDeleted Used in search APIs to specify if (soft) deleted records should be included in search results. + * @return ResponseEntity containing HFReferralBulkResponse. + * @throws Exception + */ + @RequestMapping(value = "/v1/_search", method = RequestMethod.POST) + public ResponseEntity referralV1SearchPost(@ApiParam(value = "HFReferral Search.", required = true) @Valid @RequestBody HFReferralSearchRequest request, + @NotNull @Min(0) @Max(1000) @ApiParam(value = "Pagination - limit records in response", required = true) @Valid @RequestParam(value = "limit", required = true) Integer limit, + @NotNull @Min(0) @ApiParam(value = "Pagination - offset from which records should be returned in response", required = true) @Valid @RequestParam(value = "offset", required = true) Integer offset, + @NotNull @ApiParam(value = "Unique id for a tenant.", required = true) @Valid @RequestParam(value = "tenantId", required = true) String tenantId, + @ApiParam(value = "Epoch of the time since when the changes on the object should be picked up. Search results from this parameter should include both newly created objects since this time as well as any modified objects since this time. This criterion is included to help polling clients to get the changes in system since a last time they synchronized with the platform. ") @Valid @RequestParam(value = "lastChangedSince", required = false) Long lastChangedSince, + @ApiParam(value = "Used in search APIs to specify if (soft) deleted records should be included in search results.", defaultValue = "false") @Valid @RequestParam(value = "includeDeleted", required = false, defaultValue = "false") Boolean includeDeleted) throws Exception { + + List hfReferrals = hfReferralService.search(request, limit, offset, tenantId, lastChangedSince, includeDeleted); + HFReferralBulkResponse response = HFReferralBulkResponse.builder().responseInfo(ResponseInfoFactory + .createResponseInfo(request.getRequestInfo(), true)).hfReferrals(hfReferrals).build(); + + return ResponseEntity.status(HttpStatus.OK).body(response); + } + + /** + * API endpoint to update a single HFReferral. + * + * @param request The HFReferralRequest containing updated referral details. + * @return ResponseEntity containing HFReferralResponse. + */ + @RequestMapping(value = "/v1/_update", method = RequestMethod.POST) + public ResponseEntity referralV1UpdatePost(@ApiParam(value = "Capture details of Existing HFReferral", required = true) @Valid @RequestBody HFReferralRequest request) { + HFReferral hfReferral = hfReferralService.update(request); + + HFReferralResponse response = HFReferralResponse.builder() + .hfReferral(hfReferral) + .responseInfo(ResponseInfoFactory + .createResponseInfo(request.getRequestInfo(), true)) + .build(); + + return ResponseEntity.status(HttpStatus.ACCEPTED).body(response); + } + + /** + * API endpoint to update multiple HFReferrals in bulk. + * + * @param request The HFReferralBulkRequest containing bulk updated referral details. + * @return ResponseEntity containing ResponseInfo. + */ + @RequestMapping(value = "/v1/bulk/_update", method = RequestMethod.POST) + public ResponseEntity referralV1BulkUpdatePost(@ApiParam(value = "Capture details of Existing HFReferral", required = true) @Valid @RequestBody HFReferralBulkRequest request) { + request.getRequestInfo().setApiId(httpServletRequest.getRequestURI()); + producer.push(referralManagementConfiguration.getUpdateHFReferralBulkTopic(), request); + + return ResponseEntity.status(HttpStatus.ACCEPTED).body(ResponseInfoFactory + .createResponseInfo(request.getRequestInfo(), true)); + } + + /** + * API endpoint to delete a single HFReferral. + * + * @param request The HFReferralRequest containing details of the referral to be deleted. + * @return ResponseEntity containing HFReferralResponse. + */ + @RequestMapping(value = "/v1/_delete", method = RequestMethod.POST) + public ResponseEntity referralV1DeletePost(@ApiParam(value = "Capture details of Existing HFReferral", required = true) @Valid @RequestBody HFReferralRequest request) { + HFReferral hfReferral = hfReferralService.delete(request); + + HFReferralResponse response = HFReferralResponse.builder() + .hfReferral(hfReferral) + .responseInfo(ResponseInfoFactory + .createResponseInfo(request.getRequestInfo(), true)) + .build(); + + return ResponseEntity.status(HttpStatus.ACCEPTED).body(response); + } + + /** + * API endpoint to delete multiple HFReferrals in bulk. + * + * @param request The HFReferralBulkRequest containing details of the referrals to be deleted in bulk. + * @return ResponseEntity containing ResponseInfo. + */ + @RequestMapping(value = "/v1/bulk/_delete", method = RequestMethod.POST) + public ResponseEntity referralV1BulkDeletePost(@ApiParam(value = "Capture details of Existing HFReferral", required = true) @Valid @RequestBody HFReferralBulkRequest request) { + request.getRequestInfo().setApiId(httpServletRequest.getRequestURI()); + producer.push(referralManagementConfiguration.getDeleteHFReferralBulkTopic(), request); + + return ResponseEntity.status(HttpStatus.ACCEPTED).body(ResponseInfoFactory + .createResponseInfo(request.getRequestInfo(), true)); + } +} diff --git a/health-services/referralmanagement/src/main/resources/application.properties b/health-services/referralmanagement/src/main/resources/application.properties index 22830c099f1..b7ac09656ac 100644 --- a/health-services/referralmanagement/src/main/resources/application.properties +++ b/health-services/referralmanagement/src/main/resources/application.properties @@ -97,10 +97,12 @@ egov.search.individual.url=/individual/v1/_search egov.user.id.validator=individual # PROJECT SERVICE -egov.project.host=http://localhost:8084 +egov.project.host=https://unified-dev.digit.org +egov.search.project.url=/project/v1/_search egov.search.project.task.url=/project/task/v1/_search egov.search.project.beneficiary.url=/project/beneficiary/v1/_search egov.search.project.staff.url=/project/staff/v1/_search +egov.search.project.facility.url=/project/facility/v1/_search # ADRM KAFKA CONFIG @@ -120,6 +122,14 @@ referralmanagement.referral.consumer.bulk.create.topic=save-referral-bulk-topic referralmanagement.referral.consumer.bulk.update.topic=update-referral-bulk-topic referralmanagement.referral.consumer.bulk.delete.topic=delete-referral-bulk-topic +referralmanagement.hfreferral.kafka.create.topic=save-hfreferral-topic +referralmanagement.hfreferral.kafka.update.topic=update-hfreferral-topic +referralmanagement.hfreferral.kafka.delete.topic=delete-hfreferral-topic + +referralmanagement.hfreferral.consumer.bulk.create.topic=save-hfreferral-bulk-topic +referralmanagement.hfreferral.consumer.bulk.update.topic=update-hfreferral-bulk-topic +referralmanagement.hfreferral.consumer.bulk.delete.topic=delete-hfreferral-bulk-topic + search.api.limit=1000 referralmanagement.default.offset=0 diff --git a/health-services/referralmanagement/src/main/resources/db/migration/main/V20231214113400__hf_referral_create_ddl.sql b/health-services/referralmanagement/src/main/resources/db/migration/main/V20231214113400__hf_referral_create_ddl.sql new file mode 100644 index 00000000000..0d4dfbd4dad --- /dev/null +++ b/health-services/referralmanagement/src/main/resources/db/migration/main/V20231214113400__hf_referral_create_ddl.sql @@ -0,0 +1,25 @@ +CREATE table IF NOT EXISTS hf_referral ( + id character varying(64), + clientreferenceid character varying(64), + tenantid character varying(1000), + projectid character varying(64), + facilityId character varying(64), + symptom character varying(256), + symptomsurveyid character varying(100), + beneficiaryid character varying(100), + referralcode character varying(100), + nationallevelid character varying(100), + createdby character varying(64), + createdtime bigint, + lastmodifiedby character varying(64), + lastmodifiedtime bigint, + clientcreatedby character varying(64), + clientcreatedtime bigint, + clientlastmodifiedby character varying(64), + clientlastmodifiedtime bigint, + rowversion bigint, + isdeleted boolean, + additionaldetails jsonb, + CONSTRAINT uk_hf_referral_id PRIMARY KEY (id), + CONSTRAINT uk_hf_referral_clientReferenceId UNIQUE (clientReferenceId) +); \ No newline at end of file diff --git a/health-services/referralmanagement/src/main/resources/db/migration/main/V20240103142200__hf_referral_project_facility_rename_ddl.sql b/health-services/referralmanagement/src/main/resources/db/migration/main/V20240103142200__hf_referral_project_facility_rename_ddl.sql new file mode 100644 index 00000000000..f7a8fb9b884 --- /dev/null +++ b/health-services/referralmanagement/src/main/resources/db/migration/main/V20240103142200__hf_referral_project_facility_rename_ddl.sql @@ -0,0 +1 @@ +ALTER TABLE hf_referral RENAME COLUMN facilityid to projectfacilityid; \ No newline at end of file diff --git a/health-services/stock/CHANGELOG.md b/health-services/stock/CHANGELOG.md index 8bb88bb178f..83d0dd54070 100644 --- a/health-services/stock/CHANGELOG.md +++ b/health-services/stock/CHANGELOG.md @@ -1,5 +1,11 @@ All notable changes to this module will be documented in this file. +## 1.1.2 - 2024-02-26 +- Enhance inventory flow with sender id and receiver id added. + +## 1.1.1 - 2023-11-15 + - Enhanced inventory flow for last mile delivery with QR code + ## 1.1.1-beta - Enhanced Inventory flow for last mile delivery diff --git a/health-services/stock/pom.xml b/health-services/stock/pom.xml index 36a6ee1f830..1ccbcf4a3e4 100644 --- a/health-services/stock/pom.xml +++ b/health-services/stock/pom.xml @@ -49,7 +49,7 @@ org.egov.common health-services-models - 1.0.9-SNAPSHOT + 1.0.15-SNAPSHOT diff --git a/health-services/stock/src/main/java/org/egov/stock/config/MainConfiguration.java b/health-services/stock/src/main/java/org/egov/stock/config/MainConfiguration.java index e0d61ae0682..b067e1cb2ab 100644 --- a/health-services/stock/src/main/java/org/egov/stock/config/MainConfiguration.java +++ b/health-services/stock/src/main/java/org/egov/stock/config/MainConfiguration.java @@ -6,6 +6,8 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.egov.common.models.core.validator.CustomIntegerDeserializer; import org.egov.tracer.config.TracerConfiguration; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -42,7 +44,12 @@ public void initialize() { @Bean public ObjectMapper objectMapper(){ - return new ObjectMapper().disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES).setTimeZone(TimeZone.getTimeZone(timeZone)); + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SimpleModule module = new SimpleModule(); + module.addDeserializer(Integer.class, new CustomIntegerDeserializer()); + objectMapper.registerModule(module); + return objectMapper.setTimeZone(TimeZone.getTimeZone(timeZone)); } @Bean diff --git a/health-services/stock/src/main/java/org/egov/stock/repository/rowmapper/StockRowMapper.java b/health-services/stock/src/main/java/org/egov/stock/repository/rowmapper/StockRowMapper.java index 89471581084..d011f3301a4 100644 --- a/health-services/stock/src/main/java/org/egov/stock/repository/rowmapper/StockRowMapper.java +++ b/health-services/stock/src/main/java/org/egov/stock/repository/rowmapper/StockRowMapper.java @@ -4,6 +4,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import digit.models.coremodels.AuditDetails; import org.egov.common.models.stock.AdditionalFields; +import org.egov.common.models.stock.ReferenceIdType; +import org.egov.common.models.stock.SenderReceiverType; import org.egov.common.models.stock.Stock; import org.egov.common.models.stock.TransactionReason; import org.egov.common.models.stock.TransactionType; @@ -33,6 +35,10 @@ public Stock mapRow(ResultSet resultSet, int i) throws SQLException { .lastModifiedTime(resultSet.getLong("clientLastModifiedTime")) .lastModifiedBy(resultSet.getString("clientLastModifiedBy")) .build(); + Long dateOfEntry = resultSet.getLong("dateOfEntry"); + if(resultSet.wasNull()){ + dateOfEntry = null; + } return Stock.builder() .id(resultSet.getString("id")) .clientReferenceId(resultSet.getString("clientReferenceId")) @@ -41,20 +47,20 @@ public Stock mapRow(ResultSet resultSet, int i) throws SQLException { .quantity(resultSet.getInt("quantity")) .wayBillNumber(resultSet.getString("wayBillNumber")) .referenceId(resultSet.getString("referenceId")) - .referenceIdType(resultSet.getString("referenceIdType")) + .referenceIdType(ReferenceIdType.fromValue(resultSet.getString("referenceIdType"))) .transactionType(TransactionType.fromValue(resultSet.getString("transactionType"))) .transactionReason(TransactionReason.fromValue(resultSet.getString("transactionReason"))) .senderId(resultSet.getString("senderId")) - .senderType(resultSet.getString("senderType")) + .senderType(SenderReceiverType.fromValue(resultSet.getString("senderType"))) .receiverId(resultSet.getString("receiverId")) - .receiverType(resultSet.getString("receiverType")) + .receiverType(SenderReceiverType.fromValue(resultSet.getString("receiverType"))) .additionalFields(resultSet.getString("additionalDetails") == null ? null : objectMapper .readValue(resultSet.getString("additionalDetails"), AdditionalFields.class)) .auditDetails(auditDetails) .clientAuditDetails(clientAuditDetails) .rowVersion(resultSet.getInt("rowVersion")) .isDeleted(resultSet.getBoolean("isDeleted")) - .dateOfEntry(resultSet.getLong("dateOfEntry")) + .dateOfEntry(dateOfEntry) .build(); } catch (JsonProcessingException e) { throw new SQLException(e); diff --git a/health-services/stock/src/main/java/org/egov/stock/service/FacilityService.java b/health-services/stock/src/main/java/org/egov/stock/service/FacilityService.java index 068a26a99fb..5d93a0ecfdd 100644 --- a/health-services/stock/src/main/java/org/egov/stock/service/FacilityService.java +++ b/health-services/stock/src/main/java/org/egov/stock/service/FacilityService.java @@ -25,6 +25,7 @@ import org.egov.common.models.project.ProjectFacilityBulkResponse; import org.egov.common.models.project.ProjectFacilitySearch; import org.egov.common.models.project.ProjectFacilitySearchRequest; +import org.egov.common.models.stock.SenderReceiverType; import org.egov.common.models.stock.Stock; import org.egov.common.models.stock.StockReconciliation; import org.egov.stock.config.StockConfiguration; @@ -97,10 +98,10 @@ public Map> validateProjectFacilityMappings(List ent Stock stock = (Stock) entity; - if (stock.getSenderType().equalsIgnoreCase(WAREHOUSE)) { + if (SenderReceiverType.WAREHOUSE.equals(stock.getSenderType())) { facilityIds.add(stock.getSenderId()); } - if (stock.getReceiverType().equalsIgnoreCase(WAREHOUSE)) { + if (SenderReceiverType.WAREHOUSE.equals(stock.getReceiverType())) { facilityIds.add(stock.getReceiverId()); } } diff --git a/health-services/stock/src/main/java/org/egov/stock/service/StockService.java b/health-services/stock/src/main/java/org/egov/stock/service/StockService.java index 8bbbd72c065..7876d60ac63 100644 --- a/health-services/stock/src/main/java/org/egov/stock/service/StockService.java +++ b/health-services/stock/src/main/java/org/egov/stock/service/StockService.java @@ -34,6 +34,7 @@ import org.egov.stock.validator.stock.SProductVariantIdValidator; import org.egov.stock.validator.stock.SReferenceIdValidator; import org.egov.stock.validator.stock.SRowVersionValidator; +import org.egov.stock.validator.stock.SSenderIdReceiverIdEqualsValidator; import org.egov.stock.validator.stock.SUniqueEntityValidator; import org.egov.stock.validator.stock.StocktransferPartiesValidator; import org.egov.stock.web.models.StockSearchRequest; @@ -57,6 +58,7 @@ public class StockService { private final Predicate> isApplicableForCreate = validator -> validator.getClass().equals(SProductVariantIdValidator.class) + || validator.getClass().equals(SSenderIdReceiverIdEqualsValidator.class) || validator.getClass().equals(StocktransferPartiesValidator.class) || validator.getClass().equals(SReferenceIdValidator.class); @@ -68,11 +70,13 @@ public class StockService { || validator.getClass().equals(SRowVersionValidator.class) || validator.getClass().equals(SUniqueEntityValidator.class) || validator.getClass().equals(SReferenceIdValidator.class) + || validator.getClass().equals(SSenderIdReceiverIdEqualsValidator.class) || validator.getClass().equals(StocktransferPartiesValidator.class); private final Predicate> isApplicableForDelete = validator -> validator.getClass().equals(SNonExistentValidator.class) - || validator.getClass().equals(SNullIdValidator.class); + || validator.getClass().equals(SNullIdValidator.class) + || validator.getClass().equals(SRowVersionValidator.class); public StockService(StockRepository stockRepository, List> validators, StockConfiguration configuration, StockEnrichmentService enrichmentService) { this.stockRepository = stockRepository; diff --git a/health-services/stock/src/main/java/org/egov/stock/util/ValidatorUtil.java b/health-services/stock/src/main/java/org/egov/stock/util/ValidatorUtil.java index b39ad93699d..b46431fe018 100644 --- a/health-services/stock/src/main/java/org/egov/stock/util/ValidatorUtil.java +++ b/health-services/stock/src/main/java/org/egov/stock/util/ValidatorUtil.java @@ -21,6 +21,7 @@ import org.egov.common.contract.request.RequestInfo; import org.egov.common.ds.Tuple; import org.egov.common.models.Error; +import org.egov.common.models.stock.SenderReceiverType; import org.egov.common.models.stock.Stock; import org.egov.common.models.stock.StockReconciliation; import org.egov.common.service.UserService; @@ -64,17 +65,13 @@ public static Map> validateFacilityIds(R request, Map - * @param - * @param stockRequest + * Non-generic method used for validating sender/receiver (parties) against facility or staff based on the type + * + * @param requestInfo * @param errorDetailsMap - * @param validEntities - * @param getId + * @param validStockEntities * @param facilityService + * @param userService * @return */ public static Map> validateStockTransferParties(RequestInfo requestInfo, @@ -94,17 +91,14 @@ public static Map> validateStockTransferParties(RequestInf } /** - * validates the list of party-ids (facility and staff) against the respective - * APIs and enriches the invalid ids list for both parties - * - * @param - * @param stockRequest + * Validates the list of party-ids (facility and staff) against the respective APIs and enriches the invalid ids list for both parties. + * + * @param requestInfo * @param errorDetailsMap * @param validStockEntities * @param facilityService - * @param facilityIds - * @param InvalidStaffId - * @param invalidFacilityIds + * @param userService + * @return A tuple containing lists of invalid facility ids and invalid staff ids */ @SuppressWarnings("unchecked") private static Tuple, List> validateAndEnrichInvalidPartyIds(RequestInfo requestInfo, @@ -158,18 +152,18 @@ private static void enrichFaciltyAndStaffIdsFromStock(List validStockEnti for (Stock stock : validStockEntities) { - if (stock.getSenderType().equalsIgnoreCase(WAREHOUSE)) { + if (SenderReceiverType.WAREHOUSE.equals(stock.getSenderType()) && stock.getSenderId() != null) { facilityIds.add(stock.getSenderId()); - } - if (stock.getSenderType().equalsIgnoreCase(STAFF)) { + } else if (SenderReceiverType.STAFF.equals(stock.getSenderType()) && stock.getSenderId() != null) { staffIds.add(stock.getSenderId()); } - if (stock.getReceiverType().equalsIgnoreCase(WAREHOUSE)) { + + if (SenderReceiverType.WAREHOUSE.equals(stock.getReceiverType()) && stock.getReceiverId() != null) { facilityIds.add(stock.getReceiverId()); - } - if (stock.getReceiverType().equalsIgnoreCase(STAFF)) { + } else if (SenderReceiverType.STAFF.equals(stock.getReceiverType()) && stock.getReceiverId() != null) { staffIds.add(stock.getReceiverId()); } + } } @@ -179,7 +173,7 @@ private static void enrichFaciltyAndStaffIdsFromStock(List validStockEnti * * @param errorDetailsMap * @param validStockEntities - * @param InvalidStaffId + * @param invalidStaffIds * @param invalidFacilityIds */ @SuppressWarnings("unchecked") @@ -195,16 +189,16 @@ private static void enrichErrorMapFromInvalidPartyIds(Map> er String senderId = stock.getSenderId(); String recieverId = stock.getReceiverId(); - if ((stock.getSenderType().equalsIgnoreCase(WAREHOUSE) && invalidFacilityIds.contains(senderId)) + if ((SenderReceiverType.WAREHOUSE.equals(stock.getSenderType()) && invalidFacilityIds.contains(senderId)) - || (stock.getSenderType().equalsIgnoreCase(STAFF) && invalidStaffIds.contains(senderId))) { + || (SenderReceiverType.STAFF.equals(stock.getSenderType()) && invalidStaffIds.contains(senderId))) { getIdForErrorFromMethod(errorDetailsMap, (T) stock, senderIdMethod); } - if ((stock.getReceiverType().equalsIgnoreCase(WAREHOUSE) && invalidFacilityIds.contains(recieverId)) + if ((SenderReceiverType.WAREHOUSE.equals(stock.getReceiverType()) && invalidFacilityIds.contains(recieverId)) - || (stock.getReceiverType().equalsIgnoreCase(STAFF) && invalidStaffIds.contains(recieverId))) { + || (SenderReceiverType.STAFF.equals(stock.getReceiverType()) && invalidStaffIds.contains(recieverId))) { getIdForErrorFromMethod(errorDetailsMap, (T) stock, recieverIdMethod); } @@ -232,7 +226,7 @@ private static void getIdForErrorFromMethod(Map> errorDetails * @param request * @param errorDetailsMap * @param validEntities - * @param getId + * @param getReferenceId * @param facilityService * @return */ @@ -279,11 +273,11 @@ private static void enrichErrorForStock(List validEntities, List facilityIds = ProjectFacilityMappingOfIds.get(stock.getReferenceId()); if (!CollectionUtils.isEmpty(facilityIds)) { - if (stock.getSenderType().equalsIgnoreCase("WAREHOUSE") && !facilityIds.contains(senderId)) { + if (SenderReceiverType.WAREHOUSE.equals(stock.getSenderType()) && !facilityIds.contains(senderId)) { populateErrorForStock(stock, senderId, errorDetailsMap); } - if (stock.getReceiverType().equalsIgnoreCase("WAREHOUSE") && !facilityIds.contains(receiverId)) + if (SenderReceiverType.WAREHOUSE.equals(stock.getReceiverType()) && !facilityIds.contains(receiverId)) populateErrorForStock(stock, receiverId, errorDetailsMap); } else { populateErrorForStock(stock, senderId + " and " + receiverId, errorDetailsMap); diff --git a/health-services/stock/src/main/java/org/egov/stock/validator/stock/SReferenceIdValidator.java b/health-services/stock/src/main/java/org/egov/stock/validator/stock/SReferenceIdValidator.java index 47a17106727..ceab1dfb887 100644 --- a/health-services/stock/src/main/java/org/egov/stock/validator/stock/SReferenceIdValidator.java +++ b/health-services/stock/src/main/java/org/egov/stock/validator/stock/SReferenceIdValidator.java @@ -2,6 +2,8 @@ import lombok.extern.slf4j.Slf4j; import org.egov.common.models.Error; +import org.egov.common.models.stock.ReferenceIdType; +import org.egov.common.models.stock.SenderReceiverType; import org.egov.common.models.stock.Stock; import org.egov.common.models.stock.StockBulkRequest; import org.egov.common.validator.Validator; @@ -37,11 +39,11 @@ public Map> validate(StockBulkRequest request) { List validEntities = request.getStock().stream() .filter(notHavingErrors()) - .filter(entity -> PROJECT.equals(entity.getReferenceIdType())) + .filter(entity -> ReferenceIdType.PROJECT.equals(entity.getReferenceIdType())) .collect(Collectors.toList()); - long countOfWareHouseInStock = request.getStock().stream().filter(stock -> - stock.getReceiverType().equalsIgnoreCase("WAREHOUSE") || stock.getSenderType().equalsIgnoreCase("WAREHOUSE") + long countOfWareHouseInStock = request.getStock().stream().filter(stock -> + SenderReceiverType.WAREHOUSE.equals(stock.getReceiverType()) || SenderReceiverType.WAREHOUSE.equals(stock.getSenderType()) ).count(); if(countOfWareHouseInStock == 0) return errorDetailsMap; diff --git a/health-services/stock/src/main/java/org/egov/stock/validator/stock/SSenderIdReceiverIdEqualsValidator.java b/health-services/stock/src/main/java/org/egov/stock/validator/stock/SSenderIdReceiverIdEqualsValidator.java new file mode 100644 index 00000000000..4285d90d26d --- /dev/null +++ b/health-services/stock/src/main/java/org/egov/stock/validator/stock/SSenderIdReceiverIdEqualsValidator.java @@ -0,0 +1,75 @@ +package org.egov.stock.validator.stock; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import lombok.extern.slf4j.Slf4j; +import org.egov.common.models.Error; +import org.egov.common.models.stock.Stock; +import org.egov.common.models.stock.StockBulkRequest; +import org.egov.common.validator.Validator; +import org.egov.tracer.model.CustomException; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import static org.egov.common.utils.CommonUtils.populateErrorDetails; + +/** + * Validator class to check if senderId and receiverId are equal in a list of Stock entities. + */ +@Component +@Order(value = 6) +@Slf4j +public class SSenderIdReceiverIdEqualsValidator implements Validator { + + /** + * Validates the list of Stock entities to ensure that senderId and receiverId are not equal. + * + * @param stockBulkRequest The bulk request containing a list of Stock entities. + * @return A map containing Stock entities with corresponding error details for entities with equal senderId and receiverId. + */ + @Override + public Map> validate(StockBulkRequest stockBulkRequest) { + Map> errorDetailsMap = new HashMap<>(); + List entities = stockBulkRequest.getStock(); + List invalidEntities = new ArrayList<>(); + log.info("validating whether sender id and receiver id are same"); + + // Iterate through each Stock entity in the list + entities.forEach(stock -> { + // Check if senderId and receiverId are equal using helper method + if (areSenderAndReceiverEqual(stock)) { + // If equal, add the entity to the list of invalid entities + invalidEntities.add(stock); + + // Create an error object for the entity + Error error = Error.builder() + .errorMessage("Sender Id and Receiver Id cannot be the same") + .errorCode("SENDER_RECEIVER_CANNOT_BE_EQUAL") + .type(Error.ErrorType.NON_RECOVERABLE) + .exception(new CustomException("SENDER_RECEIVER_CANNOT_BE_EQUAL", "Sender Id and Receiver Id cannot be the same")) + .build(); + + // Populate error details for the entity + populateErrorDetails(stock, error, errorDetailsMap); + } + }); + + return errorDetailsMap; + } + + /** + * Helper method to check if senderId and receiverId are equal. + * + * @param stock The Stock entity to check. + * @return True if senderId and receiverId are equal, false otherwise. + */ + private boolean areSenderAndReceiverEqual(Stock stock) { + return stock.getSenderType() == stock.getReceiverType() + && stock.getReceiverId() != null + && stock.getSenderId() != null + && stock.getReceiverId().equals(stock.getSenderId()); + } +} diff --git a/health-services/stock/src/test/java/org/egov/stock/TestConfiguration.java b/health-services/stock/src/test/java/org/egov/stock/TestConfiguration.java index 0d8d9758688..d507efd67c1 100644 --- a/health-services/stock/src/test/java/org/egov/stock/TestConfiguration.java +++ b/health-services/stock/src/test/java/org/egov/stock/TestConfiguration.java @@ -1,5 +1,11 @@ package org.egov.stock; +import java.util.TimeZone; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import org.egov.common.models.core.validator.CustomIntegerDeserializer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.kafka.core.KafkaTemplate; @@ -13,4 +19,14 @@ public class TestConfiguration { public KafkaTemplate kafkaTemplate() { return mock(KafkaTemplate.class); } + + @Bean + public ObjectMapper objectMapper(){ + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + SimpleModule module = new SimpleModule(); + module.addDeserializer(Integer.class, new CustomIntegerDeserializer()); + objectMapper.registerModule(module); + return objectMapper.setTimeZone(TimeZone.getTimeZone("UTC")); + } } \ No newline at end of file diff --git a/health-services/stock/src/test/java/org/egov/stock/helper/StockTestBuilder.java b/health-services/stock/src/test/java/org/egov/stock/helper/StockTestBuilder.java index 90960baf5a3..fd83333e42e 100644 --- a/health-services/stock/src/test/java/org/egov/stock/helper/StockTestBuilder.java +++ b/health-services/stock/src/test/java/org/egov/stock/helper/StockTestBuilder.java @@ -1,6 +1,8 @@ package org.egov.stock.helper; import org.egov.common.helper.AuditDetailsTestBuilder; +import org.egov.common.models.stock.ReferenceIdType; +import org.egov.common.models.stock.SenderReceiverType; import org.egov.common.models.stock.Stock; import org.egov.common.models.stock.TransactionReason; import org.egov.common.models.stock.TransactionType; @@ -26,13 +28,16 @@ public StockTestBuilder withStock() { this.builder .senderId("sender-id") .receiverId("receiver-id") - .productVariantId("pv-id").quantity(0) + .productVariantId("pv-id") + .quantity(1) .referenceId("reference-id") - .referenceIdType("PROJECT").rowVersion(1).tenantId("default") + .referenceIdType(ReferenceIdType.PROJECT) + .rowVersion(1) + .tenantId("default") .transactionType(TransactionType.DISPATCHED) .transactionReason(TransactionReason.RECEIVED) - .senderType("WAREHOUSE") - .receiverType("STAFF") + .senderType(SenderReceiverType.WAREHOUSE) + .receiverType(SenderReceiverType.STAFF) .hasErrors(false) .isDeleted(Boolean.FALSE) .auditDetails(AuditDetailsTestBuilder.builder().withAuditDetails().build());