2018-05-11 09:07:54 +02:00
package validation
import (
"time"
"fmt"
"strconv"
2018-05-18 18:55:00 +02:00
"regexp"
2018-05-11 09:07:54 +02:00
"bitbucket.org/nemt/nemt-portal-api/application/viewmodel"
"bitbucket.org/nemt/nemt-portal-api/infra/errors"
)
const (
2018-05-18 18:55:00 +02:00
tripTypeFromVisit = "from_visit"
tripTypeToVisit = "to_visit"
tripTypeFromVisitWillCall = "from_visit_call"
tripTypeRoundTrip = "roundtrip"
tripTypeRountTripWillCall = "roundtrip_call"
2018-05-11 09:07:54 +02:00
)
const (
loadingTime = 30 //in minutes
minimumLoadTime = 30 //in minutes
minimumPickupTime = 10 //in minutes
)
const (
hoursInDay = 24
hoursIn180Days = 24 * 180
time8Hours = 8
time10Minutes = 10
)
2018-05-19 09:53:48 +02:00
func isMixedIDValid ( id string ) bool {
hasUpperCase := false
hasLowerCase := false
hasNumber := false
for _ , character := range ( id ) {
hasUpperCase = hasUpperCase || ( ( character >= 65 ) && ( character <= 90 ) )
hasLowerCase = hasLowerCase || ( ( character >= 97 ) && ( character <= 122 ) )
hasNumber = hasNumber || ( ( character >= 48 ) && ( character <= 57 ) )
}
return ( hasUpperCase || hasLowerCase ) && hasNumber
}
2018-05-11 09:07:54 +02:00
func ValidateRide ( requestRide * viewmodel . RideRequest , user * viewmodel . User ) [ ] errors . ValidationError {
var result [ ] errors . ValidationError
2018-05-18 18:55:00 +02:00
var validUUIDregex = regexp . MustCompile ( ` ^[0-9a-f] { 8}-[0-9a-f] { 4}-4[0-9a-f] { 3}-[89ab][0-9a-f] { 3}-[0-9a-f] { 12}$ ` )
2018-05-11 09:07:54 +02:00
//Step #1 validation
2018-05-18 18:55:00 +02:00
if ! validUUIDregex . MatchString ( user . ID ) {
2018-05-11 09:07:54 +02:00
result = append ( result , errors . ValidationError { Field : "user_uuid" , Message : "Step #1 - Choose a Member" } )
}
2018-05-19 09:53:48 +02:00
fmt . Println ( "\n\n" , requestRide . Origin . ID , "\n\n" )
if ! isMixedIDValid ( requestRide . Origin . ID ) {
//it is not UUID or similar to UUID, let's try with just a number
if originID , err := strconv . Atoi ( requestRide . Origin . ID ) ; err != nil || originID <= 0 {
//it is not a number
result = append ( result , errors . ValidationError { Field : "origin.id" , Message : "Step #1 - Choose a Pickup Address" } )
}
2018-05-11 09:07:54 +02:00
}
if ! requestRide . UserConsent {
result = append ( result , errors . ValidationError { Field : "user_consent" , Message : "Step #1 - Member must consent to Terms of Use" } )
}
//Step #2 validation
2018-05-19 09:53:48 +02:00
fmt . Println ( "\n\n" , requestRide . Destination . ID , "\n\n" )
if ! isMixedIDValid ( requestRide . Destination . ID ) {
//it is not UUID or similar to UUID, let's try with just a number
if destinationID , err := strconv . Atoi ( requestRide . Destination . ID ) ; err != nil || destinationID <= 0 {
result = append ( result , errors . ValidationError { Field : "destination.id" , Message : "Step #2 - Choose a Provider" } )
}
2018-05-11 09:07:54 +02:00
}
//Step #3 validation
isVisitDayToday := requestRide . VisitDate . Day ( ) == time . Now ( ) . Day ( ) && requestRide . VisitDate . Month ( ) == time . Now ( ) . Month ( ) && requestRide . VisitDate . Year ( ) == time . Now ( ) . Year ( )
before8Hours := time . Now ( ) . Add ( - time . Hour * time8Hours )
if requestRide . VisitDate == nil {
result = append ( result , errors . ValidationError { Field : "visit_date" , Message : "Step #3 - Choose a Date for the Visit" } )
} else {
dayBeforeToday := time . Now ( ) . Add ( - time . Hour * hoursInDay )
if requestRide . VisitDate . Before ( dayBeforeToday ) {
result = append ( result , errors . ValidationError { Field : "visit_date" , Message : "Step #3 - Visit cannot occur more than one day before today" } )
}
dayAfter180Days := time . Now ( ) . Add ( time . Hour * hoursIn180Days )
if requestRide . VisitDate . After ( dayAfter180Days ) {
result = append ( result , errors . ValidationError { Field : "visit_date" , Message : "Step #3 - Visit cannot occur more than 180 days after today" } )
}
if requestRide . VisitTime == nil {
result = append ( result , errors . ValidationError { Field : "visit_time" , Message : "Step #3 - Choose a Time for the Visit" } )
} else {
if isVisitDayToday && requestRide . VisitTime . Before ( before8Hours ) {
result = append ( result , errors . ValidationError { Field : "visit_time" , Message : "Step #3 - Visit is more than 8 hours in the past" } )
}
}
}
//Step #4 validation
timeWithDurationAndLoadingTime := requestRide . VisitTime . Add ( - time . Duration ( requestRide . Duration ) * time . Second ) . Add ( - loadingTime * time . Minute )
after10Minutes := time . Now ( ) . Add ( time . Minute * time10Minutes )
2018-05-18 18:55:00 +02:00
isTripTypeValid := true
switch requestRide . TripType . Key {
2018-05-11 09:07:54 +02:00
case tripTypeToVisit :
if requestRide . PickupTime == nil {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Choose a Pickup Time" } )
} else {
if requestRide . PickupTime . After ( * requestRide . VisitTime ) {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Pickup Time must occur before Visit Time" } )
}
if requestRide . PickupTime . After ( timeWithDurationAndLoadingTime ) {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Pickup Time less than required time before Visit Time" } )
}
if isVisitDayToday && requestRide . PickupTime . Before ( before8Hours ) {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Visit cannot occour in the past" } )
}
}
case tripTypeFromVisit :
if requestRide . PickupTime == nil {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Choose a Pickup Time" } )
} else {
timeWithMinimumPickupTime := time . Now ( ) . Add ( minimumPickupTime * time . Minute )
if isVisitDayToday && requestRide . PickupTime . Before ( timeWithMinimumPickupTime ) {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : fmt . Sprint ( "Step #4 - Time must be more than %d minutes from now" , minimumPickupTime ) } )
}
if requestRide . PickupTime . Before ( * requestRide . VisitTime ) {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Pickup Time less than required time after Visit Time" } )
}
timeWithMinimumLoadTime := time . Now ( ) . Add ( minimumLoadTime * time . Minute )
if requestRide . PickupTime . Before ( timeWithMinimumLoadTime ) {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Pickup Time less than Minimum Load Time before Visit Time" } )
}
}
case tripTypeFromVisitWillCall :
//no special validation for this case
case tripTypeRoundTrip :
if requestRide . PickupTime == nil {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Choose a Pickup Time" } )
} else {
if requestRide . PickupTime . After ( * requestRide . VisitTime ) {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Pickup Time must occur before Visit Time" } )
}
if requestRide . PickupTime . After ( timeWithDurationAndLoadingTime ) {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Pickup Time less than required time before Visit Time" } )
}
if isVisitDayToday && requestRide . PickupTime . Before ( after10Minutes ) {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Pickup Time must be at least 10 minutes from now" } )
}
}
if requestRide . ReturnTime == nil {
result = append ( result , errors . ValidationError { Field : "return_time" , Message : "Step #4 - Choose a Pickup Time" } )
} else {
if isVisitDayToday {
if requestRide . ReturnTime . Before ( before8Hours ) {
result = append ( result , errors . ValidationError { Field : "return_time" , Message : "Step #4 - Return Time is more than 8 hours after Visit Time" } )
}
if requestRide . ReturnTime . Before ( after10Minutes ) {
result = append ( result , errors . ValidationError { Field : "return_time" , Message : "Step #4 - Return Time must be at least 10 minutes from now" } )
}
}
}
case tripTypeRountTripWillCall :
if requestRide . PickupTime == nil {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Choose a Pickup Time" } )
} else {
if requestRide . PickupTime . After ( * requestRide . VisitTime ) {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Pickup Time must occur before Visit Time" } )
}
if requestRide . PickupTime . After ( timeWithDurationAndLoadingTime ) {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Pickup Time less than required time after Visit Time" } )
}
if isVisitDayToday && requestRide . PickupTime . Before ( before8Hours ) {
result = append ( result , errors . ValidationError { Field : "pickup_time" , Message : "Step #4 - Visit cannot occur in the past " } )
}
}
2018-05-18 18:55:00 +02:00
default :
isTripTypeValid = false
}
if ! isTripTypeValid {
result = append ( result , errors . ValidationError { Field : "trip_type.key" , Message : "Step #4 - Choose a Trip Type" } )
2018-05-11 09:07:54 +02:00
}
2018-05-18 18:55:00 +02:00
2018-05-11 09:07:54 +02:00
return result
}