Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added HR tab for canned reports using ETL #68

Open
wants to merge 27 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
129adb7
added new endpoints for hr analytics using org schema - syncFailures …
Aug 1, 2023
37a9040
avniproject/avniproduct#1334 , AvinashRamachandruni/avni-etl | update…
ak2502 Aug 1, 2023
4f762d4
avniproject#1334 | updated userSyncStatus endpoint and verified working
ak2502 Aug 1, 2023
fdd4baf
Merge branch 'main' of https://github.com/AvinashRamachandruni/avni-etl
ak2502 Aug 1, 2023
911cab2
avniproject/avni-product#1334 | updated userSyncStatus endpoint and v…
ak2502 Aug 1, 2023
db64cf2
Merge branch 'main' of https://github.com/AvinashRamachandruni/avni-etl
ak2502 Aug 1, 2023
5bc55bb
Merge remote-tracking branch 'upstream/main'
ak2502 Aug 2, 2023
96bdfa4
Added 3 endpoints for hr tab analytics that can pull data from org sc…
Aug 3, 2023
81be492
avniproject/avni-product#1334 | adding rest of the endpoints for HR tab
ak2502 Aug 3, 2023
49db7a5
avniproject/avni-product#1334 | Joda issue fixed
ak2502 Aug 14, 2023
689c7aa
avniproject/avni-product#1334 | generateUserActivity query updated ac…
ak2502 Aug 17, 2023
8b221c0
avniproject/avni-product#1334 | modified generateCompletedVisitsOnTim…
ak2502 Aug 18, 2023
49f17da
avniproject/avni-product#1334 | modified generateUserCancellingMostVi…
ak2502 Aug 18, 2023
9446189
Merge branch 'main' of https://github.com/avniproject/avni-etl
ak2502 Aug 21, 2023
724ca9a
avniproject/avni-product#1334 | adding analytics_user in ReportContro…
ak2502 Aug 21, 2023
ea60a48
avniproject/avni-product#1334 | Sync telemetry - Latest Syncs endpoin…
ak2502 Aug 21, 2023
cb0aef0
avniproject/avni-product#1334 | modified code with string template
ak2502 Aug 22, 2023
75be325
avniproject/avni-product#1334 | removed empty ReportService class
ak2502 Aug 22, 2023
f0f40aa
avniproject/avni-product#1334 | summaryTable endpoint added in Activi…
ak2502 Aug 23, 2023
5f78858
avniproject/avni-product#1334 | added endpoint for median sync time f…
ak2502 Aug 24, 2023
b532ca6
avniproject/avni-product#1334 | modified 'median sync-time table' to …
ak2502 Sep 4, 2023
fc21afd
removed comment
ak2502 Sep 4, 2023
0fdb0c4
log used for reference removed
ak2502 Sep 7, 2023
bbda0f2
avniproject/avni-product#1334 | added suggested changes:
ak2502 Sep 16, 2023
a5af384
avniproject/avni-product#1334 | added schemaName directly into Report…
ak2502 Sep 16, 2023
abd284d
avniproject/avni-product#1334 | removed userIds from ReportController
ak2502 Sep 16, 2023
2a03014
avniproject/avni-product#1334 | removed userIds from ReportController
ak2502 Sep 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ dependencies {
implementation 'org.keycloak:keycloak-admin-client:21.0.2'
implementation 'org.antlr:ST4:4.3.4'
implementation 'org.hibernate:hibernate-validator:7.0.5.Final'
implementation "joda-time:joda-time:2.9.4"
implementation 'com.fasterxml.jackson.core:jackson-databind:2.12.6'
implementation 'com.fasterxml.jackson.core:jackson-core:2.12.6'
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.12.6'
implementation 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.12.6'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.12.6'
}

