Updates for real form

This commit is contained in:
Darren Clarke 2025-10-26 15:39:55 +01:00
parent 320b9c1b38
commit f9ddc843be
2 changed files with 81 additions and 49 deletions

View file

@ -1,5 +1,5 @@
import { createLogger } from "@link-stack/logger";
import { Zammad, getOrCreateUser } from "../../lib/zammad.js";
import { Zammad, getUser } from "../../lib/zammad.js";
const logger = createLogger('create-ticket-from-form');
@ -43,47 +43,29 @@ const createTicketFromFormTask = async (
? `${name.first || ''} ${name.last || ''}`.trim()
: 'Unknown';
// Build address string
let addressString = '';
if (address) {
const parts = [
address.address,
address.city,
address.state,
address.zip,
].filter(Boolean);
addressString = parts.join(', ');
// Get organization name from form data
const organizationName = type_of_organization || '';
// Build ticket title - matching ngo-isac-uploader pattern
let title = fullName;
if (organizationName) {
title += ` - ${organizationName}`;
}
if (type_of_help_requested) {
title += ` - ${type_of_help_requested}`;
}
// Build ticket title
const title = `Help Request: ${type_of_help_requested || 'General'} - ${fullName}`;
// Build ticket body with all form information
const body = `<h3>Contact Information</h3>
<ul>
<li><strong>Name:</strong> ${fullName}</li>
${email_address ? `<li><strong>Email:</strong> ${email_address}</li>` : ''}
${phone_number ? `<li><strong>Phone:</strong> ${phone_number}</li>` : ''}
${signal_number ? `<li><strong>Signal Number:</strong> ${signal_number}</li>` : ''}
${addressString ? `<li><strong>Address:</strong> ${addressString}</li>` : ''}
</ul>
<h3>Request Details</h3>
<ul>
${type_of_help_requested ? `<li><strong>Type of Help:</strong> ${type_of_help_requested}</li>` : ''}
${type_of_organization ? `<li><strong>Organization Type:</strong> ${type_of_organization}</li>` : ''}
${urgency_level ? `<li><strong>Urgency Level:</strong> ${urgency_level}</li>` : ''}
${preferred_contact_method ? `<li><strong>Preferred Contact Method:</strong> ${preferred_contact_method}</li>` : ''}
${available_times_for_contact ? `<li><strong>Available Times:</strong> ${available_times_for_contact}</li>` : ''}
${preferred_language ? `<li><strong>Preferred Language:</strong> ${preferred_language}</li>` : ''}
</ul>
${description_of_issue ? `<h3>Description of Issue</h3><p>${description_of_issue}</p>` : ''}
${how_did_you_hear_about_us ? `<p><strong>How they heard about us:</strong> ${how_did_you_hear_about_us}</p>` : ''}
// Build article body - only description and metadata
// All other fields go into custom Zammad ticket fields
const body = description_of_issue
? `<p>${description_of_issue}</p>
<hr>
<p><em>Form ID: ${FormID} | Submission ID: ${UniqueID} | Received: ${receivedAt}</em></p>`;
<p><em>Submitted via Formstack | Form ID: ${FormID} | Submission ID: ${UniqueID} | Received: ${receivedAt}</em></p>`
: `<p><em>No description provided</em></p>
<hr>
<p><em>Submitted via Formstack | Form ID: ${FormID} | Submission ID: ${UniqueID} | Received: ${receivedAt}</em></p>`;
// Get Zammad configuration from environment
const zammadUrl = process.env.ZAMMAD_URL || 'http://zammad-nginx:8080';
@ -97,29 +79,78 @@ const createTicketFromFormTask = async (
const zammad = Zammad({ token: zammadToken }, zammadUrl);
try {
// Get or create user based on phone number, Signal number, or email
// Get or create user based on contact info
// Priority: signal_number > phone_number > email_address
let customer;
const contactInfo = signal_number || phone_number || email_address;
if (contactInfo) {
customer = await getOrCreateUser(zammad, contactInfo);
} else {
// Create user with just the name if no contact info
// Try to find existing user by phone or email
if (signal_number || phone_number) {
const phoneToSearch = signal_number || phone_number;
customer = await getUser(zammad, phoneToSearch);
if (customer) {
logger.info({ customerId: customer.id, method: 'phone' }, 'Found existing user by phone');
}
}
if (!customer && email_address) {
// Search by email if phone search didn't work
const emailResults = await zammad.user.search(`email:${email_address}`);
if (emailResults.length > 0) {
customer = emailResults[0];
logger.info({ customerId: customer.id, method: 'email' }, 'Found existing user by email');
}
}
if (!customer) {
// Create new user with all available contact information
logger.info('Creating new user from form submission');
customer = await zammad.user.create({
firstname: name?.first,
lastname: name?.last,
firstname: name?.first || '',
lastname: name?.last || '',
email: email_address || `${UniqueID}@formstack.local`,
phone: signal_number || phone_number || '',
note: `User created from Formstack submission ${UniqueID}`,
});
}
logger.info({ customerId: customer.id, customerEmail: customer.email }, 'Customer identified/created');
logger.info({
customerId: customer.id,
customerEmail: customer.email,
customerPhone: customer.phone,
}, 'Customer identified/created');
// Create the ticket
// Build address parts
const streetAddress = address?.address || '';
const cityValue = address?.city || '';
const stateValue = address?.state || '';
const zipValue = address?.zip || '';
// Create the ticket with custom fields mapped to Zammad attributes
// Following the pattern from ngo-isac-uploader where all form data
// goes into structured fields rather than HTML body
const ticket = await zammad.ticket.create({
title,
group: "Users", // Default group - you may want to make this configurable
note: `This ticket was created automatically from Formstack form ${FormID}.`,
customer_id: customer.id,
// Custom fields - these will be populated in Zammad's ticket attributes
// NOTE: 'organization', 'formstack_form_id', 'formstack_submission_id'
// fields could not be created due to naming conflicts, so metadata
// is included in the ticket body instead
signal_number: signal_number || undefined,
type_of_help_requested: type_of_help_requested || undefined,
type_of_organization: type_of_organization || undefined,
urgency_level: urgency_level || undefined,
city: cityValue || undefined,
us_state: stateValue || undefined,
zip_code: zipValue || undefined,
street_address: streetAddress || undefined,
preferred_contact_method: preferred_contact_method || undefined,
available_times: available_times_for_contact || undefined,
where_heard: how_did_you_hear_about_us || undefined,
preferred_language: preferred_language || undefined,
// Article with just the description
article: {
body,
subject: title,