@wirecat/cli-core 0.586.0 → 0.588.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/CHANGELOG.md +38 -0
- package/dist/calendar/cli/local-times.js +3 -13
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +1 -0
- package/dist/cli/local-times.d.ts +16 -0
- package/dist/cli/local-times.js +65 -0
- package/dist/cli/runs/command.js +3 -2
- package/dist/domain/deals.d.ts +8 -6
- package/dist/domain/deals.js +7 -8
- package/dist/domain/ref-summaries.js +2 -0
- package/dist/domain/references.d.ts +1 -1
- package/dist/domain/references.js +2 -0
- package/dist/errors/reasons.js +6 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mail/cli/index.js +12 -11
- package/dist/mail/cli/review.js +10 -7
- package/dist/mail/read.d.ts +1 -1
- package/dist/mail/read.js +2 -2
- package/dist/services/proposals/registry.js +0 -2
- package/dist/store/index.d.ts +1 -1
- package/dist/store/sqlite/deals.d.ts +128 -29
- package/dist/store/sqlite/deals.js +270 -156
- package/dist/store/sqlite/entity-types.d.ts +3 -1
- package/dist/store/sqlite/entity-types.js +3 -1
- package/dist/store/sqlite/knowledge.js +3 -1
- package/dist/store/sqlite/migrations.generated.js +39 -11
- package/dist/store/sqlite/ref-summaries.js +11 -7
- package/dist/store/sqlite/schema.d.ts +600 -38
- package/dist/store/sqlite/schema.js +86 -14
- package/dist/store/sqlite/things.js +2 -0
- package/package.json +3 -3
- package/dist/services/proposals/kinds/deals.d.ts +0 -4
- package/dist/services/proposals/kinds/deals.js +0 -32
|
@@ -988,22 +988,50 @@ export const GENERATED = [
|
|
|
988
988
|
{
|
|
989
989
|
"name": "20261106010504_version-52-deals",
|
|
990
990
|
"statements": [
|
|
991
|
-
"CREATE TABLE `
|
|
992
|
-
"CREATE TABLE `
|
|
993
|
-
"CREATE TABLE `
|
|
994
|
-
"CREATE
|
|
995
|
-
"CREATE
|
|
996
|
-
"CREATE INDEX `
|
|
997
|
-
"CREATE INDEX `
|
|
998
|
-
"CREATE INDEX `
|
|
991
|
+
"CREATE TABLE `deals` (\n\t`id` integer PRIMARY KEY,\n\t`title` text NOT NULL,\n\t`organization_id` integer,\n\t`project_id` integer,\n\t`stage_id` integer NOT NULL,\n\t`status` text NOT NULL,\n\t`currency` text,\n\t`amount` integer,\n\t`close_date` text,\n\t`closed_date` text,\n\t`rank` real,\n\t`account_id` integer,\n\t`external_id` text,\n\t`author_type` text NOT NULL,\n\t`author_id` integer NOT NULL,\n\t`model` text,\n\t`source` text NOT NULL,\n\t`metadata` text,\n\t`created_at` integer NOT NULL,\n\t`updated_at` integer NOT NULL,\n\t`deleted_at` integer,\n\tCONSTRAINT `fk_deals_organization_id_organizations_id_fk` FOREIGN KEY (`organization_id`) REFERENCES `organizations`(`id`),\n\tCONSTRAINT `fk_deals_project_id_projects_id_fk` FOREIGN KEY (`project_id`) REFERENCES `projects`(`id`),\n\tCONSTRAINT `fk_deals_stage_id_pipeline_stages_id_fk` FOREIGN KEY (`stage_id`) REFERENCES `pipeline_stages`(`id`),\n\tCONSTRAINT `fk_deals_account_id_accounts_id_fk` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`)\n);",
|
|
992
|
+
"CREATE TABLE `leads` (\n\t`id` integer PRIMARY KEY,\n\t`title` text NOT NULL,\n\t`organization_id` integer,\n\t`project_id` integer,\n\t`stage_id` integer NOT NULL,\n\t`status` text NOT NULL,\n\t`currency` text,\n\t`amount` integer,\n\t`close_date` text,\n\t`closed_date` text,\n\t`rank` real,\n\t`deal_id` integer,\n\t`account_id` integer,\n\t`external_id` text,\n\t`author_type` text NOT NULL,\n\t`author_id` integer NOT NULL,\n\t`model` text,\n\t`source` text NOT NULL,\n\t`metadata` text,\n\t`created_at` integer NOT NULL,\n\t`updated_at` integer NOT NULL,\n\t`deleted_at` integer,\n\tCONSTRAINT `fk_leads_organization_id_organizations_id_fk` FOREIGN KEY (`organization_id`) REFERENCES `organizations`(`id`),\n\tCONSTRAINT `fk_leads_project_id_projects_id_fk` FOREIGN KEY (`project_id`) REFERENCES `projects`(`id`),\n\tCONSTRAINT `fk_leads_stage_id_pipeline_stages_id_fk` FOREIGN KEY (`stage_id`) REFERENCES `pipeline_stages`(`id`),\n\tCONSTRAINT `fk_leads_deal_id_deals_id_fk` FOREIGN KEY (`deal_id`) REFERENCES `deals`(`id`),\n\tCONSTRAINT `fk_leads_account_id_accounts_id_fk` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`)\n);",
|
|
993
|
+
"CREATE TABLE `pipeline_stage_changes` (\n\t`id` integer PRIMARY KEY,\n\t`item_type` text NOT NULL,\n\t`item_id` integer NOT NULL,\n\t`pipeline_id` integer NOT NULL,\n\t`from_stage_id` integer,\n\t`to_stage_id` integer NOT NULL,\n\t`changed_at` integer NOT NULL,\n\tCONSTRAINT `fk_pipeline_stage_changes_pipeline_id_pipelines_id_fk` FOREIGN KEY (`pipeline_id`) REFERENCES `pipelines`(`id`),\n\tCONSTRAINT `fk_pipeline_stage_changes_from_stage_id_pipeline_stages_id_fk` FOREIGN KEY (`from_stage_id`) REFERENCES `pipeline_stages`(`id`),\n\tCONSTRAINT `fk_pipeline_stage_changes_to_stage_id_pipeline_stages_id_fk` FOREIGN KEY (`to_stage_id`) REFERENCES `pipeline_stages`(`id`)\n);",
|
|
994
|
+
"CREATE TABLE `pipeline_stages` (\n\t`id` integer PRIMARY KEY,\n\t`pipeline_id` integer NOT NULL,\n\t`name` text NOT NULL,\n\t`name_folded` text NOT NULL,\n\t`position` integer NOT NULL,\n\t`outcome` text DEFAULT 'open' NOT NULL,\n\t`external_id` text,\n\t`created_at` integer NOT NULL,\n\t`updated_at` integer NOT NULL,\n\tCONSTRAINT `fk_pipeline_stages_pipeline_id_pipelines_id_fk` FOREIGN KEY (`pipeline_id`) REFERENCES `pipelines`(`id`),\n\tCONSTRAINT `pipeline_stages_pipeline_id_name_folded_unique` UNIQUE(`pipeline_id`,`name_folded`)\n);",
|
|
995
|
+
"CREATE TABLE `pipelines` (\n\t`id` integer PRIMARY KEY,\n\t`account_id` integer,\n\t`external_id` text,\n\t`kind` text DEFAULT 'deal' NOT NULL,\n\t`name` text NOT NULL,\n\t`name_folded` text NOT NULL,\n\t`created_at` integer NOT NULL,\n\t`updated_at` integer NOT NULL,\n\tCONSTRAINT `fk_pipelines_account_id_accounts_id_fk` FOREIGN KEY (`account_id`) REFERENCES `accounts`(`id`)\n);",
|
|
996
|
+
"CREATE UNIQUE INDEX `deals_by_account_id_external_id` ON `deals` (`account_id`,`external_id`) WHERE account_id IS NOT NULL AND external_id IS NOT NULL;",
|
|
997
|
+
"CREATE INDEX `deals_by_organization_id` ON `deals` (`organization_id`);",
|
|
998
|
+
"CREATE INDEX `deals_by_project_id` ON `deals` (`project_id`);",
|
|
999
|
+
"CREATE INDEX `deals_by_stage_id` ON `deals` (`stage_id`);",
|
|
1000
|
+
"CREATE INDEX `deals_by_author_type_author_id` ON `deals` (`author_type`,`author_id`);",
|
|
1001
|
+
"CREATE UNIQUE INDEX `leads_by_account_id_external_id` ON `leads` (`account_id`,`external_id`) WHERE account_id IS NOT NULL AND external_id IS NOT NULL;",
|
|
1002
|
+
"CREATE INDEX `leads_by_organization_id` ON `leads` (`organization_id`);",
|
|
1003
|
+
"CREATE INDEX `leads_by_project_id` ON `leads` (`project_id`);",
|
|
1004
|
+
"CREATE INDEX `leads_by_stage_id` ON `leads` (`stage_id`);",
|
|
1005
|
+
"CREATE INDEX `leads_by_deal_id` ON `leads` (`deal_id`);",
|
|
1006
|
+
"CREATE INDEX `leads_by_author_type_author_id` ON `leads` (`author_type`,`author_id`);",
|
|
1007
|
+
"CREATE INDEX `pipeline_stage_changes_by_item_type_item_id` ON `pipeline_stage_changes` (`item_type`,`item_id`);",
|
|
1008
|
+
"CREATE INDEX `pipeline_stage_changes_by_pipeline_id` ON `pipeline_stage_changes` (`pipeline_id`);",
|
|
1009
|
+
"CREATE INDEX `pipeline_stage_changes_by_from_stage_id` ON `pipeline_stage_changes` (`from_stage_id`);",
|
|
1010
|
+
"CREATE INDEX `pipeline_stage_changes_by_to_stage_id` ON `pipeline_stage_changes` (`to_stage_id`);",
|
|
1011
|
+
"CREATE UNIQUE INDEX `pipeline_stages_by_pipeline_id_external_id` ON `pipeline_stages` (`pipeline_id`,`external_id`) WHERE external_id IS NOT NULL;",
|
|
1012
|
+
"CREATE INDEX `pipeline_stages_by_pipeline_id_position` ON `pipeline_stages` (`pipeline_id`,`position`);",
|
|
1013
|
+
"CREATE UNIQUE INDEX `pipelines_by_account_id_external_id` ON `pipelines` (`account_id`,`external_id`) WHERE account_id IS NOT NULL AND external_id IS NOT NULL;",
|
|
1014
|
+
"CREATE UNIQUE INDEX `pipelines_by_name_folded_kind` ON `pipelines` (`name_folded`,`kind`) WHERE account_id IS NULL;"
|
|
999
1015
|
]
|
|
1000
1016
|
},
|
|
1001
1017
|
{
|
|
1002
1018
|
"name": "20261106010507_version-52-deals-rules",
|
|
1003
1019
|
"statements": [
|
|
1004
|
-
"-- The store's code checks these first and says why; the triggers keep a stray write from another build or a
|
|
1005
|
-
"CREATE TRIGGER
|
|
1006
|
-
"
|
|
1020
|
+
"-- The store's code checks these first and says why; the triggers keep a stray write from another build, a sync or a\n-- hand edit from storing a row the store's code would refuse.\nCREATE TRIGGER pipelines_valid_bi BEFORE INSERT ON pipelines WHEN new.kind NOT IN ('deal', 'lead') BEGIN\n SELECT RAISE(ABORT, 'pipelines: kind is deal or lead');\nEND;",
|
|
1021
|
+
"CREATE TRIGGER pipelines_valid_bu BEFORE UPDATE ON pipelines WHEN new.kind NOT IN ('deal', 'lead') BEGIN\n SELECT RAISE(ABORT, 'pipelines: kind is deal or lead');\nEND;",
|
|
1022
|
+
"CREATE TRIGGER pipelines_kind_bu BEFORE UPDATE OF kind ON pipelines\n WHEN new.kind <> old.kind AND EXISTS (SELECT 1 FROM pipeline_stages s WHERE s.pipeline_id = new.id\n AND (EXISTS (SELECT 1 FROM deals d WHERE d.stage_id = s.id) OR EXISTS (SELECT 1 FROM leads l WHERE l.stage_id = s.id))) BEGIN\n SELECT RAISE(ABORT, 'pipelines: the kind of a pipeline that holds deals or leads stays');\nEND;",
|
|
1023
|
+
"CREATE TRIGGER pipeline_stages_valid_bi BEFORE INSERT ON pipeline_stages\n WHEN new.outcome NOT IN ('open', 'won', 'lost') BEGIN\n SELECT RAISE(ABORT, 'pipeline_stages: outcome is open, won or lost');\nEND;",
|
|
1024
|
+
"CREATE TRIGGER pipeline_stages_valid_bu BEFORE UPDATE ON pipeline_stages\n WHEN new.outcome NOT IN ('open', 'won', 'lost') BEGIN\n SELECT RAISE(ABORT, 'pipeline_stages: outcome is open, won or lost');\nEND;",
|
|
1025
|
+
"CREATE TRIGGER deals_valid_bi BEFORE INSERT ON deals\n WHEN new.status NOT IN ('open', 'won', 'lost')\n OR (new.amount IS NULL) <> (new.currency IS NULL) OR new.amount < 0\n OR (SELECT p.kind FROM pipeline_stages s JOIN pipelines p ON p.id = s.pipeline_id WHERE s.id = new.stage_id) IS NOT 'deal' BEGIN\n SELECT RAISE(ABORT, 'deals: a known status, an amount with its currency, and a stage of a deal pipeline');\nEND;",
|
|
1026
|
+
"CREATE TRIGGER deals_valid_bu BEFORE UPDATE ON deals\n WHEN new.status NOT IN ('open', 'won', 'lost')\n OR (new.amount IS NULL) <> (new.currency IS NULL) OR new.amount < 0\n OR (SELECT p.kind FROM pipeline_stages s JOIN pipelines p ON p.id = s.pipeline_id WHERE s.id = new.stage_id) IS NOT 'deal' BEGIN\n SELECT RAISE(ABORT, 'deals: a known status, an amount with its currency, and a stage of a deal pipeline');\nEND;",
|
|
1027
|
+
"-- Every stage a row enters, with the time its writer gave, is what conversion between stages is counted from.\nCREATE TRIGGER deals_stage_ai AFTER INSERT ON deals BEGIN\n INSERT INTO pipeline_stage_changes (item_type, item_id, pipeline_id, from_stage_id, to_stage_id, changed_at)\n SELECT 'deal', new.id, s.pipeline_id, NULL, new.stage_id, new.created_at FROM pipeline_stages s WHERE s.id = new.stage_id;\nEND;",
|
|
1028
|
+
"CREATE TRIGGER deals_stage_au AFTER UPDATE OF stage_id ON deals WHEN new.stage_id IS NOT old.stage_id BEGIN\n INSERT INTO pipeline_stage_changes (item_type, item_id, pipeline_id, from_stage_id, to_stage_id, changed_at)\n SELECT 'deal', new.id, s.pipeline_id, old.stage_id, new.stage_id, new.updated_at FROM pipeline_stages s WHERE s.id = new.stage_id;\nEND;",
|
|
1029
|
+
"CREATE TRIGGER leads_valid_bi BEFORE INSERT ON leads\n WHEN new.status NOT IN ('open', 'won', 'lost')\n OR (new.amount IS NULL) <> (new.currency IS NULL) OR new.amount < 0\n OR (SELECT p.kind FROM pipeline_stages s JOIN pipelines p ON p.id = s.pipeline_id WHERE s.id = new.stage_id) IS NOT 'lead' BEGIN\n SELECT RAISE(ABORT, 'leads: a known status, an amount with its currency, and a stage of a lead pipeline');\nEND;",
|
|
1030
|
+
"CREATE TRIGGER leads_valid_bu BEFORE UPDATE ON leads\n WHEN new.status NOT IN ('open', 'won', 'lost')\n OR (new.amount IS NULL) <> (new.currency IS NULL) OR new.amount < 0\n OR (SELECT p.kind FROM pipeline_stages s JOIN pipelines p ON p.id = s.pipeline_id WHERE s.id = new.stage_id) IS NOT 'lead' BEGIN\n SELECT RAISE(ABORT, 'leads: a known status, an amount with its currency, and a stage of a lead pipeline');\nEND;",
|
|
1031
|
+
"CREATE TRIGGER leads_stage_ai AFTER INSERT ON leads BEGIN\n INSERT INTO pipeline_stage_changes (item_type, item_id, pipeline_id, from_stage_id, to_stage_id, changed_at)\n SELECT 'lead', new.id, s.pipeline_id, NULL, new.stage_id, new.created_at FROM pipeline_stages s WHERE s.id = new.stage_id;\nEND;",
|
|
1032
|
+
"CREATE TRIGGER leads_stage_au AFTER UPDATE OF stage_id ON leads WHEN new.stage_id IS NOT old.stage_id BEGIN\n INSERT INTO pipeline_stage_changes (item_type, item_id, pipeline_id, from_stage_id, to_stage_id, changed_at)\n SELECT 'lead', new.id, s.pipeline_id, old.stage_id, new.stage_id, new.updated_at FROM pipeline_stages s WHERE s.id = new.stage_id;\nEND;",
|
|
1033
|
+
"-- The default lead pipeline, so a lead can be recorded before the owner or an agent makes one.\nINSERT INTO pipelines (kind, name, name_folded, created_at, updated_at)\n VALUES ('lead', 'Leads', 'leads', CAST(strftime('%s', 'now') AS INTEGER) * 1000, CAST(strftime('%s', 'now') AS INTEGER) * 1000);",
|
|
1034
|
+
"INSERT INTO pipeline_stages (pipeline_id, name, name_folded, position, outcome, created_at, updated_at)\n SELECT p.id, v.name, v.name, v.position, v.outcome, p.created_at, p.created_at FROM pipelines p,\n (SELECT 'new' AS name, 1 AS position, 'open' AS outcome UNION ALL SELECT 'contacted', 2, 'open'\n UNION ALL SELECT 'qualified', 3, 'open' UNION ALL SELECT 'won', 4, 'won' UNION ALL SELECT 'lost', 5, 'lost') v\n WHERE p.kind = 'lead' AND p.name_folded = 'leads' AND p.account_id IS NULL;"
|
|
1007
1035
|
]
|
|
1008
1036
|
}
|
|
1009
1037
|
];
|
|
@@ -35,6 +35,13 @@ const byId = (kind, table, columns) => ({
|
|
|
35
35
|
kind,
|
|
36
36
|
sql: (body) => `${select(columns(body))} FROM w JOIN ${table} x ON x.id = w.k1`,
|
|
37
37
|
});
|
|
38
|
+
const crmColumns = () => ({
|
|
39
|
+
title: "json_object('id', x.id, 'title', x.title, 'stage', (SELECT name FROM pipeline_stages WHERE id = x.stage_id), " +
|
|
40
|
+
"'amount', x.amount, 'currency', x.currency, 'status', x.status)",
|
|
41
|
+
holder: "(SELECT name FROM projects WHERE id = x.project_id)",
|
|
42
|
+
at: "x.created_at",
|
|
43
|
+
deleted: "x.deleted_at",
|
|
44
|
+
});
|
|
38
45
|
const READERS = {
|
|
39
46
|
message: {
|
|
40
47
|
kind: "message",
|
|
@@ -208,13 +215,9 @@ const READERS = {
|
|
|
208
215
|
at: "x.created_at",
|
|
209
216
|
deleted: "x.deleted_at",
|
|
210
217
|
})),
|
|
211
|
-
deal: byId("deal", "
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
holder: "(SELECT name FROM projects WHERE id = x.project_id)",
|
|
215
|
-
at: "x.created_at",
|
|
216
|
-
deleted: "x.deleted_at",
|
|
217
|
-
})),
|
|
218
|
+
deal: byId("deal", "deals", crmColumns),
|
|
219
|
+
lead: byId("lead", "leads", crmColumns),
|
|
220
|
+
pipeline: byId("pipeline", "pipelines", () => ({ title: "x.name", at: "x.created_at" })),
|
|
218
221
|
};
|
|
219
222
|
/** Mail saved before the mail tables existed is still messages, so a miss there is read again as a message. */
|
|
220
223
|
const FALLBACK = { email: "message", email_thread: "chat" };
|
|
@@ -323,6 +326,7 @@ const titleOf = (kind, reference, found) => {
|
|
|
323
326
|
case "order":
|
|
324
327
|
return fieldsOf(found.title, orderLine);
|
|
325
328
|
case "deal":
|
|
329
|
+
case "lead":
|
|
326
330
|
return fieldsOf(found.title, dealLine);
|
|
327
331
|
case "folder":
|
|
328
332
|
return reference.type === "folder" && reference.path !== null && found.title !== null
|