You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
3.7 KiB

import type { Priority1DemoInput } from "@/workers/rpa/priority1/demo-input";
import { validatePriority1FormConstraints } from "@/workers/rpa/priority1/form-constraints";
import { findPhoneCountry } from "@/lib/priority1/phone-countries";
import { pickupDateValidationMessage } from "@/lib/priority1/pickup-date";
import { ValidationError } from "@/modules/quote/types";
const ZIP_RE = /^\d{5}$/;
const DATE_RE = /^\d{2}\/\d{2}\/\d{4}$/;
function req(value: string | undefined, label: string): string {
const v = value?.trim();
if (!v) throw new ValidationError(`请填写${label}`);
return v;
}
/** 校验 Priority1 模拟表单提交 */
export function validatePriority1QuoteInput(
body: unknown,
): Priority1DemoInput & { request_id: string; customer_id: string } {
if (!body || typeof body !== "object") {
throw new ValidationError("请求体格式无效");
}
const o = body as Record<string, unknown>;
const requestId = req(o.request_id as string | undefined, "请求标识");
const customerId = req(o.customer_id as string | undefined, "客户标识");
const input = o.priority1_input;
if (!input || typeof input !== "object") {
throw new ValidationError("请填写 Priority1 表单参数");
}
const p = input as Priority1DemoInput;
if (!["ltl", "ftl", "expedited"].includes(p.shipmentType)) {
throw new ValidationError("请选择运输类型");
}
if (!ZIP_RE.test(req(p.originZip, "起运邮编"))) {
throw new ValidationError("起运邮编须为 5 位数字");
}
if (!ZIP_RE.test(req(p.destinationZip, "目的邮编"))) {
throw new ValidationError("目的邮编须为 5 位数字");
}
if (p.originZip === p.destinationZip) {
throw new ValidationError("起运与目的邮编不能相同");
}
if (!DATE_RE.test(req(p.pickupDate, "提货日"))) {
throw new ValidationError("提货日格式须为 MM/DD/YYYY");
}
const pickupDateError = pickupDateValidationMessage(p.pickupDate);
if (pickupDateError) {
throw new ValidationError(pickupDateError);
}
const phoneDigits = req(p.phone, "电话").replace(/\D/g, "");
const country = findPhoneCountry(p.phoneCountry ?? "US");
if (country.code === "US" || country.code === "CA") {
if (phoneDigits.length !== 10) {
throw new ValidationError("美国/加拿大电话须为 10 位数字");
}
} else if (phoneDigits.length < 6 || phoneDigits.length > 15) {
throw new ValidationError("请填写有效电话号码");
}
req(p.email, "商务邮箱");
if (p.shipmentType === "ltl") {
req(p.lengthIn, "长度");
req(p.widthIn, "宽度");
req(p.heightIn, "高度");
req(p.weightLb, "总重量");
req(p.packaging, "包装类型");
req(p.palletCount, "托盘数");
req(p.freightClass, "货运等级");
req(p.pickupLocation, "提货地点类型");
req(p.deliveryLocation, "派送地点类型");
}
if (p.shipmentType === "ftl") {
req(p.commodity, "货描");
req(p.weightLb, "总重量");
if (p.ftlTrailer !== "ftl_expedited") {
req(p.palletCount, "托盘数");
}
if (p.ftlTrailer === "open_deck") req(p.openDeckSubtype, "Open Deck 子类型");
if (p.ftlTrailer === "temperature_controlled") {
req(p.tempMinF, "最低温度");
req(p.tempMaxF, "最高温度");
}
}
if (p.shipmentType === "expedited") {
req(p.commodity, "货描");
req(p.weightLb, "总重量");
}
const constraintErrors = validatePriority1FormConstraints(p).filter(
(v) => v.severity === "error",
);
if (constraintErrors.length > 0) {
throw new ValidationError(constraintErrors[0]!.message);
}
return {
...p,
phone: p.phone.replace(/\D/g, "").slice(-10),
request_id: requestId,
customer_id: customerId,
};
}