implement driver license date validation

This commit is contained in:
root
2026-06-11 21:53:48 -04:00
parent b52c6305b5
commit af5b7fda7e
10 changed files with 1143 additions and 15 deletions
@@ -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>