Skip to content

Commit

Permalink
[CCAP-341] Create confirmation code for family applications (#598)
Browse files Browse the repository at this point in the history
* [CCAP-341] Initial short code implementation

* [CCAP-341] Initial short code implementation

* [CCAP-341] Short code config stub

* [CCAP-341] Short code config implementation

* [CCAP-341] Short code config implementation

* [CCAP-341] Updating readme

* [CCAP-341] Updating readme, adding findByShortCode method

* [CCAP-341] Cleanup

* [CCAP-341] Cleanup

* [CCAP-314] Moving short code generation to controller (#599)

* [CCAP-314] Refactoring

* [CCAP-314] Cleaning up documentation

* [CCAP-314] Cleaning up documentation

* [CCAP-341] More tests

* [CCAP-341] More tests

* [CCAP-341] Adding prefix and suffix

* [CCAP-341] code cleanup
  • Loading branch information
cram-cfa authored Sep 18, 2024
1 parent 35a88bc commit 572a59a
Show file tree
Hide file tree
Showing 14 changed files with 1,106 additions and 524 deletions.
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Table of Contents
* [Actions](#actions)
* [Data Persistence and Defining Inputs](#data-persistence-and-defining-inputs)
* [Submission Object](#submission-object)
* [Short Code](#submission-short-code)
* [Inputs Class](#inputs-class)
* [Validating Inputs](#validating-inputs)
* [Required Inputs](#required-inputs)
Expand Down Expand Up @@ -540,6 +541,40 @@ progresses. This field is placed in the model handed to the Thymeleaf templates,
should
have access to it.

### Submission Short Code

A genericized implementation that can be used, among other things, as a unique confirmation code after
completion of the flow. An example of a 6 character, all uppercase, alphanumeric code is 8H7LP2.

The short code is accessible via `getShortCode()`. It is created by default in the `ScreenController`
after the Submission has been submitted. This can be changed via `ShortCodeConfig`'s `creationPoint`
to be generated and set after the initial creation of the Submission. It is configurable for length,
forced uppercase, character set, and creation point.

```yaml
form-flow:
short-code:
# default = 8
length: 8
# default = alphanumeric | options: alphanumeric (A-z 0-9), alpha (A-z), numeric (0-9)
type: alphanumeric
# default = true | options: true, false
uppercase: false
# default = submission | options: submission, creation
creation-point: submission
# default = null
prefix: IL-
# default = null
suffix: -APP
```

On creation of the short code, uniqueness is guaranteed. Because of that, it is incredibly important to
be sure the configuration allows for enough possible permutations in your data set. A minimum of 6
characters is recommended.

The `SubmissionRepositoryService` allows for reverse lookup of the Submission by the Short Code using
`findByShortCode`.

## Inputs Class

The inputs class's location is defined by the application using this library. Applications will need
Expand Down
24 changes: 23 additions & 1 deletion src/main/java/formflow/library/ScreenController.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import formflow.library.config.NextScreen;
import formflow.library.config.ScreenNavigationConfiguration;
import formflow.library.config.SubflowConfiguration;
import formflow.library.config.submission.ShortCodeConfig;
import formflow.library.data.FormSubmission;
import formflow.library.data.Submission;
import formflow.library.data.SubmissionRepositoryService;
Expand Down Expand Up @@ -68,6 +69,8 @@ public class ScreenController extends FormFlowController {
private final ConditionManager conditionManager;
private final ActionManager actionManager;
private final FileValidationService fileValidationService;
private final SubmissionRepositoryService submissionRepositoryService;
private final ShortCodeConfig shortCodeConfig;

public ScreenController(
List<FlowConfiguration> flowConfigurations,
Expand All @@ -79,14 +82,19 @@ public ScreenController(
ConditionManager conditionManager,
ActionManager actionManager,
FileValidationService fileValidationService,
MessageSource messageSource) {
MessageSource messageSource,
ShortCodeConfig shortCodeConfig
) {
super(submissionRepositoryService, userFileRepositoryService, flowConfigurations, formFlowConfigurationProperties,
messageSource);
this.validationService = validationService;
this.addressValidationService = addressValidationService;
this.conditionManager = conditionManager;
this.actionManager = actionManager;
this.fileValidationService = fileValidationService;
this.submissionRepositoryService = submissionRepositoryService;
this.shortCodeConfig = shortCodeConfig;

log.info("Screen Controller Created!");
}

Expand Down Expand Up @@ -339,10 +347,19 @@ private ModelAndView handlePost(
)
);
submission.setSubmittedAt(OffsetDateTime.now());

if (shortCodeConfig.isCreateShortCodeAtSubmission()) {
submissionRepositoryService.generateAndSetUniqueShortCode(submission);
}
}

actionManager.handleBeforeSaveAction(currentScreen, submission);
submission = saveToRepository(submission);

if (shortCodeConfig.isCreateShortCodeAtCreation()) {
submissionRepositoryService.generateAndSetUniqueShortCode(submission);
}

setSubmissionInSession(httpSession, submission, flow);
actionManager.handleAfterSaveAction(currentScreen, submission);

Expand Down Expand Up @@ -522,6 +539,11 @@ RedirectView postSubflowScreen(

actionManager.handleBeforeSaveAction(currentScreen, submission, iterationUuid);
submission = saveToRepository(submission, subflowName);

if (shortCodeConfig.isCreateShortCodeAtCreation()) {
submissionRepositoryService.generateAndSetUniqueShortCode(submission);
}

setSubmissionInSession(httpSession, submission, flow);
actionManager.handleAfterSaveAction(currentScreen, submission, iterationUuid);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package formflow.library.config.submission;

import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

@Getter
@Configuration
public class ShortCodeConfig {

public enum ShortCodeType {
alphanumeric, alpha, numeric;
}

public enum ShortCodeCreationPoint {
creation, submission
}

@Value("${form-flow.short-code.length:6}")
private int codeLength;

@Value("${form-flow.short-code.type:alphanumeric}")
private ShortCodeType codeType;

@Value("${form-flow.short-code.uppercase: true}")
private boolean uppercase;

@Value("${form-flow.short-code.creation-point:submission}")
private ShortCodeCreationPoint creationPoint;

@Value("${form-flow.short-code.prefix:#{null}}")
private String prefix;

@Value("${form-flow.short-code.suffix:#{null}}")
private String suffix;

public boolean isCreateShortCodeAtCreation() {
return ShortCodeCreationPoint.creation.equals(creationPoint);
}

public boolean isCreateShortCodeAtSubmission() {
return ShortCodeCreationPoint.submission.equals(creationPoint);
}
}
18 changes: 15 additions & 3 deletions src/main/java/formflow/library/data/Submission.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,15 @@
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.Optional;

import java.util.UUID;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
Expand Down Expand Up @@ -76,6 +75,10 @@ public class Submission {
@Column(name = "submitted_at")
private OffsetDateTime submittedAt;

@Setter(AccessLevel.NONE)
@Column(name = "short_code")
private String shortCode;

/**
* The key name for the field in an iteration's data that holds the status of completion for the iteration.
*/
Expand Down Expand Up @@ -220,6 +223,8 @@ public static Submission copySubmission(Submission origSubmission) {
newSubmission.setSubmittedAt(origSubmission.getSubmittedAt());
newSubmission.setId(origSubmission.getId());

newSubmission.setShortCode(origSubmission.getShortCode());

// deep copy the subflows and any lists
newSubmission.setInputData(copyMap(origSubmission.getInputData()));
return newSubmission;
Expand Down Expand Up @@ -251,6 +256,13 @@ private static Map<String, Object> copyMap(Map<String, Object> origMap) {
return result;
}

public void setShortCode(String shortCode) {
if (this.shortCode != null) {
throw new UnsupportedOperationException("Cannot change shortCode for an existing submission");
}
this.shortCode = shortCode;
}

@Override
public boolean equals(Object o) {
if (this == o) {
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/formflow/library/data/SubmissionRepository.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package formflow.library.data;

import java.util.Optional;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
Expand All @@ -10,4 +11,7 @@
@Repository
public interface SubmissionRepository extends JpaRepository<Submission, UUID> {

boolean existsByShortCode(String shortCode);

Optional<Submission> findSubmissionByShortCode(String shortCode);
}
Loading

0 comments on commit 572a59a

Please sign in to comment.