conduyt 1.49.0 → 1.51.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/dist/index.js +48 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -468,6 +468,7 @@ deals
|
|
|
468
468
|
if (opts.json !== undefined)
|
|
469
469
|
Object.assign(body, jsonArg(opts.json, "--json"));
|
|
470
470
|
assertFiniteValue(body.value);
|
|
471
|
+
assertDealSource(body);
|
|
471
472
|
return client.post("/api/v1/deals", body);
|
|
472
473
|
}));
|
|
473
474
|
deals
|
|
@@ -477,6 +478,19 @@ deals
|
|
|
477
478
|
assertUuid(id, "deal id");
|
|
478
479
|
return client.get(`/api/v1/deals/${encodeURIComponent(id)}`);
|
|
479
480
|
}));
|
|
481
|
+
// Conduyt #129: every deal carries a source — it can be changed, never cleared. Validated on the FINAL merged body
|
|
482
|
+
// (flags and --json alike) so the CLI fails locally instead of shipping a guaranteed 422. An omitted source on
|
|
483
|
+
// create is fine: the server derives it (explicit → trigger → contact → "Unknown (created via api)").
|
|
484
|
+
function assertDealSource(body) {
|
|
485
|
+
if (!("source" in body))
|
|
486
|
+
return;
|
|
487
|
+
const v = body.source;
|
|
488
|
+
if (v === null || typeof v !== "string" || v.trim() === "" || v.trim().toLowerCase() === "null") {
|
|
489
|
+
throw new Error("A deal's source can be changed, never cleared (every deal carries a source). Pass a non-blank source string, or omit it.");
|
|
490
|
+
}
|
|
491
|
+
if (v.length > 500)
|
|
492
|
+
throw new Error("source must be at most 500 characters.");
|
|
493
|
+
}
|
|
480
494
|
deals
|
|
481
495
|
.command("update <id>")
|
|
482
496
|
.description("Update a deal (PATCH — only the fields you pass change). --stage moves the deal (won/lost status auto-derives from the target stage's flags)")
|
|
@@ -487,7 +501,7 @@ deals
|
|
|
487
501
|
.option("--pipeline <id>", "move to this pipeline UUID")
|
|
488
502
|
.option("--contact <id>", "primary contact UUID")
|
|
489
503
|
.option("--status <status>", "explicit status (open|won|lost); overrides the status auto-derived from --stage")
|
|
490
|
-
.option("--source <source>", "attribution source for THIS deal (
|
|
504
|
+
.option("--source <source>", "attribution source for THIS deal (can be changed, never cleared — every deal carries a source)")
|
|
491
505
|
.option("--lost-reason <reason>", "reason for a lost/disqualified deal — some stages REQUIRE it on entry; when the stage has a configured dropdown the API 422 lists the valid lostReasonOptions, resend with one of those exact values")
|
|
492
506
|
.option("--json <json>", "full JSON body, merged over the flags")
|
|
493
507
|
.action(run(async (client, id, opts) => {
|
|
@@ -512,14 +526,14 @@ deals
|
|
|
512
526
|
if (opts.status !== undefined)
|
|
513
527
|
body.status = opts.status;
|
|
514
528
|
if (opts.source !== undefined) {
|
|
515
|
-
// Mirror the API validator (
|
|
516
|
-
// fails locally rather than shipping a guaranteed 422.
|
|
517
|
-
if (opts.source.trim() === "") {
|
|
518
|
-
throw new Error("
|
|
529
|
+
// Mirror the API validator (Conduyt #129: a deal's source can change, never be cleared; blank rejected,
|
|
530
|
+
// 500-char cap) so the CLI fails locally rather than shipping a guaranteed 422.
|
|
531
|
+
if (opts.source.trim() === "" || opts.source.trim().toLowerCase() === "null") {
|
|
532
|
+
throw new Error("A deal's source can be changed, never cleared (every deal carries a source). Pass the new source, or omit --source.");
|
|
519
533
|
}
|
|
520
534
|
if (opts.source.length > 500)
|
|
521
535
|
throw new Error("--source must be at most 500 characters.");
|
|
522
|
-
body.source = opts.source
|
|
536
|
+
body.source = opts.source;
|
|
523
537
|
}
|
|
524
538
|
if (opts.stage !== undefined) {
|
|
525
539
|
if (opts.stage.trim() === "")
|
|
@@ -534,6 +548,7 @@ deals
|
|
|
534
548
|
if (opts.json !== undefined)
|
|
535
549
|
Object.assign(body, jsonArg(opts.json, "--json"));
|
|
536
550
|
assertFiniteValue(body.value);
|
|
551
|
+
assertDealSource(body);
|
|
537
552
|
if (Object.keys(body).length === 0)
|
|
538
553
|
throw new Error("Nothing to update. Pass at least one field flag or --json.");
|
|
539
554
|
return client.patch(`/api/v1/deals/${encodeURIComponent(id)}`, body);
|
|
@@ -1262,6 +1277,33 @@ appointments
|
|
|
1262
1277
|
throw new Error("Nothing to update. Pass at least one field flag or --json.");
|
|
1263
1278
|
return client.patch(`/api/v1/appointments/${encodeURIComponent(id)}`, body);
|
|
1264
1279
|
}));
|
|
1280
|
+
appointments
|
|
1281
|
+
.command("outcome <id>")
|
|
1282
|
+
.description("Record the outcome (completed | no_show | cancelled | rescheduled): sets the status (rescheduled keeps it) and moves the contact's open deal to the stage mapped in Pipeline settings (POST /appointments/:id/outcome)")
|
|
1283
|
+
.requiredOption("--outcome <outcome>", "completed, no_show, cancelled or rescheduled")
|
|
1284
|
+
.option("--start <iso>", "rescheduled only: new start, ISO-8601 with tz offset")
|
|
1285
|
+
.option("--end <iso>", "rescheduled only: new end, ISO-8601 with tz offset")
|
|
1286
|
+
.action(run(async (client, id, opts) => {
|
|
1287
|
+
assertUuid(id, "appointment id");
|
|
1288
|
+
if (!["completed", "no_show", "cancelled", "rescheduled"].includes(opts.outcome)) {
|
|
1289
|
+
throw new Error("--outcome must be completed, no_show, cancelled or rescheduled");
|
|
1290
|
+
}
|
|
1291
|
+
if (opts.outcome === "rescheduled" && (!opts.start || !opts.end))
|
|
1292
|
+
throw new Error("--outcome rescheduled needs --start and --end");
|
|
1293
|
+
const body = { outcome: opts.outcome };
|
|
1294
|
+
if (opts.start)
|
|
1295
|
+
body.startTime = opts.start;
|
|
1296
|
+
if (opts.end)
|
|
1297
|
+
body.endTime = opts.end;
|
|
1298
|
+
return client.post(`/api/v1/appointments/${encodeURIComponent(id)}/outcome`, body);
|
|
1299
|
+
}));
|
|
1300
|
+
appointments
|
|
1301
|
+
.command("outcome-undo <id>")
|
|
1302
|
+
.description("Undo the last recorded outcome: status back to what it was, deal back to its previous stage when nobody moved it since (POST /appointments/:id/outcome/undo)")
|
|
1303
|
+
.action(run(async (client, id) => {
|
|
1304
|
+
assertUuid(id, "appointment id");
|
|
1305
|
+
return client.post(`/api/v1/appointments/${encodeURIComponent(id)}/outcome/undo`, {});
|
|
1306
|
+
}));
|
|
1265
1307
|
appointments
|
|
1266
1308
|
.command("cancel <id>")
|
|
1267
1309
|
.description("Cancel an appointment (soft-cancel; sets status=cancelled)")
|
package/package.json
CHANGED