implement driver license date validation
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import { Router } from 'express'
|
||||
import { parseBody } from '../../http/validate'
|
||||
import { ok } from '../../http/respond'
|
||||
import { AppError } from '../../http/errors'
|
||||
import { validateLicenseSchema } from './license.validation.schemas'
|
||||
import { parseExpirationDate, validateLicenseDate, ErrorCode } from '../../services/licenseValidationService'
|
||||
|
||||
const router = Router()
|
||||
|
||||
/**
|
||||
* POST /api/v1/licenses/validate
|
||||
*
|
||||
* Validates a driver's license expiration date against the minimum validity rule.
|
||||
*
|
||||
* Request body:
|
||||
* { expiration_date: string, license_number?: string, state?: string }
|
||||
*
|
||||
* Success (200): license is valid (≥30 days remaining)
|
||||
* Error (400): invalid format, missing date, future date
|
||||
* Error (422): expired or expiring soon (<30 days remaining)
|
||||
*/
|
||||
router.post('/validate', async (req, res, next) => {
|
||||
try {
|
||||
const { expiration_date } = parseBody(validateLicenseSchema, req)
|
||||
const parsedDate = parseExpirationDate(expiration_date)
|
||||
|
||||
if (!parsedDate) {
|
||||
throw new AppError(
|
||||
`Unable to parse date "${expiration_date}". Please use YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, or DD-MMM-YYYY format.`,
|
||||
400,
|
||||
ErrorCode.LICENSE_INVALID_FORMAT,
|
||||
{
|
||||
details: {
|
||||
expiration_date,
|
||||
suggested_action: 'Please provide the date in a supported format (e.g., YYYY-MM-DD).',
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
const result = validateLicenseDate(parsedDate)
|
||||
|
||||
if (!result.valid) {
|
||||
// Map error codes to HTTP status
|
||||
const statusCode =
|
||||
result.error_code === ErrorCode.LICENSE_EXPIRED || result.error_code === ErrorCode.LICENSE_EXPIRING_SOON
|
||||
? 422
|
||||
: 400
|
||||
|
||||
throw new AppError(result.message, statusCode, result.error_code!, {
|
||||
details: result.details,
|
||||
})
|
||||
}
|
||||
|
||||
ok(res, {
|
||||
valid: true,
|
||||
days_remaining: result.days_remaining,
|
||||
expiration_date: result.expiration_date,
|
||||
message: result.message,
|
||||
next_reminder: result.days_remaining
|
||||
? new Date(Date.now() + (result.days_remaining - 30) * 86400000).toISOString().split('T')[0]
|
||||
: null,
|
||||
})
|
||||
} catch (err) {
|
||||
next(err)
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
||||
@@ -0,0 +1,10 @@
|
||||
import { z } from 'zod'
|
||||
|
||||
/** Request body for POST /api/v1/licenses/validate */
|
||||
export const validateLicenseSchema = z.object({
|
||||
expiration_date: z.string().min(1, 'expiration_date is required'),
|
||||
license_number: z.string().max(100).optional(),
|
||||
state: z.string().length(2).optional(),
|
||||
})
|
||||
|
||||
export type ValidateLicenseInput = z.infer<typeof validateLicenseSchema>
|
||||
Reference in New Issue
Block a user