@openinc/parse-server-opendash 4.1.1 → 4.1.2
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/featuremap.json +27 -12
- package/dist/features/config/helper/customOptions.js +9 -0
- package/dist/features/config/helper/isFeatureEnabled.d.ts +1 -1
- package/dist/features/config/helper/isFeatureEnabled.js +2 -0
- package/dist/features/meta/index.d.ts +1 -0
- package/dist/features/meta/index.js +5 -0
- package/dist/features/meta/services/registerMetaContext.d.ts +29 -0
- package/dist/features/meta/services/registerMetaContext.js +208 -0
- package/dist/features/permissions/types/Permissions.d.ts +24 -1
- package/dist/features/permissions/types/Permissions.js +34 -0
- package/dist/features/ruleset/applyRuleSet.d.ts +41 -0
- package/dist/features/ruleset/applyRuleSet.js +81 -0
- package/dist/features/schema/helper/defaultHandler.js +13 -0
- package/dist/features/schema/helper/migrationMode.d.ts +26 -0
- package/dist/features/schema/helper/migrationMode.js +48 -0
- package/dist/features/schema/index.d.ts +1 -0
- package/dist/features/schema/index.js +3 -1
- package/dist/features/schema/services/beforeSaveHook.js +21 -0
- package/dist/features/translations/services/initTranslation.js +1 -1
- package/dist/hooks/Chat_Message.d.ts +1 -0
- package/dist/hooks/Chat_Message.js +179 -0
- package/dist/hooks/Meta_Config.js +19 -10
- package/dist/hooks/Meta_Context.d.ts +6 -0
- package/dist/hooks/Meta_Context.js +16 -0
- package/dist/hooks/Meta_Entry.js +20 -10
- package/dist/hooks/Service_Equipment.d.ts +1 -0
- package/dist/hooks/Service_Equipment.js +38 -0
- package/dist/hooks/Service_FormConfig.d.ts +1 -0
- package/dist/hooks/Service_FormConfig.js +17 -0
- package/dist/hooks/Service_Project.d.ts +1 -0
- package/dist/hooks/Service_Project.js +17 -0
- package/dist/hooks/Service_Schedule.d.ts +1 -0
- package/dist/hooks/Service_Schedule.js +24 -0
- package/dist/hooks/Service_Schedule_Execution.d.ts +1 -0
- package/dist/hooks/Service_Schedule_Execution.js +17 -0
- package/dist/hooks/Service_Schedule_Template.d.ts +1 -0
- package/dist/hooks/Service_Schedule_Template.js +17 -0
- package/dist/hooks/Service_Status.d.ts +1 -0
- package/dist/hooks/Service_Status.js +32 -0
- package/dist/hooks/Service_Tag.d.ts +1 -0
- package/dist/hooks/Service_Tag.js +168 -0
- package/dist/hooks/Service_Ticket.d.ts +1 -0
- package/dist/hooks/Service_Ticket.js +433 -0
- package/dist/hooks/Service_TriggerState.d.ts +1 -0
- package/dist/hooks/Service_TriggerState.js +17 -0
- package/dist/hooks/_ChangeLog.js +27 -6
- package/dist/i18n/de-DE/chat.json +18 -0
- package/dist/i18n/de-DE/openservice.json +14 -0
- package/dist/i18n/en-US/chat.json +18 -0
- package/dist/i18n/en-US/openservice.json +14 -0
- package/dist/scripts/backfill-meta-contexts.d.ts +1 -0
- package/dist/scripts/backfill-meta-contexts.js +100 -0
- package/dist/scripts/migration/lib/acl.d.ts +52 -0
- package/dist/scripts/migration/lib/acl.js +79 -0
- package/dist/scripts/migration/lib/articleMeta.d.ts +47 -0
- package/dist/scripts/migration/lib/articleMeta.js +132 -0
- package/dist/scripts/migration/lib/env.d.ts +56 -0
- package/dist/scripts/migration/lib/env.js +106 -0
- package/dist/scripts/migration/lib/latest.d.ts +47 -0
- package/dist/scripts/migration/lib/latest.js +115 -0
- package/dist/scripts/migration/lib/map.d.ts +53 -0
- package/dist/scripts/migration/lib/map.js +113 -0
- package/dist/scripts/migration/lib/material.d.ts +47 -0
- package/dist/scripts/migration/lib/material.js +51 -0
- package/dist/scripts/migration/lib/message.d.ts +78 -0
- package/dist/scripts/migration/lib/message.js +115 -0
- package/dist/scripts/migration/lib/pass.d.ts +67 -0
- package/dist/scripts/migration/lib/pass.js +89 -0
- package/dist/scripts/migration/lib/ptr.d.ts +32 -0
- package/dist/scripts/migration/lib/ptr.js +38 -0
- package/dist/scripts/migration/lib/report.d.ts +41 -0
- package/dist/scripts/migration/lib/report.js +78 -0
- package/dist/scripts/migration/lib/rest.d.ts +47 -0
- package/dist/scripts/migration/lib/rest.js +68 -0
- package/dist/scripts/migration/lib/ticket.d.ts +72 -0
- package/dist/scripts/migration/lib/ticket.js +192 -0
- package/dist/scripts/migration/passes/01-statuses.d.ts +12 -0
- package/dist/scripts/migration/passes/01-statuses.js +122 -0
- package/dist/scripts/migration/passes/02-tags.d.ts +13 -0
- package/dist/scripts/migration/passes/02-tags.js +150 -0
- package/dist/scripts/migration/passes/03-equipment.d.ts +14 -0
- package/dist/scripts/migration/passes/03-equipment.js +176 -0
- package/dist/scripts/migration/passes/04-projects.d.ts +27 -0
- package/dist/scripts/migration/passes/04-projects.js +241 -0
- package/dist/scripts/migration/passes/05-articles.d.ts +25 -0
- package/dist/scripts/migration/passes/05-articles.js +203 -0
- package/dist/scripts/migration/passes/06-formconfigs.d.ts +17 -0
- package/dist/scripts/migration/passes/06-formconfigs.js +166 -0
- package/dist/scripts/migration/passes/07-meta-configs.d.ts +46 -0
- package/dist/scripts/migration/passes/07-meta-configs.js +185 -0
- package/dist/scripts/migration/passes/08-tickets.d.ts +27 -0
- package/dist/scripts/migration/passes/08-tickets.js +353 -0
- package/dist/scripts/migration/passes/09-ticket-meta.d.ts +12 -0
- package/dist/scripts/migration/passes/09-ticket-meta.js +136 -0
- package/dist/scripts/migration/passes/10-chat.d.ts +17 -0
- package/dist/scripts/migration/passes/10-chat.js +230 -0
- package/dist/scripts/migration/passes/11-assets.d.ts +17 -0
- package/dist/scripts/migration/passes/11-assets.js +93 -0
- package/dist/scripts/migration/passes/12-history.d.ts +24 -0
- package/dist/scripts/migration/passes/12-history.js +332 -0
- package/dist/scripts/migration/run.d.ts +1 -0
- package/dist/scripts/migration/run.js +148 -0
- package/dist/scripts/migration/verify.d.ts +1 -0
- package/dist/scripts/migration/verify.js +620 -0
- package/dist/scripts/seed-v1-testdata.d.ts +41 -0
- package/dist/scripts/seed-v1-testdata.js +543 -0
- package/dist/types/BDE_Article.d.ts +3 -0
- package/dist/types/BDE_Article.js +6 -0
- package/dist/types/Chat_Message.d.ts +49 -0
- package/dist/types/Chat_Message.js +87 -0
- package/dist/types/MES_RessourceOverview.d.ts +38 -0
- package/dist/types/MES_RessourceOverview.js +63 -0
- package/dist/types/Meta_Context.d.ts +43 -0
- package/dist/types/Meta_Context.js +75 -0
- package/dist/types/Service_Equipment.d.ts +33 -0
- package/dist/types/Service_Equipment.js +57 -0
- package/dist/types/Service_FormConfig.d.ts +33 -0
- package/dist/types/Service_FormConfig.js +57 -0
- package/dist/types/Service_MeterReading.d.ts +35 -0
- package/dist/types/Service_MeterReading.js +57 -0
- package/dist/types/Service_Project.d.ts +53 -0
- package/dist/types/Service_Project.js +93 -0
- package/dist/types/Service_Schedule.d.ts +66 -0
- package/dist/types/Service_Schedule.js +117 -0
- package/dist/types/Service_Schedule_Execution.d.ts +38 -0
- package/dist/types/Service_Schedule_Execution.js +63 -0
- package/dist/types/Service_Schedule_Template.d.ts +36 -0
- package/dist/types/Service_Schedule_Template.js +60 -0
- package/dist/types/Service_Status.d.ts +30 -0
- package/dist/types/Service_Status.js +51 -0
- package/dist/types/Service_Tag.d.ts +30 -0
- package/dist/types/Service_Tag.js +51 -0
- package/dist/types/Service_Ticket.d.ts +92 -0
- package/dist/types/Service_Ticket.js +165 -0
- package/dist/types/Service_TicketCounter.d.ts +18 -0
- package/dist/types/Service_TicketCounter.js +27 -0
- package/dist/types/Service_TriggerState.d.ts +31 -0
- package/dist/types/Service_TriggerState.js +51 -0
- package/dist/types/_Session.d.ts +0 -1
- package/dist/types/_User.d.ts +2 -6
- package/dist/types/custom/MetaField.d.ts +9 -0
- package/dist/types/custom/TicketMaterial.d.ts +32 -0
- package/dist/types/custom/TicketMaterial.js +2 -0
- package/dist/types/index.d.ts +30 -0
- package/dist/types/index.js +33 -3
- package/package.json +6 -3
- package/schema/BDE_Article.json +3 -0
- package/schema/Changelog.json +3 -6
- package/schema/Chat_Message.json +88 -0
- package/schema/Meta_Context.json +78 -0
- package/schema/Service_Equipment.json +55 -0
- package/schema/Service_FormConfig.json +66 -0
- package/schema/Service_MeterReading.json +54 -0
- package/schema/Service_MigrationMap.json +55 -0
- package/schema/Service_Project.json +77 -0
- package/schema/Service_Schedule.json +101 -0
- package/schema/Service_Schedule_Execution.json +58 -0
- package/schema/Service_Schedule_Template.json +73 -0
- package/schema/Service_Status.json +50 -0
- package/schema/Service_Tag.json +50 -0
- package/schema/Service_Ticket.json +114 -0
- package/schema/Service_TicketCounter.json +38 -0
- package/schema/Service_TriggerState.json +50 -0
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Seed **v1** (`OD3_Maintenance_*`) test data, for exercising the v1 → v2 migration.
|
|
4
|
+
*
|
|
5
|
+
* DEV ONLY. Never run this against production.
|
|
6
|
+
*
|
|
7
|
+
* OD_MIGRATION_MODE=1 PARSE_APP_ID=… PARSE_MAINTENANCE_KEY=… \
|
|
8
|
+
* node dist/scripts/seed-v1-testdata.js [--purge]
|
|
9
|
+
*
|
|
10
|
+
* ## Why the maintenance key
|
|
11
|
+
*
|
|
12
|
+
* Realistic timestamps are the whole point. The migration's fold picks the newest
|
|
13
|
+
* side-table row and its replay builds a timeline from them — neither can be tested
|
|
14
|
+
* against data where every row was created in the same second. Historical
|
|
15
|
+
* `createdAt` / `updatedAt` require the maintenance key, so this seeder needs the
|
|
16
|
+
* same setup as the migration. That makes it a useful smoke test of the write path
|
|
17
|
+
* in its own right: if this runs, the migration's transport works.
|
|
18
|
+
*
|
|
19
|
+
* ## Why OD_MIGRATION_MODE
|
|
20
|
+
*
|
|
21
|
+
* All 29 v1 hooks call `defaultHandler`, which throws on a request with no user —
|
|
22
|
+
* and maintenance-key requests have none. The flag gates that off, so this seeder
|
|
23
|
+
* sets `tenant`, `user` and ACLs itself, exactly as the migration does.
|
|
24
|
+
*
|
|
25
|
+
* ## What it deliberately includes
|
|
26
|
+
*
|
|
27
|
+
* Every case the migration audits turned up, so a dry run has something to say:
|
|
28
|
+
*
|
|
29
|
+
* - two tenants, each with their own kanban states and meta fields
|
|
30
|
+
* - a ticket with no kanban state at all (inbox fallback)
|
|
31
|
+
* - a ticket with `enabled: false`, and one with `enabled` *unset*
|
|
32
|
+
* - side-table rows where `updatedAt` disagrees with `createdAt` ordering
|
|
33
|
+
* - a completed todo, and a todo whose title is an i18n key
|
|
34
|
+
* - a comment with an i18n-key title, and one with no author but an attachment
|
|
35
|
+
* - a source with no tag, and a source tree needing ancestors
|
|
36
|
+
* - an item with a German-decimal price and one with an unparseable price
|
|
37
|
+
* - a two-level issue-category tree (closure expansion)
|
|
38
|
+
* - an assignment batch (three rows, one `batchStamp`)
|
|
39
|
+
* - a message referencing a non-ticket object (orphan skip)
|
|
40
|
+
* - assets on a real and on a `temp-` media context
|
|
41
|
+
*/
|
|
42
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
43
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
44
|
+
};
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
const node_1 = __importDefault(require("parse/node"));
|
|
47
|
+
const acl_js_1 = require("./migration/lib/acl.js");
|
|
48
|
+
const env_js_1 = require("./migration/lib/env.js");
|
|
49
|
+
const rest_js_1 = require("./migration/lib/rest.js");
|
|
50
|
+
// ── helpers ────────────────────────────────────────────────────────────────
|
|
51
|
+
const ptr = (className, objectId) => ({
|
|
52
|
+
__type: "Pointer",
|
|
53
|
+
className,
|
|
54
|
+
objectId,
|
|
55
|
+
});
|
|
56
|
+
const dateVal = (d) => ({ __type: "Date", iso: d.toISOString() });
|
|
57
|
+
/** Days before now, at a fixed time of day so runs are comparable. */
|
|
58
|
+
function daysAgo(days, hour = 9) {
|
|
59
|
+
const d = new Date();
|
|
60
|
+
d.setDate(d.getDate() - days);
|
|
61
|
+
d.setHours(hour, 0, 0, 0);
|
|
62
|
+
return d;
|
|
63
|
+
}
|
|
64
|
+
/** Marker so `--purge` can find exactly what this seeder created. */
|
|
65
|
+
const SEED_MARKER = "seed:v1-testdata";
|
|
66
|
+
async function create(ctx, className, payload, createdAt, updatedAt) {
|
|
67
|
+
const tenantId = payload.tenant?.objectId;
|
|
68
|
+
const userId = payload.user?.objectId;
|
|
69
|
+
const body = {
|
|
70
|
+
...payload,
|
|
71
|
+
ACL: (0, acl_js_1.migrationAcl)({
|
|
72
|
+
tenantId,
|
|
73
|
+
userId,
|
|
74
|
+
allowTenantUserWrite: true,
|
|
75
|
+
}).toJSON(),
|
|
76
|
+
};
|
|
77
|
+
const result = await (0, rest_js_1.restCreateRaw)(ctx.config, className, body, createdAt, updatedAt);
|
|
78
|
+
ctx.created.set(className, (ctx.created.get(className) ?? 0) + 1);
|
|
79
|
+
return result.objectId;
|
|
80
|
+
}
|
|
81
|
+
/** Remove a field entirely, which a schema `defaultValue` otherwise prevents. */
|
|
82
|
+
async function unsetField(config, className, objectId, field) {
|
|
83
|
+
const response = await fetch(`${config.parseUrl}/classes/${className}/${objectId}`, {
|
|
84
|
+
method: "PUT",
|
|
85
|
+
headers: {
|
|
86
|
+
"X-Parse-Application-Id": config.appId,
|
|
87
|
+
"X-Parse-Maintenance-Key": config.maintenanceKey,
|
|
88
|
+
"X-Parse-Cloud-Context": JSON.stringify({ skipChangelog: true }),
|
|
89
|
+
"Content-Type": "application/json",
|
|
90
|
+
},
|
|
91
|
+
body: JSON.stringify({ [field]: { __op: "Delete" } }),
|
|
92
|
+
});
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
throw new Error(`unset ${className}.${field} → ${response.status}: ${(await response.text()).slice(0, 200)}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// ── the data ───────────────────────────────────────────────────────────────
|
|
98
|
+
async function seed(ctx) {
|
|
99
|
+
const { tenantId, tenant2Id, userId, roleId } = ctx;
|
|
100
|
+
const tenant = ptr("OD3_Tenant", tenantId);
|
|
101
|
+
const tenant2 = ptr("OD3_Tenant", tenant2Id);
|
|
102
|
+
const user = ptr("_User", userId);
|
|
103
|
+
// ── sources: a two-level tree, plus one with no tag, plus one nothing uses ──
|
|
104
|
+
const hallId = await create(ctx, "OD3_Source", { name: "Halle B", tag: "halle-b", tenant }, daysAgo(400));
|
|
105
|
+
const cncId = await create(ctx, "OD3_Source", { name: "CNC-04", tag: "cnc-04", parent: ptr("OD3_Source", hallId), tenant }, daysAgo(395));
|
|
106
|
+
// No tag: pass 03 must warn that this equipment cannot match a source.
|
|
107
|
+
const untaggedId = await create(ctx, "OD3_Source", { name: "Presse A (ohne Tag)", parent: ptr("OD3_Source", hallId), tenant }, daysAgo(390));
|
|
108
|
+
// Referenced by nothing: pass 03 must skip it (D3).
|
|
109
|
+
await create(ctx, "OD3_Source", { name: "Sensor XYZ (unreferenziert)", tag: "sensor-xyz", tenant }, daysAgo(380));
|
|
110
|
+
// ── kanban states: tenant 1 reuses the auto-seeded ones, plus a working state.
|
|
111
|
+
const inProgressId = await create(ctx, "OD3_Maintenance_Kanban_State", { label: "In Arbeit", order: 50, color: "#cce5ff", enabled: true, tenant }, daysAgo(370));
|
|
112
|
+
const finishedId = await create(ctx, "OD3_Maintenance_Kanban_State", {
|
|
113
|
+
label: "Erledigt",
|
|
114
|
+
order: 90,
|
|
115
|
+
color: "#d4edda",
|
|
116
|
+
isFinished: true,
|
|
117
|
+
enabled: true,
|
|
118
|
+
description: "Wird beim Abschluss gesetzt",
|
|
119
|
+
tenant,
|
|
120
|
+
}, daysAgo(370));
|
|
121
|
+
const inboxId = await create(ctx, "OD3_Maintenance_Kanban_State", { label: "Eingang", order: 10, isInbox: true, enabled: true, tenant }, daysAgo(370));
|
|
122
|
+
// A disabled state -> deleted: true in v2.
|
|
123
|
+
await create(ctx, "OD3_Maintenance_Kanban_State", { label: "Alt / stillgelegt", order: 99, enabled: false, tenant }, daysAgo(360));
|
|
124
|
+
// Tenant 2 gets its own, so the multi-tenant path is exercised.
|
|
125
|
+
await create(ctx, "OD3_Maintenance_Kanban_State", { label: "Offen (T2)", order: 10, isInbox: true, enabled: true, tenant: tenant2 }, daysAgo(360));
|
|
126
|
+
// ── issue categories: two levels, so the closure has something to expand ──
|
|
127
|
+
const mechId = await create(ctx, "OD3_Maintenance_Issuecategory", { name: "Mechanik", enabled: true, issuecode: "100", icon: "fa:gear", tenant }, daysAgo(350));
|
|
128
|
+
const bearingId = await create(ctx, "OD3_Maintenance_Issuecategory", {
|
|
129
|
+
name: "Lagerschaden",
|
|
130
|
+
parent: ptr("OD3_Maintenance_Issuecategory", mechId),
|
|
131
|
+
enabled: true,
|
|
132
|
+
issuecode: "110",
|
|
133
|
+
tenant,
|
|
134
|
+
}, daysAgo(349));
|
|
135
|
+
// ── projects: a parent/child pair, one finished ───────────────────────────
|
|
136
|
+
const projectId = await create(ctx, "OD3_Maintenance_Project", {
|
|
137
|
+
name: "Instandhaltung 2025",
|
|
138
|
+
description: "Laufende Instandhaltung",
|
|
139
|
+
color: "#4f7f2c",
|
|
140
|
+
start: dateVal(daysAgo(330)),
|
|
141
|
+
user,
|
|
142
|
+
tenant,
|
|
143
|
+
}, daysAgo(330));
|
|
144
|
+
await create(ctx, "OD3_Maintenance_Project", {
|
|
145
|
+
name: "Umbau Halle B (abgeschlossen)",
|
|
146
|
+
parent: ptr("OD3_Maintenance_Project", projectId),
|
|
147
|
+
finished: true,
|
|
148
|
+
user,
|
|
149
|
+
tenant,
|
|
150
|
+
}, daysAgo(320));
|
|
151
|
+
// ── items: German decimal, unparseable, and a source link ────────────────
|
|
152
|
+
const itemDichtung = await create(ctx, "OD3_Maintenance_Item", {
|
|
153
|
+
name: "Dichtung 12mm",
|
|
154
|
+
price: "12,50 €",
|
|
155
|
+
stock: 42,
|
|
156
|
+
stockUnit: "Stk",
|
|
157
|
+
internalNumber: "D-12",
|
|
158
|
+
storageLocation: "Regal 3",
|
|
159
|
+
supplier: "Muster GmbH",
|
|
160
|
+
tenant,
|
|
161
|
+
// v1 linked an item to the sources it belongs to via a Relation. Pass 05
|
|
162
|
+
// resolves those through the pass-03 map and stores the migrated Equipment
|
|
163
|
+
// ids on the article meta entry. Seeded so that path is covered — the
|
|
164
|
+
// comment above promised a source link that was never actually created.
|
|
165
|
+
sources: {
|
|
166
|
+
__op: "AddRelation",
|
|
167
|
+
objects: [
|
|
168
|
+
{ __type: "Pointer", className: "OD3_Source", objectId: cncId },
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
}, daysAgo(300));
|
|
172
|
+
const itemOel = await create(ctx, "OD3_Maintenance_Item", { name: "Spezialöl", price: "auf Anfrage", stock: 3, tenant }, daysAgo(299));
|
|
173
|
+
// ── ticket 1: the rich one. History across several side tables. ───────────
|
|
174
|
+
const t1 = await create(ctx, "OD3_Maintenance_Ticket", {
|
|
175
|
+
title: "Lager läuft heiß",
|
|
176
|
+
description: "Temperatur an Spindel steigt seit Tagen.",
|
|
177
|
+
enabled: true,
|
|
178
|
+
latestPriorityValue: 80,
|
|
179
|
+
project: ptr("OD3_Maintenance_Project", projectId),
|
|
180
|
+
// `kostenstelle` and `schicht` are defined by the form config below;
|
|
181
|
+
// `altfeld` is NOT — it only exists here, which is exactly the case pass 07
|
|
182
|
+
// unions in from tickets so pass 09 does not write an undefined-able value.
|
|
183
|
+
meta: {
|
|
184
|
+
fields: [
|
|
185
|
+
{ name: "kostenstelle", label: "Kostenstelle", type: "string", value: "4711" },
|
|
186
|
+
{ name: "schicht", label: "Schicht", type: "select", options: ["Früh", "Spät", "Nacht"], value: "Spät" },
|
|
187
|
+
{ name: "altfeld", label: "Altes Feld", type: "string", value: "nur am Ticket" },
|
|
188
|
+
],
|
|
189
|
+
},
|
|
190
|
+
user,
|
|
191
|
+
tenant,
|
|
192
|
+
}, daysAgo(60, 8));
|
|
193
|
+
// Priority raised over time -> a real timeline.
|
|
194
|
+
await create(ctx, "OD3_Maintenance_Priority", { ticket: ptr("OD3_Maintenance_Ticket", t1), value: 20, user, tenant }, daysAgo(60, 9));
|
|
195
|
+
await create(ctx, "OD3_Maintenance_Priority", { ticket: ptr("OD3_Maintenance_Ticket", t1), value: 60, user, tenant }, daysAgo(40, 9));
|
|
196
|
+
await create(ctx, "OD3_Maintenance_Priority", { ticket: ptr("OD3_Maintenance_Ticket", t1), value: 80, user, tenant }, daysAgo(10, 9));
|
|
197
|
+
// THE `effectiveAt` CASE: created earlier but edited later, so `updatedAt`
|
|
198
|
+
// ordering differs from `createdAt` ordering. The fold and the replay must agree
|
|
199
|
+
// on which of these two wins.
|
|
200
|
+
await create(ctx, "OD3_Maintenance_Downtime", { ticket: ptr("OD3_Maintenance_Ticket", t1), value: 30, user, tenant }, daysAgo(50, 9), daysAgo(5, 9));
|
|
201
|
+
await create(ctx, "OD3_Maintenance_Downtime", { ticket: ptr("OD3_Maintenance_Ticket", t1), value: 15, user, tenant }, daysAgo(20, 9), daysAgo(20, 9));
|
|
202
|
+
await create(ctx, "OD3_Maintenance_Frequency", { ticket: ptr("OD3_Maintenance_Ticket", t1), value: 40, user, tenant }, daysAgo(45, 9));
|
|
203
|
+
await create(ctx, "OD3_Maintenance_Restriction", { ticket: ptr("OD3_Maintenance_Ticket", t1), value: 60, user, tenant }, daysAgo(45, 10));
|
|
204
|
+
await create(ctx, "OD3_Maintenance_Duedate", {
|
|
205
|
+
ticket: ptr("OD3_Maintenance_Ticket", t1),
|
|
206
|
+
start: dateVal(daysAgo(30)),
|
|
207
|
+
end: dateVal(daysAgo(-14)),
|
|
208
|
+
startformat: "date",
|
|
209
|
+
endformat: "date",
|
|
210
|
+
user,
|
|
211
|
+
tenant,
|
|
212
|
+
}, daysAgo(30, 11));
|
|
213
|
+
// Title changed after creation -> the fold must prefer the override.
|
|
214
|
+
await create(ctx, "OD3_Maintenance_Ticket_Title", { ticket: ptr("OD3_Maintenance_Ticket", t1), title: "Lager läuft heiß (Spindel 2)", user, tenant }, daysAgo(35, 9));
|
|
215
|
+
await create(ctx, "OD3_Maintenance_Ticket_Source", { ticket: ptr("OD3_Maintenance_Ticket", t1), source: ptr("OD3_Source", cncId), user, tenant }, daysAgo(60, 9));
|
|
216
|
+
await create(ctx, "OD3_Maintenance_Ticket_Project", { ticket: ptr("OD3_Maintenance_Ticket", t1), project: ptr("OD3_Maintenance_Project", projectId), user, tenant }, daysAgo(60, 9));
|
|
217
|
+
await create(ctx, "OD3_Maintenance_Ticket_Issuecategory", { ticket: ptr("OD3_Maintenance_Ticket", t1), issuecategory: ptr("OD3_Maintenance_Issuecategory", bearingId), user, tenant }, daysAgo(59, 9));
|
|
218
|
+
// Status history: inbox -> in progress. No finished row, so `closedAt` stays null.
|
|
219
|
+
await create(ctx, "OD3_Maintenance_Ticket_Kanban_State", { ticket: ptr("OD3_Maintenance_Ticket", t1), state: ptr("OD3_Maintenance_Kanban_State", inboxId), user, tenant }, daysAgo(60, 9));
|
|
220
|
+
await create(ctx, "OD3_Maintenance_Ticket_Kanban_State", { ticket: ptr("OD3_Maintenance_Ticket", t1), state: ptr("OD3_Maintenance_Kanban_State", inProgressId), user, tenant }, daysAgo(38, 9));
|
|
221
|
+
await create(ctx, "OD3_Maintenance_Ticket_Kanban_State_Current", { ticket: ptr("OD3_Maintenance_Ticket", t1), state: ptr("OD3_Maintenance_Kanban_State", inProgressId), tenant }, daysAgo(38, 9));
|
|
222
|
+
// An assignment batch: several rows sharing one `batchStamp`, which the replay
|
|
223
|
+
// must collapse into a SINGLE timeline event rather than one per assignee.
|
|
224
|
+
const batchStamp = dateVal(daysAgo(37, 14));
|
|
225
|
+
await create(ctx, "OD3_Maintenance_Ticket_Assignment", { ticket: ptr("OD3_Maintenance_Ticket", t1), assignedUser: user, batchStamp, user, tenant }, daysAgo(37, 14));
|
|
226
|
+
if (ctx.roleId) {
|
|
227
|
+
await create(ctx, "OD3_Maintenance_Ticket_Assignment", {
|
|
228
|
+
ticket: ptr("OD3_Maintenance_Ticket", t1),
|
|
229
|
+
assignedRole: ptr("_Role", ctx.roleId),
|
|
230
|
+
batchStamp,
|
|
231
|
+
user,
|
|
232
|
+
tenant,
|
|
233
|
+
}, daysAgo(37, 14));
|
|
234
|
+
}
|
|
235
|
+
// A second, later batch -> a second event, so the timeline shows a reassignment.
|
|
236
|
+
await create(ctx, "OD3_Maintenance_Ticket_Assignment", {
|
|
237
|
+
ticket: ptr("OD3_Maintenance_Ticket", t1),
|
|
238
|
+
assignedUser: user,
|
|
239
|
+
batchStamp: dateVal(daysAgo(8, 11)),
|
|
240
|
+
user,
|
|
241
|
+
tenant,
|
|
242
|
+
}, daysAgo(8, 11));
|
|
243
|
+
// Material: an append-only side table where each row carries the WHOLE list,
|
|
244
|
+
// so two rows means one edit. Covers all three cases the migration handles:
|
|
245
|
+
// a catalogue item (maps to an Article), an ad-hoc line v1 allowed with a
|
|
246
|
+
// synthetic id, and a quantity changed later so the fold must pick row 2.
|
|
247
|
+
await create(ctx, "OD3_Maintenance_Ticket_Material", {
|
|
248
|
+
ticket: ptr("OD3_Maintenance_Ticket", t1),
|
|
249
|
+
itemList: [
|
|
250
|
+
{ id: itemDichtung, name: "Dichtung 12mm", quantity: 3, unit: "Stk" },
|
|
251
|
+
],
|
|
252
|
+
user,
|
|
253
|
+
tenant,
|
|
254
|
+
}, daysAgo(12, 9));
|
|
255
|
+
await create(ctx, "OD3_Maintenance_Ticket_Material", {
|
|
256
|
+
ticket: ptr("OD3_Maintenance_Ticket", t1),
|
|
257
|
+
itemList: [
|
|
258
|
+
{ id: itemDichtung, name: "Dichtung 12mm", quantity: 5, unit: "Stk" },
|
|
259
|
+
{ id: itemOel, name: "Spezialöl", quantity: 1, unit: "L" },
|
|
260
|
+
{ id: "manual-1", name: "Kabelbinder (Restbestand)", quantity: 10, unit: "Stk" },
|
|
261
|
+
],
|
|
262
|
+
user,
|
|
263
|
+
tenant,
|
|
264
|
+
}, daysAgo(9, 14));
|
|
265
|
+
// ── comments + todos on ticket 1 ─────────────────────────────────────────
|
|
266
|
+
await create(ctx, "OD3_Maintenance_Message", {
|
|
267
|
+
classname: "OD3_Maintenance_Ticket",
|
|
268
|
+
referencedObjectId: t1,
|
|
269
|
+
title: "Erste Sichtung",
|
|
270
|
+
content: "Lager sichtbar verfärbt, Austausch nötig.",
|
|
271
|
+
data: { type: "userinput" },
|
|
272
|
+
displayAt: dateVal(daysAgo(58)),
|
|
273
|
+
user,
|
|
274
|
+
tenant,
|
|
275
|
+
}, daysAgo(58, 10));
|
|
276
|
+
// Title is an i18n KEY (user left the subject blank) -> must not be rendered.
|
|
277
|
+
await create(ctx, "OD3_Maintenance_Message", {
|
|
278
|
+
classname: "OD3_Maintenance_Ticket",
|
|
279
|
+
referencedObjectId: t1,
|
|
280
|
+
title: "maintenance:article.create.default_subject.userinput",
|
|
281
|
+
content: "Ersatzteil bestellt, Lieferung nächste Woche.",
|
|
282
|
+
data: { type: "userinput" },
|
|
283
|
+
user,
|
|
284
|
+
tenant,
|
|
285
|
+
}, daysAgo(30, 10));
|
|
286
|
+
// A completed todo, and one still open with an i18n-key title.
|
|
287
|
+
await create(ctx, "OD3_Maintenance_Message", {
|
|
288
|
+
classname: "OD3_Maintenance_Ticket",
|
|
289
|
+
referencedObjectId: t1,
|
|
290
|
+
title: "Lager ausmessen",
|
|
291
|
+
content: "Innendurchmesser prüfen",
|
|
292
|
+
data: { type: "todo", todoCompleted: true },
|
|
293
|
+
user,
|
|
294
|
+
tenant,
|
|
295
|
+
}, daysAgo(50, 10));
|
|
296
|
+
await create(ctx, "OD3_Maintenance_Message", {
|
|
297
|
+
classname: "OD3_Maintenance_Ticket",
|
|
298
|
+
referencedObjectId: t1,
|
|
299
|
+
title: "maintenance:article.create.default_subject.todo",
|
|
300
|
+
content: "Schmierplan anpassen",
|
|
301
|
+
data: { type: "todo", todoCompleted: false },
|
|
302
|
+
user,
|
|
303
|
+
tenant,
|
|
304
|
+
}, daysAgo(20, 10));
|
|
305
|
+
// ── ticket 2: no kanban state at all -> inbox fallback ───────────────────
|
|
306
|
+
const t2 = await create(ctx, "OD3_Maintenance_Ticket", { title: "Kühlmittel nachfüllen", enabled: true, user, tenant }, daysAgo(25, 8));
|
|
307
|
+
await create(ctx, "OD3_Maintenance_Ticket_Source", { ticket: ptr("OD3_Maintenance_Ticket", t2), source: ptr("OD3_Source", untaggedId), user, tenant }, daysAgo(25, 9));
|
|
308
|
+
// ── ticket 2b: closed, so `closedAt` can be derived ─────────────────────
|
|
309
|
+
// v1 has no closedAt column; pass 08 infers it from the newest state-history row
|
|
310
|
+
// whose state is `isFinished`. Without a ticket like this that logic is untested.
|
|
311
|
+
const tClosed = await create(ctx, "OD3_Maintenance_Ticket", {
|
|
312
|
+
title: "Riemen getauscht",
|
|
313
|
+
description: "Antriebsriemen war gerissen.",
|
|
314
|
+
enabled: true,
|
|
315
|
+
latestPriorityValue: 40,
|
|
316
|
+
user,
|
|
317
|
+
tenant,
|
|
318
|
+
}, daysAgo(120, 8));
|
|
319
|
+
await create(ctx, "OD3_Maintenance_Ticket_Source", { ticket: ptr("OD3_Maintenance_Ticket", tClosed), source: ptr("OD3_Source", cncId), user, tenant }, daysAgo(120, 9));
|
|
320
|
+
await create(ctx, "OD3_Maintenance_Ticket_Kanban_State", { ticket: ptr("OD3_Maintenance_Ticket", tClosed), state: ptr("OD3_Maintenance_Kanban_State", inboxId), user, tenant }, daysAgo(120, 9));
|
|
321
|
+
await create(ctx, "OD3_Maintenance_Ticket_Kanban_State", { ticket: ptr("OD3_Maintenance_Ticket", tClosed), state: ptr("OD3_Maintenance_Kanban_State", inProgressId), user, tenant }, daysAgo(118, 9));
|
|
322
|
+
// The finished row: its updatedAt is what `closedAt` must end up as.
|
|
323
|
+
await create(ctx, "OD3_Maintenance_Ticket_Kanban_State", { ticket: ptr("OD3_Maintenance_Ticket", tClosed), state: ptr("OD3_Maintenance_Kanban_State", finishedId), user, tenant }, daysAgo(115, 16));
|
|
324
|
+
await create(ctx, "OD3_Maintenance_Ticket_Kanban_State_Current", { ticket: ptr("OD3_Maintenance_Ticket", tClosed), state: ptr("OD3_Maintenance_Kanban_State", finishedId), tenant }, daysAgo(115, 16));
|
|
325
|
+
// ── ticket 3: disabled -> deleted: true ──────────────────────────────────
|
|
326
|
+
await create(ctx, "OD3_Maintenance_Ticket", { title: "Storniert: Fehlalarm", enabled: false, user, tenant }, daysAgo(80, 8));
|
|
327
|
+
// ── ticket 4: `enabled` UNSET -> must also become deleted: true ───────────
|
|
328
|
+
const t4 = await create(ctx, "OD3_Maintenance_Ticket", { title: "Altlast ohne enabled-Flag", enabled: true, user, tenant }, daysAgo(500, 8));
|
|
329
|
+
await unsetField(ctx.config, "OD3_Maintenance_Ticket", t4, "enabled");
|
|
330
|
+
// ── ticket 5: tenant 2, so the multi-tenant path has data ────────────────
|
|
331
|
+
await create(ctx, "OD3_Maintenance_Ticket", {
|
|
332
|
+
title: "T2: Förderband prüfen",
|
|
333
|
+
enabled: true,
|
|
334
|
+
meta: {
|
|
335
|
+
fields: [
|
|
336
|
+
{ name: "kostenstelle", label: "Kostenstelle", type: "string", value: "T2-4711" },
|
|
337
|
+
],
|
|
338
|
+
},
|
|
339
|
+
user,
|
|
340
|
+
tenant: tenant2,
|
|
341
|
+
}, daysAgo(15, 8));
|
|
342
|
+
// ── a message pointing at something that is not a ticket -> orphan skip ──
|
|
343
|
+
await create(ctx, "OD3_Maintenance_Message", {
|
|
344
|
+
classname: "OD3_Source",
|
|
345
|
+
referencedObjectId: cncId,
|
|
346
|
+
title: "Maschinennotiz",
|
|
347
|
+
content: "Gehört zu einer Source, nicht zu einem Ticket.",
|
|
348
|
+
data: { type: "userinput" },
|
|
349
|
+
user,
|
|
350
|
+
tenant,
|
|
351
|
+
}, daysAgo(45, 10));
|
|
352
|
+
// ── form config, incl. meta field definitions and priority labels ─────────
|
|
353
|
+
await create(ctx, "OD3_Maintenance_Ticket_FormConfig", {
|
|
354
|
+
view: "formular",
|
|
355
|
+
label: "Standardformular",
|
|
356
|
+
config: {
|
|
357
|
+
config: [
|
|
358
|
+
{ name: "title", required: true, label: "Kurzbeschreibung" },
|
|
359
|
+
{ name: "description", label: "-" },
|
|
360
|
+
{
|
|
361
|
+
name: "priority",
|
|
362
|
+
required: true,
|
|
363
|
+
customLabels: [
|
|
364
|
+
{ label: "verylow", value: "Sehr niedrig" },
|
|
365
|
+
{ label: "low", value: "Niedrig" },
|
|
366
|
+
{ label: "mid", value: "Mittel" },
|
|
367
|
+
{ label: "high", value: "Hoch" },
|
|
368
|
+
{ label: "ultra", value: "Kritisch" },
|
|
369
|
+
],
|
|
370
|
+
},
|
|
371
|
+
{ name: "media", label: "Fotos" },
|
|
372
|
+
{ name: "material", label: "Material" },
|
|
373
|
+
{ name: "source", required: true },
|
|
374
|
+
{ name: "issuecategory", help: "Bitte möglichst genau wählen" },
|
|
375
|
+
{
|
|
376
|
+
name: "meta",
|
|
377
|
+
fields: [
|
|
378
|
+
{ name: "kostenstelle", label: "Kostenstelle", type: "string" },
|
|
379
|
+
{ name: "stillstand", label: "Stillstand?", type: "boolean" },
|
|
380
|
+
{
|
|
381
|
+
name: "schicht",
|
|
382
|
+
label: "Schicht",
|
|
383
|
+
type: "select",
|
|
384
|
+
options: ["Früh", "Spät", "Nacht"],
|
|
385
|
+
},
|
|
386
|
+
],
|
|
387
|
+
},
|
|
388
|
+
],
|
|
389
|
+
},
|
|
390
|
+
tenant,
|
|
391
|
+
// v1 stored this as a Parse Relation. Pass 06 reads it with relationIds()
|
|
392
|
+
// and writes a plain id array, which is what the v2 FormConfig.roles
|
|
393
|
+
// column is — seeded so that conversion is actually covered.
|
|
394
|
+
...(roleId
|
|
395
|
+
? {
|
|
396
|
+
roles: {
|
|
397
|
+
__op: "AddRelation",
|
|
398
|
+
objects: [{ __type: "Pointer", className: "_Role", objectId: roleId }],
|
|
399
|
+
},
|
|
400
|
+
}
|
|
401
|
+
: {}),
|
|
402
|
+
}, daysAgo(340));
|
|
403
|
+
// ── assets: one real ticket-media context, one abandoned temp context ────
|
|
404
|
+
await create(ctx, "OD3_Assets", {
|
|
405
|
+
context: `ticket-media-${t1}`,
|
|
406
|
+
description: "Foto Lager",
|
|
407
|
+
file: { __type: "File", name: "lager.txt", url: "https://example.invalid/lager.txt" },
|
|
408
|
+
user,
|
|
409
|
+
tenant,
|
|
410
|
+
}, daysAgo(57, 10));
|
|
411
|
+
await create(ctx, "OD3_Assets", {
|
|
412
|
+
context: "ticket-media-temp-abandoned-uuid",
|
|
413
|
+
description: "Verwaister Upload",
|
|
414
|
+
file: { __type: "File", name: "temp.txt", url: "https://example.invalid/temp.txt" },
|
|
415
|
+
user,
|
|
416
|
+
tenant,
|
|
417
|
+
}, daysAgo(56, 10));
|
|
418
|
+
}
|
|
419
|
+
// ── purge ──────────────────────────────────────────────────────────────────
|
|
420
|
+
const SEEDED_CLASSES = [
|
|
421
|
+
"OD3_Maintenance_Ticket_Assignment",
|
|
422
|
+
"OD3_Maintenance_Ticket_Material",
|
|
423
|
+
"OD3_Maintenance_Ticket_Kanban_State_Current",
|
|
424
|
+
"OD3_Maintenance_Ticket_Kanban_State",
|
|
425
|
+
"OD3_Maintenance_Ticket_Issuecategory",
|
|
426
|
+
"OD3_Maintenance_Ticket_Project",
|
|
427
|
+
"OD3_Maintenance_Ticket_Source",
|
|
428
|
+
"OD3_Maintenance_Ticket_Title",
|
|
429
|
+
"OD3_Maintenance_Duedate",
|
|
430
|
+
"OD3_Maintenance_Restriction",
|
|
431
|
+
"OD3_Maintenance_Frequency",
|
|
432
|
+
"OD3_Maintenance_Downtime",
|
|
433
|
+
"OD3_Maintenance_Priority",
|
|
434
|
+
"OD3_Maintenance_Message",
|
|
435
|
+
"OD3_Maintenance_Ticket",
|
|
436
|
+
"OD3_Maintenance_Ticket_FormConfig",
|
|
437
|
+
"OD3_Maintenance_Item",
|
|
438
|
+
"OD3_Maintenance_Project",
|
|
439
|
+
"OD3_Maintenance_Issuecategory",
|
|
440
|
+
"OD3_Maintenance_Kanban_State",
|
|
441
|
+
];
|
|
442
|
+
/**
|
|
443
|
+
* Delete everything in the v1 classes this seeder touches.
|
|
444
|
+
*
|
|
445
|
+
* Deliberately blunt: this is a dev-only reset, and the seeder's whole point is a
|
|
446
|
+
* known starting state. It does **not** touch `OD3_Source`, `OD3_Assets`,
|
|
447
|
+
* `OD3_Tenant` or `_User`, because those are shared with the rest of the stack.
|
|
448
|
+
*/
|
|
449
|
+
async function purge() {
|
|
450
|
+
for (const className of SEEDED_CLASSES) {
|
|
451
|
+
let removed = 0;
|
|
452
|
+
for (;;) {
|
|
453
|
+
const page = await new node_1.default.Query(className).limit(200).find(env_js_1.MK);
|
|
454
|
+
if (page.length === 0)
|
|
455
|
+
break;
|
|
456
|
+
await node_1.default.Object.destroyAll(page, {
|
|
457
|
+
context: { skipChangelog: true },
|
|
458
|
+
});
|
|
459
|
+
removed += page.length;
|
|
460
|
+
}
|
|
461
|
+
if (removed)
|
|
462
|
+
console.log(` purged ${removed.toString().padStart(4)} ${className}`);
|
|
463
|
+
}
|
|
464
|
+
console.log(`\n (OD3_Source, OD3_Assets, OD3_Tenant and _User left alone — shared with the stack)\n`);
|
|
465
|
+
}
|
|
466
|
+
// ── main ───────────────────────────────────────────────────────────────────
|
|
467
|
+
async function main() {
|
|
468
|
+
let config;
|
|
469
|
+
try {
|
|
470
|
+
config = (0, env_js_1.readConfig)(process.argv.slice(2));
|
|
471
|
+
}
|
|
472
|
+
catch (error) {
|
|
473
|
+
if (error instanceof env_js_1.MigrationConfigError) {
|
|
474
|
+
console.error(`\n✗ ${error.message}\n`);
|
|
475
|
+
return 2;
|
|
476
|
+
}
|
|
477
|
+
throw error;
|
|
478
|
+
}
|
|
479
|
+
(0, env_js_1.initParse)(config);
|
|
480
|
+
console.log(`\nv1 test-data seeder (DEV ONLY)`);
|
|
481
|
+
console.log(` server ${config.parseUrl}`);
|
|
482
|
+
if (process.argv.includes("--purge")) {
|
|
483
|
+
console.log(`\npurging v1 classes…\n`);
|
|
484
|
+
await purge();
|
|
485
|
+
return 0;
|
|
486
|
+
}
|
|
487
|
+
// Attach to whatever tenant/user the stack already has rather than inventing one.
|
|
488
|
+
const tenants = await new node_1.default.Query("OD3_Tenant").ascending("createdAt").find(env_js_1.MK);
|
|
489
|
+
const users = await new node_1.default.Query(node_1.default.User).ascending("createdAt").find(env_js_1.MK);
|
|
490
|
+
if (tenants.length === 0 || users.length === 0 || !tenants[0].id || !users[0].id) {
|
|
491
|
+
console.error(`\n✗ Need at least one OD3_Tenant and one _User to attach the test data to.\n` +
|
|
492
|
+
` Found ${tenants.length} tenant(s), ${users.length} user(s).\n`);
|
|
493
|
+
return 2;
|
|
494
|
+
}
|
|
495
|
+
// Tenant 1 is the one the seeding user actually belongs to, not simply the
|
|
496
|
+
// oldest. Everything seeded here gets tenant-role ACLs, and master data
|
|
497
|
+
// (Status, Equipment) grants roles ONLY — no per-user grant — so data written
|
|
498
|
+
// into a tenant the user is not a member of is invisible in the UI. That reads
|
|
499
|
+
// exactly like a broken migration: tickets show up (they also grant their
|
|
500
|
+
// creator) while their status and equipment render as blank or raw ids.
|
|
501
|
+
//
|
|
502
|
+
// The oldest-first ordering made this worse: the synthetic tenant below is
|
|
503
|
+
// backdated, so on every run after the first it sorted ahead of the real one.
|
|
504
|
+
const userTenantId = users[0].get("tenant")?.id;
|
|
505
|
+
const tenantId = userTenantId && tenants.some((t) => t.id === userTenantId)
|
|
506
|
+
? userTenantId
|
|
507
|
+
: tenants[0].id;
|
|
508
|
+
let tenant2Id = tenants.find((t) => t.id !== tenantId)?.id ?? "";
|
|
509
|
+
if (!tenant2Id) {
|
|
510
|
+
// The multi-tenant cases need a second tenant; create one if the stack has
|
|
511
|
+
// only the default.
|
|
512
|
+
const second = await (0, rest_js_1.restCreateRaw)(config, "OD3_Tenant", { label: `Testmandant 2 (${SEED_MARKER})` }, daysAgo(600));
|
|
513
|
+
tenant2Id = second.objectId;
|
|
514
|
+
console.log(` created a second tenant for the multi-tenant cases: ${tenant2Id}`);
|
|
515
|
+
}
|
|
516
|
+
console.log(` tenant 1 ${tenantId}`);
|
|
517
|
+
console.log(` tenant 2 ${tenant2Id}`);
|
|
518
|
+
console.log(` user ${users[0].id}\n`);
|
|
519
|
+
// Prefer a tenant-scoped role, so the assignment looks like real data.
|
|
520
|
+
const roles = await new node_1.default.Query(node_1.default.Role).find(env_js_1.MK);
|
|
521
|
+
const roleId = roles.find((r) => r.getName() === `od-tenant-user-${tenantId}`)?.id ??
|
|
522
|
+
roles[0]?.id;
|
|
523
|
+
const ctx = {
|
|
524
|
+
config,
|
|
525
|
+
tenantId,
|
|
526
|
+
tenant2Id,
|
|
527
|
+
userId: users[0].id,
|
|
528
|
+
roleId,
|
|
529
|
+
created: new Map(),
|
|
530
|
+
};
|
|
531
|
+
await seed(ctx);
|
|
532
|
+
console.log(`created:`);
|
|
533
|
+
for (const [className, count] of [...ctx.created].sort()) {
|
|
534
|
+
console.log(` ${count.toString().padStart(4)} ${className}`);
|
|
535
|
+
}
|
|
536
|
+
console.log(`\n✓ seeded. Next:\n` +
|
|
537
|
+
` node dist/scripts/migration/run.js --dry-run\n`);
|
|
538
|
+
return 0;
|
|
539
|
+
}
|
|
540
|
+
main().then((code) => process.exit(code), (error) => {
|
|
541
|
+
console.error(error);
|
|
542
|
+
process.exit(1);
|
|
543
|
+
});
|
|
@@ -10,6 +10,7 @@ export interface BDE_ArticleAttributes {
|
|
|
10
10
|
isDeleted: boolean;
|
|
11
11
|
targettime?: number | undefined;
|
|
12
12
|
tenant?: Tenant | undefined;
|
|
13
|
+
type?: string | undefined;
|
|
13
14
|
unit?: string | undefined;
|
|
14
15
|
}
|
|
15
16
|
export declare class BDE_Article extends Parse.Object<BDE_ArticleAttributes> {
|
|
@@ -25,6 +26,8 @@ export declare class BDE_Article extends Parse.Object<BDE_ArticleAttributes> {
|
|
|
25
26
|
set targettime(value: number | undefined);
|
|
26
27
|
get tenant(): Tenant | undefined;
|
|
27
28
|
set tenant(value: Tenant | undefined);
|
|
29
|
+
get type(): string | undefined;
|
|
30
|
+
set type(value: string | undefined);
|
|
28
31
|
get unit(): string | undefined;
|
|
29
32
|
set unit(value: string | undefined);
|
|
30
33
|
}
|
|
@@ -40,6 +40,12 @@ class BDE_Article extends node_1.default.Object {
|
|
|
40
40
|
set tenant(value) {
|
|
41
41
|
super.set("tenant", value);
|
|
42
42
|
}
|
|
43
|
+
get type() {
|
|
44
|
+
return super.get("type");
|
|
45
|
+
}
|
|
46
|
+
set type(value) {
|
|
47
|
+
super.set("type", value);
|
|
48
|
+
}
|
|
43
49
|
get unit() {
|
|
44
50
|
return super.get("unit");
|
|
45
51
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import Parse from "parse/node";
|
|
2
|
+
import type { _User } from "./_User";
|
|
3
|
+
import type { Tenant } from "./Tenant";
|
|
4
|
+
export interface Chat_MessageAttributes {
|
|
5
|
+
id: string;
|
|
6
|
+
objectId: string;
|
|
7
|
+
createdAt: Date;
|
|
8
|
+
updatedAt: Date;
|
|
9
|
+
attachments?: any[] | undefined;
|
|
10
|
+
author?: _User | undefined;
|
|
11
|
+
authorName?: string | undefined;
|
|
12
|
+
chatId?: string | undefined;
|
|
13
|
+
context?: string | undefined;
|
|
14
|
+
deleted: boolean;
|
|
15
|
+
editedAt?: Date | undefined;
|
|
16
|
+
mentions?: any[] | undefined;
|
|
17
|
+
parent?: Chat_Message | undefined;
|
|
18
|
+
reactions?: any | undefined;
|
|
19
|
+
tenant?: Tenant | undefined;
|
|
20
|
+
text: string;
|
|
21
|
+
}
|
|
22
|
+
export declare class Chat_Message extends Parse.Object<Chat_MessageAttributes> {
|
|
23
|
+
static className: string;
|
|
24
|
+
constructor(data?: Partial<Chat_MessageAttributes>);
|
|
25
|
+
get attachments(): any[] | undefined;
|
|
26
|
+
set attachments(value: any[] | undefined);
|
|
27
|
+
get author(): _User | undefined;
|
|
28
|
+
set author(value: _User | undefined);
|
|
29
|
+
get authorName(): string | undefined;
|
|
30
|
+
set authorName(value: string | undefined);
|
|
31
|
+
get chatId(): string | undefined;
|
|
32
|
+
set chatId(value: string | undefined);
|
|
33
|
+
get context(): string | undefined;
|
|
34
|
+
set context(value: string | undefined);
|
|
35
|
+
get deleted(): boolean;
|
|
36
|
+
set deleted(value: boolean);
|
|
37
|
+
get editedAt(): Date | undefined;
|
|
38
|
+
set editedAt(value: Date | undefined);
|
|
39
|
+
get mentions(): any[] | undefined;
|
|
40
|
+
set mentions(value: any[] | undefined);
|
|
41
|
+
get parent(): Chat_Message | undefined;
|
|
42
|
+
set parent(value: Chat_Message | undefined);
|
|
43
|
+
get reactions(): any | undefined;
|
|
44
|
+
set reactions(value: any | undefined);
|
|
45
|
+
get tenant(): Tenant | undefined;
|
|
46
|
+
set tenant(value: Tenant | undefined);
|
|
47
|
+
get text(): string;
|
|
48
|
+
set text(value: string);
|
|
49
|
+
}
|