tasks.named('test') {
Expand Down
117 changes: 117 additions & 0 deletions src/main/java/org/avniproject/etl/controller/ReportController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package org.avniproject.etl.controller;

import org.avniproject.etl.dto.AggregateReportResult;
import org.avniproject.etl.dto.UserActivityDTO;
import org.avniproject.etl.repository.ReportRepository;
import org.avniproject.etl.util.ReportUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class ReportController {

private final ReportRepository reportRepository;
private final ReportUtil reportUtil;

@Autowired
public ReportController(ReportRepository reportRepository, ReportUtil reportUtil) {
this.reportRepository = reportRepository;
this.reportUtil = reportUtil;
}

@PreAuthorize("hasAnyAuthority('analytics_user')")
@RequestMapping(value = "/report/aggregate/summaryTable", method = RequestMethod.GET)
public List<UserActivityDTO> getSummaryTable(){
return reportRepository.generateSummaryTable();
}

@PreAuthorize("hasAnyAuthority('analytics_user')")
@RequestMapping(value = "report/hr/userActivity", method = RequestMethod.GET)
public List<UserActivityDTO> getUserActivity(@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate){
return reportRepository.generateUserActivity(
reportUtil.getDateDynamicWhere(startDate, endDate, "registration_date"),
reportUtil.getDateDynamicWhere(startDate, endDate, "encounter_date_time"),
reportUtil.getDateDynamicWhere(startDate, endDate, "enrolment_date_time"));
}

@PreAuthorize("hasAnyAuthority('analytics_user')")
@RequestMapping(value = "/report/hr/syncFailures",method = RequestMethod.GET)
public List<UserActivityDTO> getUserWiseSyncFailures(@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate){
return reportRepository.generateUserSyncFailures(
reportUtil.getDateDynamicWhere(startDate, endDate, "st.sync_start_time")
);
}

@PreAuthorize("hasAnyAuthority('analytics_user')")
@RequestMapping(value = "/report/hr/deviceModels", method = RequestMethod.GET)
public List<AggregateReportResult> getUserWiseDeviceModels() {

return reportRepository.generateUserDeviceModels();
}

@PreAuthorize("hasAnyAuthority('analytics_user')")
@RequestMapping(value = "/report/hr/appVersions", method = RequestMethod.GET)
public List<AggregateReportResult> getUserWiseAppVersions() {

return reportRepository.generateUserAppVersions();
}

@PreAuthorize("hasAnyAuthority('analytics_user')")
@RequestMapping(value = "/report/hr/userDetails", method = RequestMethod.GET)
public List<UserActivityDTO> getUserDetails() {

return reportRepository.generateUserDetails();
}

@PreAuthorize("hasAnyAuthority('analytics_user')")
@RequestMapping(value = "/report/hr/latestSyncs", method = RequestMethod.GET)
public List<UserActivityDTO> getLatestSyncs(@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate) {

return reportRepository.generateLatestSyncs(
reportUtil.getDateDynamicWhere(startDate, endDate, "st.sync_end_time"));
}

@PreAuthorize("hasAnyAuthority('analytics_user')")
@RequestMapping(value = "/report/hr/medianSync", method = RequestMethod.GET)
public List<UserActivityDTO> getMedianSync(@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate) {

return reportRepository.generateMedianSync(
reportUtil.getDateSeries(startDate, endDate));
}

@PreAuthorize("hasAnyAuthority('analytics_user')")
@RequestMapping(value = "/report/hr/championUsers", method = RequestMethod.GET)
public List<AggregateReportResult> getChampionUsers(@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate) {
return reportRepository.generateCompletedVisitsOnTimeByProportion(
">= 0.5",
reportUtil.getDateDynamicWhere(startDate, endDate, "encounter_date_time"));
}

@PreAuthorize("hasAnyAuthority('analytics_user')")
@RequestMapping(value = "/report/hr/nonPerformingUsers", method = RequestMethod.GET)
public List<AggregateReportResult> getNonPerformingUsers(@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate) {
return reportRepository.generateCompletedVisitsOnTimeByProportion(
"<= 0.5",
reportUtil.getDateDynamicWhere(startDate, endDate, "encounter_date_time"));
}

@PreAuthorize("hasAnyAuthority('analytics_user')")
@RequestMapping(value = "/report/hr/mostCancelled", method = RequestMethod.GET)
public List<AggregateReportResult> getUsersCancellingMostVisits(@RequestParam(value = "startDate", required = false) String startDate,
@RequestParam(value = "endDate", required = false) String endDate) {
return reportRepository.generateUserCancellingMostVisits(
reportUtil.getDateDynamicWhere(startDate, endDate, "encounter_date_time"));
}


}

Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,54 @@ public List<TableMetadata> getAllSubjectTables() {
return tableMetadata.stream().filter(TableMetadata::isSubjectTable).toList();
}

public List<String> getAllSubjectTableNames() {
List<TableMetadata> subjectTables = getAllSubjectTables();
List<String> subjectTableNames = new ArrayList<>();
for(TableMetadata subject : subjectTables){
subjectTableNames.add(subject.getName());
}
return subjectTableNames;
}

public List<TableMetadata> getAllProgramEnrolmentTables() {
return tableMetadata.stream().filter(table -> table.getType() == TableMetadata.Type.ProgramEnrolment).toList();
}

public List<String> getAllProgramEnrolmentTableNames() {
List<TableMetadata> programEnrolmentTables = getAllProgramEnrolmentTables();
List<String> programEnrolmentTableNames = new ArrayList<>();
for(TableMetadata programEnrolment : programEnrolmentTables){
programEnrolmentTableNames.add(programEnrolment.getName());
}
return programEnrolmentTableNames;
}

public List<TableMetadata> getAllProgramEncounterTables() {
return tableMetadata.stream().filter(table -> table.getType() == TableMetadata.Type.ProgramEncounter).toList();
}

public List<String> getAllProgramEncounterTableNames() {
List<TableMetadata> programEncounterTables = getAllProgramEncounterTables();
List<String> programEncounterTableNames = new ArrayList<>();
for(TableMetadata programEncounter : programEncounterTables){
programEncounterTableNames.add(programEncounter.getName());
}
return programEncounterTableNames;
}

public List<TableMetadata> getAllEncounterTables() {
return tableMetadata.stream().filter(table -> table.getType() == TableMetadata.Type.Encounter).toList();
}

public List<String> getAllEncounterTableNames() {
List<TableMetadata> encounterTables = getAllEncounterTables();
List<String> encounterTableNames = new ArrayList<>();
for(TableMetadata encounter : encounterTables){
encounterTableNames.add(encounter.getName());
}
return encounterTableNames;
}

private List<Diff> findChanges(SchemaMetadata currentSchema, TableMetadata newTable) {
List<Diff> diffs = new ArrayList<>();
Optional<TableMetadata> optionalMatchingTable = currentSchema.findMatchingTable(newTable);
Expand Down
31 changes: 31 additions & 0 deletions src/main/java/org/avniproject/etl/dto/AggregateReportResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.avniproject.etl.dto;

public class AggregateReportResult {
private String label;
private Long value;
private String id;

public String getLabel() {
return label;
}

public void setLabel(String label) {
this.label = label;
}

public Long getValue() {
return value;
}

public void setValue(Long value) {
this.value = value;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}
}
169 changes: 169 additions & 0 deletions src/main/java/org/avniproject/etl/dto/UserActivityDTO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package org.avniproject.etl.dto;

import org.joda.time.DateTime;

public class UserActivityDTO {

private String tableName;
private String tableType;
private String userName;
private Long id;
private Long registrationCount;
private Long programEnrolmentCount;
private Long programEncounterCount;
private Long generalEncounterCount;
private Long count;
private String androidVersion;
private String appVersion;
private String deviceModel;
private String syncStatus;
private String syncSource;
private DateTime syncStart;
private DateTime syncEnd;
private DateTime lastSuccessfulSync;
private String medianSync;

public String getTableName() {
return tableName;
}

public void setTableName(String tableName) {
this.tableName = tableName;
}

public String getTableType() {
return tableType;
}

public void setTableType(String tableType) {
this.tableType = tableType;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public Long getRegistrationCount() {
return registrationCount;
}

public void setRegistrationCount(Long registrationCount) {
this.registrationCount = registrationCount;
}

public Long getProgramEnrolmentCount() {
return programEnrolmentCount;
}

public void setProgramEnrolmentCount(Long programEnrolmentCount) {
this.programEnrolmentCount = programEnrolmentCount;
}

public Long getProgramEncounterCount() {
return programEncounterCount;
}

public void setProgramEncounterCount(Long programEncounterCount) {
this.programEncounterCount = programEncounterCount;
}

public Long getGeneralEncounterCount() {
return generalEncounterCount;
}

public void setGeneralEncounterCount(Long generalEncounterCount) {
this.generalEncounterCount = generalEncounterCount;
}

public Long getCount() {
return count;
}

public void setCount(Long count) {
this.count = count;
}

public String getAndroidVersion() {
return androidVersion;
}

public void setAndroidVersion(String androidVersion) {
this.androidVersion = androidVersion;
}

public String getAppVersion() {
return appVersion;
}

public void setAppVersion(String appVersion) {
this.appVersion = appVersion;
}

public String getDeviceModel() {
return deviceModel;
}

public void setDeviceModel(String deviceModel) {
this.deviceModel = deviceModel;
}

public DateTime getLastSuccessfulSync() {
return lastSuccessfulSync;
}

public void setLastSuccessfulSync(DateTime lastSuccessfulSync) {
this.lastSuccessfulSync = lastSuccessfulSync;
}

public DateTime getSyncStart() {
return syncStart;
}

public void setSyncStart(DateTime syncStart) {
this.syncStart = syncStart;
}

public DateTime getSyncEnd() {
return syncEnd;
}

public void setSyncEnd(DateTime syncEnd) {
this.syncEnd = syncEnd;
}

public String getSyncStatus() {
return syncStatus;
}

public void setSyncStatus(String syncStatus) {
this.syncStatus = syncStatus;
}

public String getSyncSource() {
return syncSource;
}

public void setSyncSource(String syncSource) {
this.syncSource = syncSource;
}

public String getMedianSync() {
return medianSync;
}

public void setMedianSync(String medianSync) {
this.medianSync = medianSync;
}
}
Loading