UNPKG

@defra-fish/gafl-webapp-service

Version:

The websales frontend for the GAFL service

162 lines (144 loc) 5.75 kB
import Joi from 'joi' import moment from 'moment' import { ADVANCED_PURCHASE_MAX_DAYS, SERVICE_LOCAL_TIME } from '@defra-fish/business-rules-lib' import { dateSchema, dateSchemaInput } from '../date.schema.js' const MAX_AGE = 120 const LICENCE_TO_START_FIELD = 'licence-to-start' const AFTER_PAYMENT = 'after-payment' const ANOTHER_DATE = 'another-date' const DOB_ERROR_KEYS = { DAY_AND_MONTH: 'day-and-month', DAY_AND_YEAR: 'day-and-year', MONTH_AND_YEAR: 'month-and-year' } const DAY_SPECIFIC_ERRORS = [DOB_ERROR_KEYS.DAY_AND_MONTH, DOB_ERROR_KEYS.DAY_AND_YEAR, 'day'] const MONTH_SPECIFIC_ERRORS = [DOB_ERROR_KEYS.DAY_AND_MONTH, DOB_ERROR_KEYS.MONTH_AND_YEAR, 'month'] const YEAR_SPECIFIC_ERRORS = [DOB_ERROR_KEYS.DAY_AND_YEAR, DOB_ERROR_KEYS.MONTH_AND_YEAR, 'year'] const DOB_FIELD_ERROR_PRIORITY = [ 'full-date', DOB_ERROR_KEYS.DAY_AND_MONTH, DOB_ERROR_KEYS.DAY_AND_YEAR, DOB_ERROR_KEYS.MONTH_AND_YEAR, 'day', 'month', 'year', 'non-numeric', 'invalid-date' ] const validateDate = (day, month, year, minDate, maxDate) => { Joi.assert(dateSchemaInput(day, month, year), dateSchema) const dateRange = moment(`${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`, 'YYYY-MM-DD') .tz(SERVICE_LOCAL_TIME) .startOf('day') .toDate() Joi.assert({ 'date-range': dateRange }, Joi.object({ 'date-range': Joi.date().min(minDate).max(maxDate) })) } export const dateOfBirthValidator = payload => { const day = payload['date-of-birth-day'] const month = payload['date-of-birth-month'] const year = payload['date-of-birth-year'] const minDate = moment().tz(SERVICE_LOCAL_TIME).subtract(MAX_AGE, 'years').startOf('day').toDate() const maxDate = moment().tz(SERVICE_LOCAL_TIME).subtract(1, 'day').startOf('day').toDate() validateDate(day, month, year, minDate, maxDate) } export const startDateValidator = payload => { Joi.assert( { 'licence-to-start': payload[LICENCE_TO_START_FIELD] }, Joi.object({ 'licence-to-start': Joi.string().valid(AFTER_PAYMENT, ANOTHER_DATE).required() }) ) if (payload[LICENCE_TO_START_FIELD] === ANOTHER_DATE) { const day = payload['licence-start-date-day'] const month = payload['licence-start-date-month'] const year = payload['licence-start-date-year'] const minDate = moment().tz(SERVICE_LOCAL_TIME).startOf('day').toDate() const maxDate = moment().tz(SERVICE_LOCAL_TIME).add(ADVANCED_PURCHASE_MAX_DAYS, 'days').toDate() validateDate(day, month, year, minDate, maxDate) } } export const renewalStartDateValidator = (payload, options) => { const { permission } = options.context.app.request const endDateMoment = moment.utc(permission.renewedEndDate).tz(SERVICE_LOCAL_TIME) const day = payload['licence-start-date-day'] const month = payload['licence-start-date-month'] const year = payload['licence-start-date-year'] const minDate = endDateMoment.clone().startOf('day').toDate() const maxDate = endDateMoment.clone().add(ADVANCED_PURCHASE_MAX_DAYS, 'days').toDate() validateDate(day, month, year, minDate, maxDate) } export const getDateErrorFlags = error => { const errorFlags = { isDayError: false, isMonthError: false, isYearError: false } const commonErrors = ['full-date', 'invalid-date', 'date-range', 'non-numeric'] const dayErrorKeys = new Set([...DAY_SPECIFIC_ERRORS, ...commonErrors]) const monthErrorKeys = new Set([...MONTH_SPECIFIC_ERRORS, ...commonErrors]) const yearErrorKeys = new Set([...YEAR_SPECIFIC_ERRORS, ...commonErrors]) if (error) { const errorKeys = Object.keys(error) for (const errorKey of errorKeys) { if (dayErrorKeys.has(errorKey)) { errorFlags.isDayError = true } if (monthErrorKeys.has(errorKey)) { errorFlags.isMonthError = true } if (yearErrorKeys.has(errorKey)) { errorFlags.isYearError = true } } } return errorFlags } export const getDobErrorMessage = (error, catalog) => { const normalizedError = error ?? {} if (!catalog) { return undefined } const DATE_RANGE = 'date-range' const errorMap = { 'full-date': { 'object.missing': { text: catalog.dob_error } }, [DOB_ERROR_KEYS.DAY_AND_MONTH]: { 'object.missing': { text: catalog.dob_error_missing_day_and_month } }, [DOB_ERROR_KEYS.DAY_AND_YEAR]: { 'object.missing': { text: catalog.dob_error_missing_day_and_year } }, [DOB_ERROR_KEYS.MONTH_AND_YEAR]: { 'object.missing': { text: catalog.dob_error_missing_month_and_year } }, day: { 'any.required': { text: catalog.dob_error_missing_day } }, month: { 'any.required': { text: catalog.dob_error_missing_month } }, year: { 'any.required': { text: catalog.dob_error_missing_year } }, 'non-numeric': { 'number.base': { text: catalog.dob_error_non_numeric } }, 'invalid-date': { 'any.custom': { text: catalog.dob_error_date_real } }, [DATE_RANGE]: { 'date.min': { text: catalog.dob_error_year_min }, 'date.max': { text: catalog.dob_error_year_max } } } const errorTypes = [...DOB_FIELD_ERROR_PRIORITY.map(type => [type]), [DATE_RANGE, 'date.min'], [DATE_RANGE, 'date.max']] const found = errorTypes.find(([errType, errSubType]) => { if (errType === DATE_RANGE) { return normalizedError[errType] === errSubType && errorMap[errType]?.[errSubType] } return normalizedError[errType] && errorMap[errType]?.[normalizedError[errType]] }) if (!found) { return undefined } const [foundType, foundSubType] = found if (foundType === DATE_RANGE) { return { text: errorMap[foundType]?.[foundSubType]?.text } } return { text: errorMap[foundType]?.[normalizedError[foundType]]?.text } }