v1.0.0-beta3a: make Job_Name and Job_Address optional, allow blank phone, add Timothy Cardoza to Office_Rep, comment out Job_Size_Guess fields

This commit is contained in:
2026-01-08 14:56:11 +00:00
parent 2546eb30fe
commit d7cb428ed7
4 changed files with 45 additions and 168 deletions
+6 -39
View File
@@ -273,7 +273,7 @@ function calculateJobFullName(record: any): string {
const companyClient = record.Company_Client || record.company_client || '';
const parts = [jobName, jobAddress, companyClient].filter(p => p && String(p).trim());
return parts.map(p => String(p).trim()).join(' - ').trim();
return parts.map(p => String(p).trim()).join(' ').trim();
}
/**
@@ -518,7 +518,7 @@ async function addToExcel(record: any, pbId: string) {
// Job_Full_Name: CONCAT(Job_Name, " - ", Job_Address, " - ", Company_Client)
if (colLower === 'job_full_name') {
return calculateJobFullName(record);
return '=CONCATENATE([@[Job_Name]]," ",[@[Job_Address]]," ",[@[Company_Client]])';
}
// Due_Date_Counter: Status-aware due date counter (ASAP, Passed due, Due today, X days)
@@ -693,43 +693,10 @@ app.post('/api/submit', async (c) => {
if (dueIso) data.Due_Date = dueIso;
if (startIso) data.Start_Date = startIso;
// Address validation: require plausible address, coordinates, OR Address_Notes provided
const addr = (data.Job_Address || '').toString().trim();
const addrNotes = (data.Address_Notes || '').toString().trim();
// Check if it looks like coordinates: pattern "lat, lon" or "lat,lon"
const coordPattern = /^-?\d+\.?\d*\s*,\s*-?\d+\.?\d*$/;
const isCoordinates = coordPattern.test(addr);
// Check if it looks like a real address: has digit(s) and letter(s), at least 5 chars
const hasDigit = /\d/.test(addr);
const hasAlpha = /[A-Za-z]/.test(addr);
const isAddress = addr.length >= 5 && hasDigit && hasAlpha;
const addressLooksValid = isCoordinates || isAddress;
if (!addressLooksValid && addrNotes.length < 5) {
return c.json({
success: false,
message: 'Provide a real address (e.g., 123 Main St, City, State), coordinates (e.g., 34.0522, -118.2437), or enter directions in Address Notes.'
}, 400);
}
data.Job_Address = addr;
data.Address_Notes = addrNotes;
// Job name validation: must be at least 4 characters, contain letters, not symbols-only, not "n/a"
const jobName = (data.Job_Name || '').toString().trim();
const invalidLiterals = ['n/a', 'na', 'n.a.', 'n\\a', 'none'];
const onlySymbols = /^[^A-Za-z0-9]+$/.test(jobName);
const hasLetters = /[A-Za-z]/.test(jobName);
const isInvalidLiteral = invalidLiterals.includes(jobName.toLowerCase());
const isLongEnough = jobName.length >= 4;
if (!isLongEnough || !hasLetters || onlySymbols || isInvalidLiteral) {
return c.json({
success: false,
message: 'Job name must be at least 4 characters with letters (no symbols-only, no N/A).'
}, 400);
}
data.Job_Name = jobName;
// Address and Job_Name are optional; trim but do not validate
data.Job_Address = (data.Job_Address || '').toString().trim();
data.Address_Notes = (data.Address_Notes || '').toString().trim();
data.Job_Name = (data.Job_Name || '').toString().trim();
// Enforce Job_Type and Job_Division selection
const jobType = (data.Job_Type || '').toString().trim();