Skip to content

Commit

Permalink
avniproject/avni-client#1538 | Generate and sync identifier assignmen…
Browse files Browse the repository at this point in the history
…ts based on device_id
  • Loading branch information
1t5j0y committed Dec 5, 2024
1 parent 10722d4 commit ff5a968
Show file tree
Hide file tree
Showing 15 changed files with 91 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
@Repository
@RepositoryRestResource(collectionResourceRel = "identifierAssignment", path = "identifierAssignment")
public interface IdentifierAssignmentRepository extends TransactionalDataRepository<IdentifierAssignment>, FindByLastModifiedDateTime<IdentifierAssignment> {
Page<IdentifierAssignment> findByAssignedToAndLastModifiedDateTimeGreaterThanAndIsVoidedFalseAndIndividualIsNullAndProgramEnrolmentIsNullOrderByAssignmentOrderAsc(User currentUser, Date lastModifiedDateTime, Pageable pageable);
Page<IdentifierAssignment> findByAssignedToAndLastModifiedDateTimeGreaterThanAndIsVoidedFalseAndIndividualIsNullAndProgramEnrolmentIsNullAndDeviceIdEqualsOrderByAssignmentOrderAsc(User currentUser, Date lastModifiedDateTime, String deviceId, Pageable pageable);

Slice<IdentifierAssignment> findSliceByAssignedToAndLastModifiedDateTimeGreaterThanAndIsVoidedFalseAndIndividualIsNullAndProgramEnrolmentIsNullOrderByAssignmentOrderAsc(User currentUser, Date lastModifiedDateTime, Pageable pageable);
Slice<IdentifierAssignment> findSliceByAssignedToAndLastModifiedDateTimeGreaterThanAndIsVoidedFalseAndIndividualIsNullAndProgramEnrolmentIsNullAndDeviceIdEqualsOrderByAssignmentOrderAsc(User currentUser, Date lastModifiedDateTime, String deviceId, Pageable pageable);

Integer countIdentifierAssignmentByIdentifierSourceEqualsAndAndAssignedToEqualsAndIndividualIsNullAndProgramEnrolmentIsNullAndUsedIsFalse(IdentifierSource identifierSource, User assignedTo);
Integer countIdentifierAssignmentByIdentifierSourceEqualsAndAssignedToEqualsAndIndividualIsNullAndProgramEnrolmentIsNullAndUsedIsFalseAndDeviceIdEquals(IdentifierSource identifierSource, User assignedTo, String deviceId);

boolean existsByAssignedToAndLastModifiedDateTimeGreaterThanAndIsVoidedFalseAndIndividualIsNullAndProgramEnrolmentIsNull(User currentUser, Date lastModifiedDateTime);
boolean existsByAssignedToAndLastModifiedDateTimeGreaterThanAndIsVoidedFalseAndIndividualIsNullAndProgramEnrolmentIsNullAndDeviceIdEquals(User currentUser, Date lastModifiedDateTime, String deviceId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,19 @@ public class IdentifierAssignment extends OrganisationAwareEntity {
@NotNull
private boolean used;

private String deviceId;

public IdentifierAssignment() {
super();
}

public IdentifierAssignment(IdentifierSource identifierSource, String identifier, Long assignmentOrder, User assignedTo) {
public IdentifierAssignment(IdentifierSource identifierSource, String identifier, Long assignmentOrder, User assignedTo, String deviceId) {
this();
this.identifierSource = identifierSource;
this.identifier = identifier;
this.assignmentOrder = assignmentOrder;
this.assignedTo = assignedTo;
this.deviceId = deviceId;
}

public IdentifierSource getIdentifierSource() {
Expand Down Expand Up @@ -104,4 +107,12 @@ public boolean isUsed() {
public void setUsed(boolean used) {
this.used = used;
}

public String getDeviceId() {
return deviceId;
}

public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
import org.avni.server.domain.User;

public interface IdentifierGenerator {
void generateIdentifiers(IdentifierSource identifierSource, User user);
void generateIdentifiers(IdentifierSource identifierSource, User user, String deviceId);
IdentifierAssignment generateSingleIdentifier(IdentifierSource identifierSource, User user);
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,38 +41,40 @@ public PrefixedUserPoolBasedIdentifierGenerator(IdentifierAssignmentRepository i
}

@Transactional
public void generateIdentifiers(IdentifierSource identifierSource, User user, String prefix) {
public void generateIdentifiers(IdentifierSource identifierSource, User user, String prefix, String deviceId) {
List<IdentifierUserAssignment> identifierUserAssignments = identifierUserAssignmentRepository.getAllNonExhaustedUserAssignments(user, identifierSource);
Long batchGenerationSize = identifierSource.getBatchGenerationSize();
NextIdentifierUserAssignment nextIdentifierUserAssignment = new NextIdentifierUserAssignment(identifierUserAssignments, batchGenerationSize);
List<IdentifierAssignment> generatedIdentifiers = new ArrayList<>();

while(nextIdentifierUserAssignment.hasNext()) {
IdentifierUserAssignment identifierUserAssignment = nextIdentifierUserAssignment.next();
generatedIdentifiers.add(assignNextIdentifier(identifierUserAssignment, prefix));
generatedIdentifiers.add(assignNextIdentifier(identifierUserAssignment, prefix, deviceId));
}

identifierUserAssignmentRepository.saveAll(identifierUserAssignments);
identifierAssignmentRepository.saveAll(generatedIdentifiers);
}

@Transactional
public IdentifierAssignment generateSingleIdentifier(IdentifierSource identifierSource, User user, String prefix) {
public IdentifierAssignment generateSingleIdentifier(IdentifierSource identifierSource, User user, String prefix, String deviceId) {
List<IdentifierUserAssignment> identifierUserAssignments = identifierUserAssignmentRepository.getAllNonExhaustedUserAssignments(user, identifierSource);
NextIdentifierUserAssignment nextIdentifierUserAssignment = new NextIdentifierUserAssignment(identifierUserAssignments, 1L);
List<IdentifierAssignment> generatedIdentifiers = new ArrayList<>();

while(nextIdentifierUserAssignment.hasNext()) {
IdentifierUserAssignment identifierUserAssignment = nextIdentifierUserAssignment.next();
generatedIdentifiers.add(assignNextIdentifier(identifierUserAssignment, prefix));
IdentifierAssignment identifierAssignment = assignNextIdentifier(identifierUserAssignment, prefix, deviceId);
identifierAssignment.setUsed(true);
generatedIdentifiers.add(identifierAssignment);
}

identifierUserAssignmentRepository.saveAll(identifierUserAssignments);
identifierAssignmentRepository.saveAll(generatedIdentifiers);
return generatedIdentifiers.stream().findFirst().orElse(null);
}

private IdentifierAssignment assignNextIdentifier(IdentifierUserAssignment identifierUserAssignment, String prefix) {
private IdentifierAssignment assignNextIdentifier(IdentifierUserAssignment identifierUserAssignment, String prefix, String deviceId) {
String lastAssignedIdentifier = identifierUserAssignment.getLastAssignedIdentifier();
IdentifierSource identifierSource = identifierUserAssignment.getIdentifierSource();
long newIdentifierOrder; String newIdentifierStr, newIdentifierStrWithPrefix;
Expand All @@ -92,7 +94,7 @@ private IdentifierAssignment assignNextIdentifier(IdentifierUserAssignment ident

identifierUserAssignment.setLastAssignedIdentifier(newIdentifierStrWithPrefix);

IdentifierAssignment identifierAssignment = new IdentifierAssignment(identifierSource, newIdentifierStrWithPrefix, newIdentifierOrder, identifierUserAssignment.getAssignedTo());
IdentifierAssignment identifierAssignment = new IdentifierAssignment(identifierSource, newIdentifierStrWithPrefix, newIdentifierOrder, identifierUserAssignment.getAssignedTo(), deviceId);
identifierAssignment.assignUUID();
return identifierAssignment;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import static org.avni.server.service.DeviceAwareService.WEB_DEVICE_ID;

@Service
@Qualifier("userBasedIdentifierGenerator")
public class UserBasedIdentifierGenerator implements IdentifierGenerator {
Expand All @@ -18,15 +20,15 @@ public UserBasedIdentifierGenerator(PrefixedUserPoolBasedIdentifierGenerator pre
}

@Override
public void generateIdentifiers(IdentifierSource identifierSource, User user) {
public void generateIdentifiers(IdentifierSource identifierSource, User user, String deviceId) {
String idPrefix = getIdPrefix(user);
prefixedUserPoolBasedIdentifierGenerator.generateIdentifiers(identifierSource, user, idPrefix);
prefixedUserPoolBasedIdentifierGenerator.generateIdentifiers(identifierSource, user, idPrefix, deviceId);
}

@Override
public IdentifierAssignment generateSingleIdentifier(IdentifierSource identifierSource, User user) {
String idPrefix = getIdPrefix(user);
IdentifierAssignment identifierAssignment = prefixedUserPoolBasedIdentifierGenerator.generateSingleIdentifier(identifierSource, user, idPrefix);
IdentifierAssignment identifierAssignment = prefixedUserPoolBasedIdentifierGenerator.generateSingleIdentifier(identifierSource, user, idPrefix, WEB_DEVICE_ID);
return identifierAssignment;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

import javax.transaction.Transactional;

import static org.avni.server.service.DeviceAwareService.WEB_DEVICE_ID;


@Service
@Qualifier("userPoolBasedIdentifierGenerator")
Expand All @@ -23,14 +25,14 @@ public UserPoolBasedIdentifierGenerator(PrefixedUserPoolBasedIdentifierGenerator

@Override
@Transactional
public void generateIdentifiers(IdentifierSource identifierSource, User user) {
public void generateIdentifiers(IdentifierSource identifierSource, User user, String deviceId) {
String prefix = identifierSource.getPrefix();
prefixedUserPoolBasedIdentifierGenerator.generateIdentifiers(identifierSource, user, prefix);
prefixedUserPoolBasedIdentifierGenerator.generateIdentifiers(identifierSource, user, prefix, deviceId);
}

@Override
public IdentifierAssignment generateSingleIdentifier(IdentifierSource identifierSource, User user) {
String prefix = identifierSource.getPrefix();
return prefixedUserPoolBasedIdentifierGenerator.generateSingleIdentifier(identifierSource, user, prefix);
return prefixedUserPoolBasedIdentifierGenerator.generateSingleIdentifier(identifierSource, user, prefix, WEB_DEVICE_ID);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.avni.server.service;

import org.joda.time.DateTime;

public interface DeviceAwareService {
String WEB_DEVICE_ID = "web";

boolean isSyncRequiredForDevice(DateTime lastModifiedDateTime, String deviceId);

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import java.util.stream.Collectors;

@Service
public class IdentifierAssignmentService implements NonScopeAwareService {
public class IdentifierAssignmentService implements DeviceAwareService {

private IdentifierSourceRepository identifierSourceRepository;

Expand All @@ -38,18 +38,18 @@ public IdentifierAssignmentService(IdentifierSourceRepository identifierSourceRe


@Transactional
public void generateIdentifiersIfNecessary(User user) {
public void generateIdentifiersIfNecessary(User user, String deviceId) {
List<IdentifierSource> allAuthorisedIdentifierSources = identifierSourceRepository.getAllAuthorisedIdentifierSources(user.getCatchment());
for (IdentifierSource identifierSource : allAuthorisedIdentifierSources) {
generateIdentifiersIfNecessary(user, identifierSource);
generateIdentifiersIfNecessary(user, identifierSource, deviceId);
}
}

@Transactional
public void generateIdentifiersIfNecessary(User user, IdentifierSource identifierSource) {
if (shouldGenerateIdentifiers(user, identifierSource)) {
public void generateIdentifiersIfNecessary(User user, IdentifierSource identifierSource, String deviceId) {
if (shouldGenerateIdentifiers(user, identifierSource, deviceId)) {
IdentifierGenerator identifierGenerator = context.getBean(identifierSource.getType().name(), IdentifierGenerator.class);
identifierGenerator.generateIdentifiers(identifierSource, user);
identifierGenerator.generateIdentifiers(identifierSource, user, deviceId);
}
}

Expand All @@ -65,15 +65,14 @@ public List<IdentifierAssignment> generateIdentifiersForAForm(Form form, User us
}).collect(Collectors.toList());
}

private boolean shouldGenerateIdentifiers(User user, IdentifierSource identifierSource) {
Integer spareIdentifierAssignments = identifierAssignmentRepository.countIdentifierAssignmentByIdentifierSourceEqualsAndAndAssignedToEqualsAndIndividualIsNullAndProgramEnrolmentIsNullAndUsedIsFalse(identifierSource, user);
private boolean shouldGenerateIdentifiers(User user, IdentifierSource identifierSource, String deviceId) {
Integer spareIdentifierAssignments = identifierAssignmentRepository.countIdentifierAssignmentByIdentifierSourceEqualsAndAssignedToEqualsAndIndividualIsNullAndProgramEnrolmentIsNullAndUsedIsFalseAndDeviceIdEquals(identifierSource, user, deviceId);
return spareIdentifierAssignments < identifierSource.getMinimumBalance();
}

@Override
public boolean isNonScopeEntityChanged(DateTime lastModifiedDateTime) {
public boolean isSyncRequiredForDevice(DateTime lastModifiedDateTime, String deviceId) {
User user = UserContextHolder.getUserContext().getUser();
this.generateIdentifiersIfNecessary(user);
return identifierAssignmentRepository.existsByAssignedToAndLastModifiedDateTimeGreaterThanAndIsVoidedFalseAndIndividualIsNullAndProgramEnrolmentIsNull(user, CHSEntity.toDate(lastModifiedDateTime));
}
this.generateIdentifiersIfNecessary(user, deviceId);
return identifierAssignmentRepository.existsByAssignedToAndLastModifiedDateTimeGreaterThanAndIsVoidedFalseAndIndividualIsNullAndProgramEnrolmentIsNullAndDeviceIdEquals(user, CHSEntity.toDate(lastModifiedDateTime), deviceId); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,23 +60,25 @@ public IdentifierAssignmentController(IdentifierAssignmentRepository identifierA
@Transactional
public PagedResources<Resource<IdentifierAssignment>> get(
@RequestParam("lastModifiedDateTime") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) DateTime lastModifiedDateTime,
@RequestParam(value = "deviceId", required = false) String deviceId,
Pageable pageable) {
User currentUser = userService.getCurrentUser();
identifierAssignmentService.generateIdentifiersIfNecessary(currentUser);
identifierAssignmentService.generateIdentifiersIfNecessary(currentUser, deviceId);

return wrap(identifierAssignmentRepository.findByAssignedToAndLastModifiedDateTimeGreaterThanAndIsVoidedFalseAndIndividualIsNullAndProgramEnrolmentIsNullOrderByAssignmentOrderAsc(currentUser, CHSEntity.toDate(lastModifiedDateTime), pageable));
return wrap(identifierAssignmentRepository.findByAssignedToAndLastModifiedDateTimeGreaterThanAndIsVoidedFalseAndIndividualIsNullAndProgramEnrolmentIsNullAndDeviceIdEqualsOrderByAssignmentOrderAsc(currentUser, CHSEntity.toDate(lastModifiedDateTime), deviceId, pageable));
}

@RequestMapping(value = "/identifierAssignment/v2", method = RequestMethod.GET)
@PreAuthorize(value = "hasAnyAuthority('user')")
@Transactional
public SlicedResources<Resource<IdentifierAssignment>> getAsSlice(
@RequestParam("lastModifiedDateTime") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) DateTime lastModifiedDateTime,
@RequestParam(value = "deviceId", required = false) String deviceId,
Pageable pageable) {
User currentUser = userService.getCurrentUser();
identifierAssignmentService.generateIdentifiersIfNecessary(currentUser);
identifierAssignmentService.generateIdentifiersIfNecessary(currentUser, deviceId);

return wrap(identifierAssignmentRepository.findSliceByAssignedToAndLastModifiedDateTimeGreaterThanAndIsVoidedFalseAndIndividualIsNullAndProgramEnrolmentIsNullOrderByAssignmentOrderAsc(currentUser, CHSEntity.toDate(lastModifiedDateTime), pageable));
return wrap(identifierAssignmentRepository.findSliceByAssignedToAndLastModifiedDateTimeGreaterThanAndIsVoidedFalseAndIndividualIsNullAndProgramEnrolmentIsNullAndDeviceIdEqualsOrderByAssignmentOrderAsc(currentUser, CHSEntity.toDate(lastModifiedDateTime), deviceId, pageable));
}

@RequestMapping(value = "/identifierAssignments", method = RequestMethod.POST)
Expand Down
Loading

0 comments on commit ff5a968

Please sign in to comment.