@startanaicompany/crm 2.14.0 → 2.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +129 -6
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1120,6 +1120,38 @@ leadsCmd
|
|
|
1120
1120
|
} catch (err) { handleError(err); }
|
|
1121
1121
|
});
|
|
1122
1122
|
|
|
1123
|
+
// Sprint 52 T2: leads escalate + leads unassign
|
|
1124
|
+
leadsCmd
|
|
1125
|
+
.command('escalate <lead-id>')
|
|
1126
|
+
.description('Manually escalate a lead — sets escalated=true and fires lead.escalated webhook (Sprint 52 T2)')
|
|
1127
|
+
.option('--reason <text>', 'Reason for escalation')
|
|
1128
|
+
.option('--to <agent>', 'Reassign to this agent/user on escalation')
|
|
1129
|
+
.action(async (leadId, opts) => {
|
|
1130
|
+
const globalOpts = program.opts();
|
|
1131
|
+
const client = getClient(globalOpts);
|
|
1132
|
+
try {
|
|
1133
|
+
const body = {};
|
|
1134
|
+
if (opts.reason) body.reason = opts.reason;
|
|
1135
|
+
if (opts.to) body.to = opts.to;
|
|
1136
|
+
const res = await client.post(`/leads/${leadId}/escalate`, body);
|
|
1137
|
+
console.log(`Lead ${leadId} escalated.`);
|
|
1138
|
+
printJSON(res.data);
|
|
1139
|
+
} catch (err) { handleError(err); }
|
|
1140
|
+
});
|
|
1141
|
+
|
|
1142
|
+
leadsCmd
|
|
1143
|
+
.command('unassign <lead-id>')
|
|
1144
|
+
.description('Remove assignment from a lead (sets assigned_to to null) (Sprint 52 T2)')
|
|
1145
|
+
.action(async (leadId) => {
|
|
1146
|
+
const globalOpts = program.opts();
|
|
1147
|
+
const client = getClient(globalOpts);
|
|
1148
|
+
try {
|
|
1149
|
+
const res = await client.patch(`/leads/${leadId}`, { assigned_to: null });
|
|
1150
|
+
console.log(`Lead ${leadId} unassigned.`);
|
|
1151
|
+
printJSON(res.data);
|
|
1152
|
+
} catch (err) { handleError(err); }
|
|
1153
|
+
});
|
|
1154
|
+
|
|
1123
1155
|
// Sprint 51 T3: leads export / leads import
|
|
1124
1156
|
leadsCmd
|
|
1125
1157
|
.command('export')
|
|
@@ -1187,11 +1219,14 @@ const contactsCmd = program
|
|
|
1187
1219
|
contactsCmd
|
|
1188
1220
|
.command('create')
|
|
1189
1221
|
.description('Create a new contact')
|
|
1190
|
-
.
|
|
1222
|
+
.option('--name <name>', 'Full name (alias for --first-name)')
|
|
1223
|
+
.option('--first-name <name>', 'First name')
|
|
1191
1224
|
.option('--last-name <name>', 'Last name')
|
|
1192
|
-
.
|
|
1225
|
+
.requiredOption('--email <email>', 'Email address (unique)')
|
|
1193
1226
|
.option('--phone <phone>', 'Phone number')
|
|
1194
|
-
.option('--company <company>', 'Company name')
|
|
1227
|
+
.option('--company <company>', 'Company name (text)')
|
|
1228
|
+
.option('--company-id <uuid>', 'Company UUID (links to companies table)')
|
|
1229
|
+
.option('--lead-id <uuid>', 'Lead UUID to link to this contact on creation')
|
|
1195
1230
|
.option('--title <title>', 'Job title')
|
|
1196
1231
|
.option('--tags <tags>', 'Comma-separated tags')
|
|
1197
1232
|
.option('--do-not-contact', 'Mark as do not contact')
|
|
@@ -1203,11 +1238,14 @@ contactsCmd
|
|
|
1203
1238
|
const client = getClient(globalOpts, agentName);
|
|
1204
1239
|
try {
|
|
1205
1240
|
const body = {
|
|
1206
|
-
|
|
1241
|
+
name: opts.name || opts.firstName,
|
|
1242
|
+
first_name: opts.firstName || opts.name,
|
|
1207
1243
|
last_name: opts.lastName,
|
|
1208
1244
|
email: opts.email,
|
|
1209
1245
|
phone: opts.phone,
|
|
1210
1246
|
company: opts.company,
|
|
1247
|
+
company_id: opts.companyId,
|
|
1248
|
+
lead_id: opts.leadId,
|
|
1211
1249
|
title: opts.title,
|
|
1212
1250
|
notes: opts.notes,
|
|
1213
1251
|
do_not_contact: opts.doNotContact === true,
|
|
@@ -1224,8 +1262,10 @@ contactsCmd
|
|
|
1224
1262
|
.command('list')
|
|
1225
1263
|
.description('List contacts')
|
|
1226
1264
|
.option('--email <email>', 'Filter by email (partial match)')
|
|
1227
|
-
.option('--company <company>', 'Filter by company (partial match)')
|
|
1265
|
+
.option('--company <company>', 'Filter by company name (partial match)')
|
|
1266
|
+
.option('--company-id <uuid>', 'Filter by company UUID')
|
|
1228
1267
|
.option('--tag <tag>', 'Filter by tag')
|
|
1268
|
+
.option('--limit <n>', 'Max results per page (default 20)')
|
|
1229
1269
|
.option('--page <n>', 'Page number', '1')
|
|
1230
1270
|
.option('--per-page <n>', 'Results per page', '20')
|
|
1231
1271
|
.action(async (opts) => {
|
|
@@ -1233,8 +1273,10 @@ contactsCmd
|
|
|
1233
1273
|
const client = getClient(globalOpts);
|
|
1234
1274
|
try {
|
|
1235
1275
|
const params = { page: opts.page, per_page: opts.perPage };
|
|
1276
|
+
if (opts.limit) params.limit = opts.limit;
|
|
1236
1277
|
if (opts.email) params.email = opts.email;
|
|
1237
1278
|
if (opts.company) params.company = opts.company;
|
|
1279
|
+
if (opts.companyId) params.company_id = opts.companyId;
|
|
1238
1280
|
if (opts.tag) params.tag = opts.tag;
|
|
1239
1281
|
const res = await client.get('/contacts', { params });
|
|
1240
1282
|
printJSON(res.data);
|
|
@@ -1260,11 +1302,13 @@ contactsCmd
|
|
|
1260
1302
|
contactsCmd
|
|
1261
1303
|
.command('update <id>')
|
|
1262
1304
|
.description('Update a contact')
|
|
1305
|
+
.option('--name <name>', 'Full name (alias for --first-name)')
|
|
1263
1306
|
.option('--first-name <name>', 'First name')
|
|
1264
1307
|
.option('--last-name <name>', 'Last name')
|
|
1265
1308
|
.option('--email <email>', 'Email address')
|
|
1266
1309
|
.option('--phone <phone>', 'Phone number')
|
|
1267
|
-
.option('--company <company>', 'Company name')
|
|
1310
|
+
.option('--company <company>', 'Company name (text)')
|
|
1311
|
+
.option('--company-id <uuid>', 'Company UUID (links to companies table)')
|
|
1268
1312
|
.option('--title <title>', 'Job title')
|
|
1269
1313
|
.option('--role <role>', 'Role: champion|economic_buyer|technical_buyer|gatekeeper|influencer|end_user')
|
|
1270
1314
|
.option('--tags <tags>', 'Comma-separated tags')
|
|
@@ -1274,11 +1318,13 @@ contactsCmd
|
|
|
1274
1318
|
const client = getClient(globalOpts);
|
|
1275
1319
|
try {
|
|
1276
1320
|
const body = {};
|
|
1321
|
+
if (opts.name !== undefined) body.name = opts.name;
|
|
1277
1322
|
if (opts.firstName !== undefined) body.first_name = opts.firstName;
|
|
1278
1323
|
if (opts.lastName !== undefined) body.last_name = opts.lastName;
|
|
1279
1324
|
if (opts.email !== undefined) body.email = opts.email;
|
|
1280
1325
|
if (opts.phone !== undefined) body.phone = opts.phone;
|
|
1281
1326
|
if (opts.company !== undefined) body.company = opts.company;
|
|
1327
|
+
if (opts.companyId !== undefined) body.company_id = opts.companyId;
|
|
1282
1328
|
if (opts.title !== undefined) body.title = opts.title;
|
|
1283
1329
|
if (opts.role !== undefined) body.role = opts.role;
|
|
1284
1330
|
if (opts.tags !== undefined) body.tags = opts.tags.split(',').map(t => t.trim());
|
|
@@ -3442,4 +3488,81 @@ gdprCmd
|
|
|
3442
3488
|
}
|
|
3443
3489
|
});
|
|
3444
3490
|
|
|
3491
|
+
// ============================================================
|
|
3492
|
+
// REPORTS COMMANDS — Sprint 52 T3
|
|
3493
|
+
// ============================================================
|
|
3494
|
+
const reportsCmd = program.command('reports').description('Manage and run saved CRM reports (Sprint 52 T3)');
|
|
3495
|
+
|
|
3496
|
+
reportsCmd
|
|
3497
|
+
.command('list')
|
|
3498
|
+
.description('List all saved reports')
|
|
3499
|
+
.action(async () => {
|
|
3500
|
+
const globalOpts = program.opts();
|
|
3501
|
+
const client = getClient(globalOpts);
|
|
3502
|
+
try {
|
|
3503
|
+
const res = await client.get('/reports');
|
|
3504
|
+
const reports = res.data.data || res.data;
|
|
3505
|
+
if (!reports || reports.length === 0) { console.log('No reports found.'); return; }
|
|
3506
|
+
reports.forEach(r => console.log(`[${r.id}] ${r.name} — type: ${r.dimension}/${r.metric}, period: ${r.period}`));
|
|
3507
|
+
} catch (err) { handleError(err); }
|
|
3508
|
+
});
|
|
3509
|
+
|
|
3510
|
+
reportsCmd
|
|
3511
|
+
.command('create')
|
|
3512
|
+
.description('Create and save a report definition')
|
|
3513
|
+
.requiredOption('--name <name>', 'Report name')
|
|
3514
|
+
.option('--type <type>', 'Report type: leads (count by stage) | pipeline (deal value by pipeline) | revenue (deal value by stage)', 'leads')
|
|
3515
|
+
.option('--period <period>', 'Time period: 7d | 30d | 90d | 365d | all', '30d')
|
|
3516
|
+
.option('--filter-status <status>', 'Filter leads by status')
|
|
3517
|
+
.option('--filter-stage <stage>', 'Filter leads by pipeline stage')
|
|
3518
|
+
.option('--chart-type <type>', 'Chart type: bar | line | pie | table', 'bar')
|
|
3519
|
+
.action(async (opts) => {
|
|
3520
|
+
const globalOpts = program.opts();
|
|
3521
|
+
const client = getClient(globalOpts);
|
|
3522
|
+
try {
|
|
3523
|
+
const body = {
|
|
3524
|
+
name: opts.name,
|
|
3525
|
+
type: opts.type,
|
|
3526
|
+
period: opts.period,
|
|
3527
|
+
chart_type: opts.chartType,
|
|
3528
|
+
};
|
|
3529
|
+
if (opts.filterStatus) body.filter_status = opts.filterStatus;
|
|
3530
|
+
if (opts.filterStage) body.filter_stage = opts.filterStage;
|
|
3531
|
+
const res = await client.post('/reports', body);
|
|
3532
|
+
const r = res.data.data || res.data;
|
|
3533
|
+
console.log(`Report created: [${r.id}] ${r.name}`);
|
|
3534
|
+
printJSON(res.data);
|
|
3535
|
+
} catch (err) { handleError(err); }
|
|
3536
|
+
});
|
|
3537
|
+
|
|
3538
|
+
reportsCmd
|
|
3539
|
+
.command('run <report-id>')
|
|
3540
|
+
.description('Run a saved report and display or save results')
|
|
3541
|
+
.option('--output <file>', 'Save results to this JSON file')
|
|
3542
|
+
.action(async (reportId, opts) => {
|
|
3543
|
+
const globalOpts = program.opts();
|
|
3544
|
+
const client = getClient(globalOpts);
|
|
3545
|
+
try {
|
|
3546
|
+
const res = await client.get(`/reports/${reportId}/run`);
|
|
3547
|
+
if (opts.output) {
|
|
3548
|
+
fs.writeFileSync(opts.output, JSON.stringify(res.data, null, 2));
|
|
3549
|
+
console.log(`Report results saved to ${opts.output}`);
|
|
3550
|
+
} else {
|
|
3551
|
+
printJSON(res.data);
|
|
3552
|
+
}
|
|
3553
|
+
} catch (err) { handleError(err); }
|
|
3554
|
+
});
|
|
3555
|
+
|
|
3556
|
+
reportsCmd
|
|
3557
|
+
.command('delete <report-id>')
|
|
3558
|
+
.description('Delete a saved report')
|
|
3559
|
+
.action(async (reportId) => {
|
|
3560
|
+
const globalOpts = program.opts();
|
|
3561
|
+
const client = getClient(globalOpts);
|
|
3562
|
+
try {
|
|
3563
|
+
await client.delete(`/reports/${reportId}`);
|
|
3564
|
+
console.log(`Report ${reportId} deleted.`);
|
|
3565
|
+
} catch (err) { handleError(err); }
|
|
3566
|
+
});
|
|
3567
|
+
|
|
3445
3568
|
program.parse(process.argv);
|