├── .gitignore ├── README.md ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main └── java │ └── com │ └── gb │ └── amazonlocker │ ├── AmazonLockerMain.java │ ├── exception │ ├── LockeCodeMisMatchException.java │ ├── LockerNotFoundException.java │ ├── PackPickTimeExceededException.java │ ├── PackageSizeMappingException.java │ └── PickupCodeExpiredException.java │ ├── model │ ├── GeoLocation.java │ ├── Item.java │ ├── LocationTiming.java │ ├── Locker.java │ ├── LockerLocation.java │ ├── LockerPackage.java │ ├── LockerSize.java │ ├── LockerStatus.java │ ├── Notification.java │ ├── Order.java │ ├── Pack.java │ └── Timing.java │ ├── repository │ ├── LockerLocationRepository.java │ ├── LockerPackageRepository.java │ ├── LockerRepository.java │ ├── NotificationRepository.java │ └── OrderRepository.java │ ├── service │ ├── CustomerService.java │ ├── DeliveryService.java │ ├── LockerService.java │ ├── NotificationService.java │ ├── OrderService.java │ └── ReturnsService.java │ └── utils │ ├── IdGenerator.java │ └── SizeUtil.java └── test └── java └── com └── gb └── amazonlocker ├── TestData.java ├── repository ├── LockerLocationRepositoryTest.java ├── LockerPackageRepositoryTest.java ├── LockerRepositoryTest.java └── OrderRepositoryTest.java └── service ├── DeliveryServiceTest.java ├── LockerServiceTest.java └── NotificationServiceTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/** 6 | !**/src/test/** 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | 17 | ### IntelliJ IDEA ### 18 | .idea 19 | *.iws 20 | *.iml 21 | *.ipr 22 | out/ 23 | 24 | ### NetBeans ### 25 | /nbproject/private/ 26 | /nbbuild/ 27 | /dist/ 28 | /nbdist/ 29 | /.nb-gradle/ 30 | 31 | ### VS Code ### 32 | .vscode/ 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Design Amazon Locker 2 | 3 | What is amazon locker? 4 | When a customer orders items with amazon they may choose to deliver it to locker which customer can pick it up on the way to their home. 5 | 6 | Customers can also return items to lockers which can be picked up pickup team than pickup form home geoLocation. 7 | 8 | Locker Sizes 9 | 1. Small 10 | 2. Medium 11 | 3. Large 12 | 4. Extra Large 13 | 5. Double Extra Large 14 | 15 | Customer while ordering item can pick up their nearest geoLocation of locker where items are shipped to. 16 | Items are kept for maximum of 3 days. 17 | User gets locker code using which they can open the locker. 18 | Once the locker is closed the code is expired and cannot be open again. 19 | 20 | 1. Assign a closest locker to a person given current co-ordinates( where customer wants ) 21 | 2. After order is delivered by courier service to customer specified amazon locker, a 6 digit code will be sent to customer . 22 | 3. Item will be placed in Amazon locker for 3 days 23 | 4. After 3 days, if Item is not picked up from the locker, refund process will be initiated 24 | 5. Amazon locker will be assigned to customer based on the size of the locker ( S,M,L,XL,XXL) 25 | 6. Only items that are eligible to be put in locker can be assigned to amazon locker .i.e Not all items can be placed inside locker (like furniture can't be put inside amazon locker) 26 | 7. Access to Amazon locker will depend on Store's opening and closing time.(Since Amazon locker are placed inside stores,malls etc) 27 | 8. Items can be returned to Amazon locker as well . 28 | 9. Items that are eligible Amazon locker item, can only be returned by customer 29 | 10. Once the Door is closed. User's code will be expired. (User will not be able to open the locker now) 30 | 31 | https://www.amazon.com/primeinsider/tips/amazon-locker-qa.html 32 | Requirements Courtesy - Leetcode 33 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'java' 3 | } 4 | 5 | group 'com.gb.amazonlocker' 6 | version '1.0-SNAPSHOT' 7 | 8 | sourceCompatibility = 11 9 | targetCompatibility = 11 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | test { 15 | useJUnitPlatform() 16 | } 17 | dependencies { 18 | compileOnly 'org.projectlombok:lombok:1.18.12' 19 | compile group: 'org.apache.commons', name: 'commons-lang3', version: '3.10' 20 | annotationProcessor 'org.projectlombok:lombok:1.18.12' 21 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1' 22 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.3.1' 23 | // https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter 24 | testCompile group: 'org.mockito', name: 'mockito-junit-jupiter', version: '3.3.3' 25 | 26 | 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gopalbala/amazonlocker/50d27bb62c55f19f7dd5a43b0d899b9b987bbd2c/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 26 01:04:54 IST 2020 2 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-all.zip 3 | distributionBase=GRADLE_USER_HOME 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS='"-Xmx64m"' 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | geoLocation of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | geoLocation of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS="-Xmx64m" 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo geoLocation of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo geoLocation of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'amazonlocker' 2 | 3 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/AmazonLockerMain.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker; 2 | 3 | public class AmazonLockerMain { 4 | public static void main(String[] args) { 5 | 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/exception/LockeCodeMisMatchException.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.exception; 2 | 3 | public class LockeCodeMisMatchException extends Exception { 4 | public LockeCodeMisMatchException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/exception/LockerNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.exception; 2 | 3 | public class LockerNotFoundException extends Exception { 4 | public LockerNotFoundException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/exception/PackPickTimeExceededException.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.exception; 2 | 3 | public class PackPickTimeExceededException extends Exception { 4 | public PackPickTimeExceededException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/exception/PackageSizeMappingException.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.exception; 2 | 3 | public class PackageSizeMappingException extends Exception { 4 | public PackageSizeMappingException(String message) { 5 | super(message); 6 | System.out.println(message); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/exception/PickupCodeExpiredException.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.exception; 2 | 3 | public class PickupCodeExpiredException extends Exception { 4 | public PickupCodeExpiredException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/model/GeoLocation.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public class GeoLocation { 9 | private double latitude; 10 | private double longitude; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/model/Item.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class Item { 9 | private String id; 10 | private int quantity; 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/model/LocationTiming.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.time.DayOfWeek; 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | @Getter 11 | @Setter 12 | public class LocationTiming { 13 | private Map timingMap = new HashMap<>(); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/model/Locker.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.model; 2 | 3 | import com.gb.amazonlocker.utils.IdGenerator; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | @Getter 8 | @Setter 9 | public class Locker { 10 | private String id; 11 | private LockerSize lockerSize; 12 | private String locationId; 13 | private LockerStatus lockerStatus; 14 | 15 | public Locker(LockerSize lockerSize, String locationId) { 16 | id = IdGenerator.generateId(8); 17 | this.lockerSize = lockerSize; 18 | this.locationId = locationId; 19 | this.lockerStatus = LockerStatus.AVAILALBE; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/model/LockerLocation.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Getter 10 | @Setter 11 | public class LockerLocation { 12 | private String locationId; 13 | private List lockers = new ArrayList<>(); 14 | private GeoLocation geoLocation; 15 | private LocationTiming locationTiming; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/model/LockerPackage.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.model; 2 | 3 | import com.gb.amazonlocker.exception.PickupCodeExpiredException; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | 7 | import java.time.LocalDateTime; 8 | 9 | @Getter 10 | @Setter 11 | public class LockerPackage { 12 | final int codeValidDays = 3; 13 | private String lockerId; 14 | private String orderId; 15 | private String code; 16 | private LocalDateTime packageDeliveredTime; 17 | 18 | public boolean isValidCode(LocalDateTime currentTime) throws PickupCodeExpiredException { 19 | if (currentTime.compareTo(packageDeliveredTime) > 3) { 20 | throw new PickupCodeExpiredException("Pickup code expired."); 21 | } 22 | return true; 23 | } 24 | 25 | public boolean verifyCode(String code) { 26 | return this.code.equals(code); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/model/LockerSize.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.model; 2 | 3 | public enum LockerSize { 4 | XS, 5 | S, 6 | M, 7 | L, 8 | XL, 9 | XXL 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/model/LockerStatus.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.model; 2 | 3 | public enum LockerStatus { 4 | CLOSED, 5 | BOOKED, 6 | AVAILALBE, 7 | NOTOPENED, 8 | OPEN 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/model/Notification.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | @Getter 7 | @AllArgsConstructor 8 | public class Notification { 9 | private String customerId; 10 | private String orderId; 11 | private String lockerId; 12 | private String code; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/model/Order.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.List; 7 | 8 | @Getter 9 | @Setter 10 | public class Order { 11 | private String orderId; 12 | private List items; 13 | private GeoLocation deliveryGeoLocation; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/model/Pack.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.model; 2 | 3 | import lombok.Getter; 4 | 5 | import java.util.List; 6 | import java.util.UUID; 7 | 8 | @Getter 9 | public class Pack { 10 | private String id; 11 | private double packageSize; 12 | private String orderId; 13 | private List items; 14 | 15 | public Pack(String orderId, List items) { 16 | this.id = UUID.randomUUID().toString(); 17 | this.orderId = orderId; 18 | this.items = items; 19 | pack(); 20 | } 21 | 22 | private void pack() { 23 | packageSize = Math.random() * 10; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/model/Timing.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.model; 2 | 3 | import lombok.Getter; 4 | 5 | import java.sql.Time; 6 | 7 | @Getter 8 | public class Timing { 9 | private Time openTime; 10 | private Time closeTime; 11 | 12 | public Timing(String openTime, String closeTime) { 13 | this.openTime = Time.valueOf(openTime); 14 | this.closeTime = Time.valueOf(closeTime); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/repository/LockerLocationRepository.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.repository; 2 | 3 | import com.gb.amazonlocker.model.LockerLocation; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Optional; 8 | 9 | public class LockerLocationRepository { 10 | public static List lockerLocations = new ArrayList<>(); 11 | 12 | public static LockerLocation getLockerLocation(String locationId) { 13 | Optional lockerLocation = 14 | lockerLocations.stream() 15 | .filter(ll -> ll.getLocationId().equals(locationId)).findFirst(); 16 | if (lockerLocation.isPresent()) 17 | return lockerLocation.get(); 18 | return null; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/repository/LockerPackageRepository.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.repository; 2 | 3 | import com.gb.amazonlocker.model.LockerPackage; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Optional; 8 | 9 | public class LockerPackageRepository { 10 | public static List lockerPackages = new ArrayList<>(); 11 | 12 | public static Optional getLockerByLockerId(String lockerId) { 13 | return lockerPackages.stream() 14 | .filter(lockerPackage -> lockerPackage.getLockerId().equals(lockerId)) 15 | .findFirst(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/repository/LockerRepository.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.repository; 2 | 3 | import com.gb.amazonlocker.model.GeoLocation; 4 | import com.gb.amazonlocker.model.Locker; 5 | import com.gb.amazonlocker.model.LockerSize; 6 | import com.gb.amazonlocker.model.LockerStatus; 7 | 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.stream.Collectors; 13 | 14 | public class LockerRepository { 15 | public static List lockers; 16 | public static Map lockerMap; 17 | 18 | static { 19 | lockers = new ArrayList<>(); 20 | lockerMap = new HashMap<>(); 21 | } 22 | 23 | public static Locker getLocker(LockerSize lockerSize, GeoLocation location) { 24 | //assumption the near by locers in radius are fetched from a service 25 | 26 | List lockerList = 27 | lockers.stream() 28 | .filter(locker -> 29 | locker.getLockerStatus() == LockerStatus.AVAILALBE && 30 | locker.getLockerSize() == lockerSize) 31 | .collect(Collectors.toList()); 32 | if (lockerList != null && lockerList.size() > 0) 33 | return lockerList.get(0); 34 | return null; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/repository/NotificationRepository.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.repository; 2 | 3 | import com.gb.amazonlocker.model.Notification; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class NotificationRepository { 9 | public static Map notificationMap = new HashMap<>(); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/repository/OrderRepository.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.repository; 2 | 3 | import com.gb.amazonlocker.model.Order; 4 | 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | public class OrderRepository { 9 | public static Map orderMap = new HashMap<>(); 10 | 11 | public static Order getOrder(String orderId) { 12 | return orderMap.get(orderId); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/service/CustomerService.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.service; 2 | 3 | import java.util.UUID; 4 | 5 | public class CustomerService { 6 | public String getCustomerIdForOrder(String orderId) { 7 | return UUID.randomUUID().toString(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/service/DeliveryService.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.service; 2 | 3 | import com.gb.amazonlocker.exception.PackageSizeMappingException; 4 | import com.gb.amazonlocker.model.*; 5 | import com.gb.amazonlocker.repository.LockerPackageRepository; 6 | import com.gb.amazonlocker.utils.IdGenerator; 7 | import com.gb.amazonlocker.utils.SizeUtil; 8 | 9 | import java.util.List; 10 | 11 | public class DeliveryService { 12 | NotificationService notificationService = new NotificationService(); 13 | OrderService orderService = new OrderService(); 14 | LockerService lockerService = new LockerService(); 15 | 16 | public void deliver(String orderId) throws PackageSizeMappingException { 17 | Order order = orderService.getOrder(orderId); 18 | List items = orderService.getItemsForOrder(orderId); 19 | Pack pack = new Pack(orderId, items); 20 | LockerSize lockerSize = SizeUtil.getLockerSizeForPack(pack.getPackageSize()); 21 | Locker locker = lockerService.getLocker(lockerSize, order.getDeliveryGeoLocation()); 22 | LockerPackage lockerPackage = new LockerPackage(); 23 | lockerPackage.setOrderId(orderId); 24 | lockerPackage.setLockerId(locker.getId()); 25 | lockerPackage.setCode(IdGenerator.generateId(6)); 26 | LockerPackageRepository.lockerPackages.add(lockerPackage); 27 | locker.setLockerStatus(LockerStatus.CLOSED); 28 | notificationService.notifyCustomerOrder(lockerPackage); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/service/LockerService.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.service; 2 | 3 | import com.gb.amazonlocker.exception.LockeCodeMisMatchException; 4 | import com.gb.amazonlocker.exception.LockerNotFoundException; 5 | import com.gb.amazonlocker.exception.PackPickTimeExceededException; 6 | import com.gb.amazonlocker.exception.PickupCodeExpiredException; 7 | import com.gb.amazonlocker.model.*; 8 | import com.gb.amazonlocker.repository.LockerLocationRepository; 9 | import com.gb.amazonlocker.repository.LockerPackageRepository; 10 | import com.gb.amazonlocker.repository.LockerRepository; 11 | 12 | import java.sql.Time; 13 | import java.text.SimpleDateFormat; 14 | import java.time.LocalDateTime; 15 | import java.util.Date; 16 | import java.util.Optional; 17 | 18 | public class LockerService { 19 | 20 | public Locker findLockerIbyId(String id) { 21 | return LockerRepository.lockerMap.get(id); 22 | } 23 | 24 | public Locker getLocker(LockerSize lockerSize, GeoLocation geoLocation) { 25 | return getAvailableLocker(lockerSize, geoLocation); 26 | } 27 | 28 | public void pickFromLocker(String lockerId, 29 | String code, LocalDateTime localDateTime) throws 30 | LockerNotFoundException, LockeCodeMisMatchException, PackPickTimeExceededException, 31 | PickupCodeExpiredException { 32 | Optional lockerPackage = 33 | LockerPackageRepository.getLockerByLockerId(lockerId); 34 | if (!lockerPackage.isPresent()) 35 | throw new LockerNotFoundException("Locker with code not found"); 36 | if (!lockerPackage.get().verifyCode(code)) 37 | throw new LockeCodeMisMatchException("Locker code mismatch"); 38 | if (!lockerPackage.get().isValidCode(localDateTime)) { 39 | throw new PickupCodeExpiredException("Pickup code expired"); 40 | } 41 | Locker locker = LockerRepository.lockerMap.get(lockerId); 42 | if (canPickFromLocker(lockerId, localDateTime)) { 43 | locker.setLockerStatus(LockerStatus.AVAILALBE); 44 | lockerPackage.get().setCode(null); 45 | } else { 46 | lockerPackage.get().setCode(null); 47 | throw new PackPickTimeExceededException("Package not picked for x days"); 48 | } 49 | } 50 | 51 | private Locker getAvailableLocker(LockerSize lockerSize, 52 | GeoLocation geoLocation) { 53 | return checkAndGetAvailableLockers(lockerSize, geoLocation); 54 | } 55 | 56 | private Locker checkAndGetAvailableLockers(LockerSize lockerSize, 57 | GeoLocation geoLocation) { 58 | Locker locker = LockerRepository.getLocker(lockerSize, geoLocation); 59 | locker.setLockerStatus(LockerStatus.BOOKED); 60 | return locker; 61 | } 62 | 63 | private boolean canPickFromLocker(String lockerId, LocalDateTime localDateTime) { 64 | Locker locker = LockerRepository.lockerMap.get(lockerId); 65 | LockerLocation lockerLocation = LockerLocationRepository.getLockerLocation(locker.getLocationId()); 66 | LocationTiming locationTiming = lockerLocation.getLocationTiming(); 67 | Timing timing = locationTiming.getTimingMap().get(localDateTime.getDayOfWeek()); 68 | Time currentTime = Time.valueOf(getTimeFromDate(localDateTime)); 69 | if (currentTime.after(timing.getOpenTime()) && currentTime.before(timing.getCloseTime())) { 70 | return true; 71 | } 72 | return false; 73 | } 74 | 75 | private String getTimeFromDate(LocalDateTime localDateTime) { 76 | SimpleDateFormat localDateFormat = new SimpleDateFormat("HH:mm:ss"); 77 | String time = localDateFormat.format(new Date()); 78 | return time; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/service/NotificationService.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.service; 2 | 3 | import com.gb.amazonlocker.model.LockerPackage; 4 | import com.gb.amazonlocker.model.Notification; 5 | import com.gb.amazonlocker.repository.NotificationRepository; 6 | 7 | public class NotificationService { 8 | CustomerService customerService = new CustomerService(); 9 | 10 | public void notifyCustomerOrder(LockerPackage lockerPackage) { 11 | String customerId = customerService.getCustomerIdForOrder(lockerPackage.getOrderId()); 12 | Notification notification = new Notification(customerId, lockerPackage.getOrderId(), 13 | lockerPackage.getLockerId(), lockerPackage.getCode()); 14 | NotificationRepository.notificationMap.put(lockerPackage.getOrderId(), notification); 15 | System.out.printf("Customer %s notified for order %s " + 16 | " in locker %s with pin %s", customerId, 17 | lockerPackage.getOrderId(), 18 | lockerPackage.getLockerId(), 19 | lockerPackage.getCode() 20 | ); 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.service; 2 | 3 | import com.gb.amazonlocker.model.Item; 4 | import com.gb.amazonlocker.model.Order; 5 | import com.gb.amazonlocker.repository.OrderRepository; 6 | 7 | import java.util.List; 8 | 9 | public class OrderService { 10 | 11 | OrderRepository orderRepository = new OrderRepository(); 12 | 13 | public Order getOrder(String orderId) { 14 | return orderRepository.getOrder(orderId); 15 | } 16 | 17 | public List getItemsForOrder(String orderId) { 18 | return orderRepository.getOrder(orderId).getItems(); 19 | } 20 | 21 | public void initiateRefund(String orderId) { 22 | System.out.printf("Refund for order %s initiated", orderId); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/service/ReturnsService.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.service; 2 | 3 | import com.gb.amazonlocker.model.Item; 4 | import com.gb.amazonlocker.model.Locker; 5 | import com.gb.amazonlocker.model.LockerStatus; 6 | 7 | public class ReturnsService { 8 | 9 | public void returnItemsToLocker(Item item, Locker locker) { 10 | locker.setLockerStatus(LockerStatus.CLOSED); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/utils/IdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.utils; 2 | 3 | import org.apache.commons.lang3.RandomStringUtils; 4 | 5 | public class IdGenerator { 6 | public static String generateId(int length) { 7 | return RandomStringUtils.randomAlphanumeric(length); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/gb/amazonlocker/utils/SizeUtil.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.utils; 2 | 3 | import com.gb.amazonlocker.exception.PackageSizeMappingException; 4 | import com.gb.amazonlocker.model.LockerSize; 5 | 6 | public class SizeUtil { 7 | public static LockerSize getLockerSizeForPack(double packSize) throws 8 | PackageSizeMappingException { 9 | if (packSize < 10) { 10 | return LockerSize.XS; 11 | } else if (packSize > 10 && packSize <= 20) { 12 | return LockerSize.S; 13 | } else if (packSize > 20 && packSize <= 40) { 14 | return LockerSize.M; 15 | } else if (packSize > 40 && packSize <= 50) { 16 | return LockerSize.L; 17 | } else if (packSize > 50 && packSize <= 70) { 18 | return LockerSize.XL; 19 | } else if (packSize > 70 && packSize <= 100) { 20 | return LockerSize.XXL; 21 | } else { 22 | throw new PackageSizeMappingException("Package size more than" + 23 | " the largest available locker."); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/com/gb/amazonlocker/TestData.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker; 2 | 3 | import com.gb.amazonlocker.model.*; 4 | import com.gb.amazonlocker.utils.IdGenerator; 5 | 6 | import java.time.DayOfWeek; 7 | import java.time.LocalDateTime; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | public class TestData { 13 | 14 | public static Map lockerLocationMap = new HashMap<>(); 15 | 16 | public static void setupTest() { 17 | setupLockerLocation("RMBGBGKAIN", 18 | 12.876416, 77.595466); 19 | setupLockerLocation("VMBGBGKAIN", 20 | 12.909953, 77.601866); 21 | } 22 | 23 | public static LockerLocation setupLockerLocation(String locationId, 24 | double latitude, double longitude) { 25 | LockerLocation lockerLocation = getLockerLocation(locationId, latitude, longitude); 26 | for (int i = 0; i < 50; i++) { 27 | lockerLocation.getLockers().add(createLocker(LockerSize.XS, locationId)); 28 | } 29 | for (int i = 0; i < 50; i++) { 30 | lockerLocation.getLockers().add(createLocker(LockerSize.S, locationId)); 31 | } 32 | for (int i = 0; i < 40; i++) { 33 | lockerLocation.getLockers().add(createLocker(LockerSize.M, locationId)); 34 | } 35 | for (int i = 0; i < 30; i++) { 36 | lockerLocation.getLockers().add(createLocker(LockerSize.L, locationId)); 37 | } 38 | for (int i = 0; i < 20; i++) { 39 | lockerLocation.getLockers().add(createLocker(LockerSize.XL, locationId)); 40 | } 41 | for (int i = 0; i < 10; i++) { 42 | lockerLocation.getLockers().add(createLocker(LockerSize.XXL, locationId)); 43 | } 44 | return lockerLocation; 45 | } 46 | 47 | public static Locker createLocker(LockerSize lockerSize, String locationId) { 48 | return new Locker(lockerSize, locationId); 49 | } 50 | 51 | public static LockerLocation getLockerLocation(String locationId, 52 | double latitude, 53 | double longitude) { 54 | LockerLocation lockerLocation = new LockerLocation(); 55 | lockerLocation.setLocationId(locationId); 56 | LocationTiming locationTiming = new LocationTiming(); 57 | locationTiming.setTimingMap(getTiming()); 58 | lockerLocation.setLocationTiming(locationTiming); 59 | lockerLocation.setGeoLocation(new GeoLocation(latitude, longitude)); 60 | return lockerLocation; 61 | } 62 | 63 | public static Map getTiming() { 64 | Map timingMap = new HashMap<>(); 65 | 66 | timingMap.put(DayOfWeek.MONDAY, new Timing("9:00:00", "22:00:00")); 67 | timingMap.put(DayOfWeek.TUESDAY, new Timing("9:00:00", "22:00:00")); 68 | timingMap.put(DayOfWeek.WEDNESDAY, new Timing("9:00:00", "22:00:00")); 69 | timingMap.put(DayOfWeek.THURSDAY, new Timing("9:00:00", "22:00:00")); 70 | timingMap.put(DayOfWeek.FRIDAY, new Timing("9:00:00", "22:00:00")); 71 | timingMap.put(DayOfWeek.SATURDAY, new Timing("7:00:00", "23:00:00")); 72 | timingMap.put(DayOfWeek.SUNDAY, new Timing("7:00:00", "23:00:00")); 73 | return timingMap; 74 | } 75 | 76 | public static LockerPackage getLockerPackage() { 77 | LockerPackage lockerPackage = new LockerPackage(); 78 | LockerLocation lockerLocation = setupLockerLocation("VMBGBGKAIN", 79 | 12.909953, 77.601866); 80 | lockerPackage.setCode(IdGenerator.generateId(8)); 81 | lockerPackage.setLockerId(lockerLocation.getLockers().get(0).getId()); 82 | lockerPackage.setPackageDeliveredTime(LocalDateTime.now()); 83 | lockerPackage.setOrderId(IdGenerator.generateId(12)); 84 | lockerPackage.setCode(IdGenerator.generateId(6)); 85 | return lockerPackage; 86 | } 87 | 88 | public static Order getPhoneOrder() { 89 | Order order = new Order(); 90 | Item item = new Item(); 91 | item.setId("IPHONE11"); 92 | item.setQuantity(1); 93 | order.setOrderId(IdGenerator.generateId(16)); 94 | order.setItems(List.of(item)); 95 | order.setDeliveryGeoLocation(new GeoLocation(12.909953, 77.601866)); 96 | return order; 97 | } 98 | 99 | public static Order getHeadSetOrder() { 100 | Order order = new Order(); 101 | Item item = new Item(); 102 | item.setId("JABRAWLHS"); 103 | item.setQuantity(1); 104 | order.setOrderId(IdGenerator.generateId(16)); 105 | order.setItems(List.of(item)); 106 | order.setDeliveryGeoLocation(new GeoLocation(12.876416, 77.595466)); 107 | return order; 108 | } 109 | 110 | public static Pack getPackage() { 111 | Order order = getPhoneOrder(); 112 | Pack pack = new Pack(order.getOrderId(), order.getItems()); 113 | return pack; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/test/java/com/gb/amazonlocker/repository/LockerLocationRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.repository; 2 | 3 | import com.gb.amazonlocker.TestData; 4 | import com.gb.amazonlocker.model.LockerLocation; 5 | import org.junit.jupiter.api.Assertions; 6 | import org.junit.jupiter.api.BeforeAll; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class LockerLocationRepositoryTest { 10 | @BeforeAll 11 | public static void setup() { 12 | LockerLocationRepository.lockerLocations.add( 13 | TestData.setupLockerLocation("RMBGBGKAIN", 14 | 12.876416, 77.595466)); 15 | LockerLocationRepository.lockerLocations.add( 16 | TestData.setupLockerLocation("VMBGBGKAIN", 17 | 12.909953, 77.601866)); 18 | } 19 | 20 | @Test 21 | public void getLockerByLockerIdTest() { 22 | LockerLocation lockerLocation = LockerLocationRepository.getLockerLocation("RMBGBGKAIN"); 23 | Assertions.assertNotNull(lockerLocation); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/gb/amazonlocker/repository/LockerPackageRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.repository; 2 | 3 | import com.gb.amazonlocker.TestData; 4 | import com.gb.amazonlocker.model.LockerPackage; 5 | import org.junit.jupiter.api.BeforeAll; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import java.util.Optional; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertNotNull; 11 | 12 | public class LockerPackageRepositoryTest { 13 | @BeforeAll 14 | public static void setup() { 15 | LockerPackageRepository.lockerPackages.add(TestData.getLockerPackage()); 16 | } 17 | 18 | @Test 19 | public void shouldGetByLockerId() { 20 | String lockerId = LockerPackageRepository.lockerPackages.get(0).getLockerId(); 21 | Optional lockerPackage = 22 | LockerPackageRepository.getLockerByLockerId(lockerId); 23 | assertNotNull(lockerPackage.get()); 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/com/gb/amazonlocker/repository/LockerRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.repository; 2 | 3 | import com.gb.amazonlocker.TestData; 4 | import com.gb.amazonlocker.model.Locker; 5 | import com.gb.amazonlocker.model.LockerLocation; 6 | import org.junit.jupiter.api.BeforeAll; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertNotNull; 10 | 11 | public class LockerRepositoryTest { 12 | @BeforeAll 13 | public static void setup() { 14 | LockerLocation lockerLocation = TestData.setupLockerLocation("RMBGBGKAIN", 15 | 12.876416, 77.595466); 16 | LockerRepository.lockers.addAll(lockerLocation.getLockers()); 17 | for (Locker locker : LockerRepository.lockers) { 18 | LockerRepository.lockerMap.put(locker.getId(), locker); 19 | } 20 | } 21 | 22 | @Test 23 | public void shouldFetchLocker() { 24 | Locker locker = LockerRepository.lockerMap.get(LockerRepository.lockers.get(0).getId()); 25 | assertNotNull(locker); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/test/java/com/gb/amazonlocker/repository/OrderRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.repository; 2 | 3 | import com.gb.amazonlocker.TestData; 4 | import org.junit.jupiter.api.BeforeAll; 5 | import org.junit.jupiter.api.Test; 6 | 7 | import static org.junit.jupiter.api.Assertions.assertNotNull; 8 | 9 | public class OrderRepositoryTest { 10 | @BeforeAll 11 | public static void setup() { 12 | OrderRepository.orderMap.put("o1", TestData.getPhoneOrder()); 13 | OrderRepository.orderMap.put("o2", TestData.getHeadSetOrder()); 14 | } 15 | 16 | @Test 17 | public void shouldGetOrderById() { 18 | assertNotNull(OrderRepository.getOrder("o1")); 19 | assertNotNull(OrderRepository.getOrder("o2")); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/com/gb/amazonlocker/service/DeliveryServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.service; 2 | 3 | import com.gb.amazonlocker.TestData; 4 | import com.gb.amazonlocker.exception.PackageSizeMappingException; 5 | import com.gb.amazonlocker.model.Locker; 6 | import com.gb.amazonlocker.model.Notification; 7 | import com.gb.amazonlocker.repository.*; 8 | import org.junit.jupiter.api.BeforeAll; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import static org.junit.jupiter.api.Assertions.assertEquals; 12 | 13 | public class DeliveryServiceTest { 14 | static DeliveryService deliveryService; 15 | 16 | @BeforeAll 17 | public static void setup() { 18 | LockerLocationRepository.lockerLocations.add( 19 | TestData.setupLockerLocation("RMBGBGKAIN", 20 | 12.876416, 77.595466)); 21 | LockerLocationRepository.lockerLocations.add( 22 | TestData.setupLockerLocation("VMBGBGKAIN", 23 | 12.909953, 77.601866)); 24 | LockerPackageRepository.lockerPackages.add(TestData.getLockerPackage()); 25 | 26 | LockerRepository.lockers.addAll(LockerLocationRepository 27 | .getLockerLocation("RMBGBGKAIN").getLockers()); 28 | for (Locker locker : LockerRepository.lockers) { 29 | LockerRepository.lockerMap.put(locker.getId(), locker); 30 | } 31 | 32 | OrderRepository.orderMap.put("o1", TestData.getPhoneOrder()); 33 | OrderRepository.orderMap.put("o2", TestData.getHeadSetOrder()); 34 | deliveryService = new DeliveryService(); 35 | } 36 | 37 | @Test 38 | public void emulateDelivery() throws 39 | PackageSizeMappingException { 40 | deliveryService.deliver("o1"); 41 | Notification notification = NotificationRepository.notificationMap.get("o1"); 42 | assertEquals("o1", notification.getOrderId()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/com/gb/amazonlocker/service/LockerServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.service; 2 | 3 | import com.gb.amazonlocker.TestData; 4 | import com.gb.amazonlocker.exception.LockeCodeMisMatchException; 5 | import com.gb.amazonlocker.exception.LockerNotFoundException; 6 | import com.gb.amazonlocker.exception.PackPickTimeExceededException; 7 | import com.gb.amazonlocker.exception.PackageSizeMappingException; 8 | import com.gb.amazonlocker.model.*; 9 | import com.gb.amazonlocker.repository.*; 10 | import com.gb.amazonlocker.utils.SizeUtil; 11 | import org.junit.jupiter.api.BeforeAll; 12 | import org.junit.jupiter.api.Test; 13 | 14 | import java.time.LocalDateTime; 15 | 16 | import static org.junit.jupiter.api.Assertions.assertEquals; 17 | import static org.junit.jupiter.api.Assertions.assertNotNull; 18 | 19 | public class LockerServiceTest { 20 | static LockerService lockerService; 21 | static DeliveryService deliveryService; 22 | 23 | @BeforeAll 24 | public static void setup() { 25 | LockerLocationRepository.lockerLocations.add( 26 | TestData.setupLockerLocation("RMBGBGKAIN", 27 | 12.876416, 77.595466)); 28 | LockerLocationRepository.lockerLocations.add( 29 | TestData.setupLockerLocation("VMBGBGKAIN", 30 | 12.909953, 77.601866)); 31 | LockerPackageRepository.lockerPackages.add(TestData.getLockerPackage()); 32 | 33 | LockerRepository.lockers.addAll(LockerLocationRepository 34 | .getLockerLocation("RMBGBGKAIN").getLockers()); 35 | for (Locker locker : LockerRepository.lockers) { 36 | LockerRepository.lockerMap.put(locker.getId(), locker); 37 | } 38 | 39 | OrderRepository.orderMap.put("o1", TestData.getPhoneOrder()); 40 | OrderRepository.orderMap.put("o2", TestData.getHeadSetOrder()); 41 | lockerService = new LockerService(); 42 | deliveryService = new DeliveryService(); 43 | } 44 | 45 | @Test 46 | public void shouldReturnLocker() { 47 | String lockerId = LockerRepository.lockers.get(0).getId(); 48 | assertNotNull(lockerService.findLockerIbyId(lockerId)); 49 | } 50 | 51 | @Test 52 | public void shouldGetLocker() { 53 | Locker locker = 54 | lockerService.getLocker(LockerSize.XS, 55 | new GeoLocation(12.909953, 77.601866)); 56 | assertNotNull(locker); 57 | } 58 | 59 | @Test 60 | public void shouldGetLockerSizeForPack() throws PackageSizeMappingException { 61 | Pack pack = TestData.getPackage(); 62 | LockerSize lockerSize = SizeUtil.getLockerSizeForPack(pack.getPackageSize()); 63 | System.out.println(lockerSize); 64 | assertNotNull(lockerSize); 65 | } 66 | 67 | @Test 68 | public void emulatePickFromLocker() throws 69 | PackageSizeMappingException, LockeCodeMisMatchException, 70 | LockerNotFoundException, PackPickTimeExceededException { 71 | deliveryService.deliver("o1"); 72 | Notification notification = NotificationRepository.notificationMap.get("o1"); 73 | LockerPackage lockerPackage = 74 | LockerPackageRepository.lockerPackages.stream() 75 | .filter(lockerPackage1 -> lockerPackage1.getOrderId().equals("o1")) 76 | .findFirst().get(); 77 | lockerService.pickFromLocker(lockerPackage.getLockerId(), lockerPackage.getCode(), 78 | LocalDateTime.now()); 79 | 80 | assertEquals(LockerStatus.AVAILALBE, 81 | LockerRepository.lockerMap.get(notification.getLockerId()).getLockerStatus()); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/test/java/com/gb/amazonlocker/service/NotificationServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.gb.amazonlocker.service; 2 | 3 | import com.gb.amazonlocker.TestData; 4 | import com.gb.amazonlocker.model.Locker; 5 | import com.gb.amazonlocker.repository.*; 6 | import org.junit.jupiter.api.BeforeAll; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.junit.jupiter.api.Assertions.assertEquals; 10 | 11 | public class NotificationServiceTest { 12 | static NotificationService notificationService; 13 | 14 | @BeforeAll 15 | public static void setup() { 16 | LockerLocationRepository.lockerLocations.add( 17 | TestData.setupLockerLocation("RMBGBGKAIN", 18 | 12.876416, 77.595466)); 19 | LockerLocationRepository.lockerLocations.add( 20 | TestData.setupLockerLocation("VMBGBGKAIN", 21 | 12.909953, 77.601866)); 22 | LockerPackageRepository.lockerPackages.add(TestData.getLockerPackage()); 23 | 24 | LockerRepository.lockers.addAll(LockerLocationRepository 25 | .getLockerLocation("RMBGBGKAIN").getLockers()); 26 | for (Locker locker : LockerRepository.lockers) { 27 | LockerRepository.lockerMap.put(locker.getId(), locker); 28 | } 29 | 30 | OrderRepository.orderMap.put("o1", TestData.getPhoneOrder()); 31 | OrderRepository.orderMap.put("o2", TestData.getHeadSetOrder()); 32 | notificationService = new NotificationService(); 33 | } 34 | 35 | @Test 36 | public void emulateNotification() { 37 | notificationService.notifyCustomerOrder(TestData.getLockerPackage()); 38 | assertEquals("o1", NotificationRepository.notificationMap.get("o1").getOrderId()); 39 | } 40 | } 41 | --------------------------------------------------------------------------------