/** * Temporary discovery script. * Goal: Inspect the shape of notes returned by the ServiceChannel API * to determine the correct timestamp field name. * * Run with: node discover-note-timestamps.js * * This script now loads credentials from environment variables (via .env) * — same as the main app — so there's no plaintext credential in this file. * Feel free to delete once you're done using it. */ import 'dotenv/config'; import axios from 'axios'; import qs from 'node:querystring'; const SC = { clientId: process.env.SC_CLIENT_ID, clientSecret: process.env.SC_CLIENT_SECRET, username: process.env.SC_USERNAME, password: process.env.SC_PASSWORD, baseUrl: process.env.SC_BASE_URL || 'https://api.servicechannel.com/v3', oauthUrl: process.env.SC_OAUTH_URL || 'https://login.servicechannel.com/oauth/token', }; if (!SC.clientId || !SC.clientSecret || !SC.username || !SC.password) { console.error('Missing ServiceChannel credentials. Set SC_CLIENT_ID, SC_CLIENT_SECRET, SC_USERNAME, SC_PASSWORD in .env.'); process.exit(1); } async function getToken() { const basicAuth = Buffer.from(`${SC.clientId}:${SC.clientSecret}`).toString('base64'); const response = await axios.post( SC.oauthUrl, qs.stringify({ grant_type: 'password', username: SC.username, password: SC.password, }), { headers: { 'Authorization': `Basic ${basicAuth}`, 'Content-Type': 'application/x-www-form-urlencoded', }, timeout: 15000, } ); return response.data.access_token; } async function main() { const workOrderId = Number(process.argv[2] || 352088878); console.log(`Discovering note structure for work order ${workOrderId}...\n`); try { const token = await getToken(); const notesRes = await axios.get( `${SC.baseUrl}/workorders/${workOrderId}/notes`, { headers: { Authorization: `Bearer ${token}` }, timeout: 30000, } ); const notes = notesRes.data?.Notes || notesRes.data || []; console.log(`Found ${notes.length} notes.\n`); if (notes.length === 0) { console.log("No notes found on this work order."); return; } const firstNote = notes[0]; console.log("Keys on the first note object:"); console.log(Object.keys(firstNote)); console.log("\n"); console.log("=== First note (full object) ==="); console.dir(firstNote, { depth: null, colors: true }); console.log("\n=== Last 3 notes - looking for timestamp fields ==="); const lastNotes = notes.slice(-3).reverse(); lastNotes.forEach((note, i) => { console.log(`\nNote ${i + 1}:`); const possibleTimestampFields = Object.keys(note).filter(k => /time|date|stamp|created|updated/i.test(k) ); console.log(" Possible timestamp fields:", possibleTimestampFields); possibleTimestampFields.forEach(field => { console.log(` ${field}: ${note[field]}`); }); }); } catch (err) { console.error("Error:", err.response?.data || err.message); if (err.response) { console.error("Status:", err.response.status); } } } main();