Some checks are pending
CI / verify (push) Waiting to run
New /provisionDect slash command manages DECT basestations and handsets for a store via a single card: multi-select checkbox list doubles as the display, MACs render as AA:BB:CC:DD:EE:FF, Add/Remove sit side-by-side per section, and every removal goes through an explicit confirm card. Handsets always auto-pair (no bind-to-basestation input) so they roam. /finalizeStore now idempotently creates the "Store XXXX" DECT network (DBS-210) with the per-store default access code, so new stores are DECT-ready the moment finalize completes. Location-scoped lookup (findDectNetworkInLocation) handles both the finalize idempotency check and the /provisionDect fallback for freshly-created empty networks. Non-critical: a store can still go live if the DECT step fails, and /provisionDect keeps a recovery "create network" prompt for legacy stores. Pure-logic helpers (generateDectAccessCode, MAC normalize/format/ display, dectNetworkName) are unit-tested via node:test. Co-authored-by: Cursor <cursoragent@cursor.com>
63 lines
2.7 KiB
JavaScript
63 lines
2.7 KiB
JavaScript
import { logger } from '../logger.js';
|
|
import { findWebexLocation } from '../webex/locations.js';
|
|
import {
|
|
dectNetworkName,
|
|
generateDectAccessCode,
|
|
getDectProvisioningStatus,
|
|
} from '../webex/dect.js';
|
|
import { dectCreateNetworkCard, dectManagementCard } from '../cards/dectCards.js';
|
|
import { parseStoreNumber } from './helpers.js';
|
|
|
|
// /provisionDect does NOT require the remote agent — every operation is
|
|
// against public Webex Calling APIs, which the bot reaches directly.
|
|
|
|
export function register(framework) {
|
|
framework.hears(
|
|
/\/provisiondect/i,
|
|
async (bot, trigger) => {
|
|
logger.info(`${trigger.person.displayName} ran the provisionDect command.`);
|
|
const storeNumber = parseStoreNumber(trigger);
|
|
if (!storeNumber) {
|
|
bot.say('Usage: `/provisionDect <storeNumber>` — e.g. `/provisionDect 499`');
|
|
return;
|
|
}
|
|
try {
|
|
const status = await getDectProvisioningStatus(storeNumber);
|
|
if (status.network) {
|
|
bot.sendCard(
|
|
dectManagementCard(storeNumber, status),
|
|
'Please use another client',
|
|
);
|
|
return;
|
|
}
|
|
|
|
// No network yet — need the store's Webex location to create in.
|
|
const matches = await findWebexLocation(dectNetworkName(storeNumber));
|
|
if (!matches.length) {
|
|
bot.say(
|
|
'markdown',
|
|
`No Webex location found for **${dectNetworkName(storeNumber)}**. ` +
|
|
`Run \`/stageStore ${storeNumber}\` first.`,
|
|
);
|
|
return;
|
|
}
|
|
const location = matches[0];
|
|
bot.sendCard(
|
|
dectCreateNetworkCard(storeNumber, {
|
|
locationId: location.id,
|
|
locationName: location.name,
|
|
suggestedAccessCode: generateDectAccessCode(storeNumber),
|
|
}),
|
|
'Please use another client',
|
|
);
|
|
} catch (error) {
|
|
logger.error('provisionDect command failed:', error);
|
|
bot.say(
|
|
'markdown',
|
|
`Error running /provisionDect:\n\`\`\`\n${error.message}\n\`\`\``,
|
|
);
|
|
}
|
|
},
|
|
'**/provisionDect** <storeNumber> - Add or remove DECT basestations and handsets for a store. New stores get their DECT network created by /finalizeStore; this command offers a recovery-create prompt if the network is missing.',
|
|
);
|
|
}
|