From 2a6f5f73900d92c64ff2b3c2bda47565e229b557 Mon Sep 17 00:00:00 2001 From: Andrey Sobolev <haiodo@users.noreply.github.com> Date: Thu, 16 Dec 2021 16:06:56 +0700 Subject: [PATCH] Fix migration (#650) Signed-off-by: Andrey Sobolev <haiodo@gmail.com> --- models/lead/src/migration.ts | 34 +++----- models/recruit/src/migration.ts | 52 ++++++------ models/task/src/migration.ts | 137 ++++++++++++++++++++------------ 3 files changed, 120 insertions(+), 103 deletions(-) diff --git a/models/lead/src/migration.ts b/models/lead/src/migration.ts index de27373f34..90e88e9235 100644 --- a/models/lead/src/migration.ts +++ b/models/lead/src/migration.ts @@ -15,22 +15,29 @@ // import { Doc, TxOperations } from '@anticrm/core' -import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model' +import { MigrateOperation, MigrationClient, MigrationResult, MigrationUpgradeClient } from '@anticrm/model' import core from '@anticrm/model-core' -import task from '@anticrm/model-task' +import task, { DOMAIN_TASK } from '@anticrm/model-task' import { createKanban } from '@anticrm/lead' import lead from './plugin' +function logInfo (msg: string, result: MigrationResult): void { + if (result.updated > 0) { + console.log(`Lead: Migrate ${msg} ${result.updated}`) + } +} + export const leadOperation: MigrateOperation = { async migrate (client: MigrationClient): Promise<void> { - + // Update done states for tasks + logInfo('lead done states', await client.update(DOMAIN_TASK, { _class: lead.class.Lead, doneState: { $exists: false } }, { doneState: null })) }, async upgrade (client: MigrationUpgradeClient): Promise<void> { console.log('Lead: Performing model upgrades') const ops = new TxOperations(client, core.account.System) if (await client.findOne(task.class.Kanban, { attachedTo: lead.space.DefaultFunnel }) === undefined) { - console.info('Create kanban for default funnel.') + console.info('Lead: Create kanban for default funnel.') await createKanban(lead.space.DefaultFunnel, async (_class, space, data, id) => { const doc = await ops.findOne<Doc>(_class, { _id: id }) if (doc === undefined) { @@ -44,29 +51,14 @@ export const leadOperation: MigrateOperation = { } if (await client.findOne(task.class.Sequence, { attachedTo: lead.class.Lead }) === undefined) { - console.info('Create sequence for default task project.') + console.info('Lead: Create sequence for default task project.') // We need to create sequence await ops.createDoc(task.class.Sequence, task.space.Sequence, { attachedTo: lead.class.Lead, sequence: 0 }) } else { - console.log('Task: => sequence is ok') + console.log('Lead: => sequence is ok') } - - const outdatedLeads = (await client.findAll(lead.class.Lead, {})) - .filter((x) => x.doneState === undefined) - - await Promise.all( - outdatedLeads.map(async (lead) => { - console.info('Upgrade lead:', lead._id) - - try { - await ops.updateDoc(lead._class, lead.space, lead._id, { doneState: null }) - } catch (err: unknown) { - console.error(err) - } - }) - ) } } diff --git a/models/recruit/src/migration.ts b/models/recruit/src/migration.ts index 20d2551102..575bad5f0b 100644 --- a/models/recruit/src/migration.ts +++ b/models/recruit/src/migration.ts @@ -13,42 +13,36 @@ // limitations under the License. // -import { TxOperations } from '@anticrm/core' -import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model' -import core from '@anticrm/model-core' - +import { MigrateOperation, MigrationClient, MigrationResult, MigrationUpgradeClient } from '@anticrm/model' +import contact, { DOMAIN_CONTACT } from '@anticrm/model-contact' +import { DOMAIN_TASK } from '@anticrm/model-task' import recruit from './plugin' +function logInfo (msg: string, result: MigrationResult): void { + if (result.updated > 0) { + console.log(`Recruit: Migrate ${msg} ${result.updated}`) + } +} export const recruitOperation: MigrateOperation = { async migrate (client: MigrationClient): Promise<void> { + logInfo('done for Applicants', await client.update(DOMAIN_TASK, { _class: recruit.class.Applicant, doneState: { $exists: false } }, { doneState: null })) + logInfo('$move employee => assignee', await client.update( + DOMAIN_TASK, + { _class: recruit.class.Applicant, employee: { $exists: true } }, + { $rename: { employee: 'assignee' } } + )) + + const employees = (await client.find(DOMAIN_CONTACT, { _class: contact.class.Employee })).map(emp => emp._id) + + // update assignee to unassigned if there is no employee exists. + logInfo('applicants wrong assignee', await client.update( + DOMAIN_TASK, + { _class: recruit.class.Applicant, assignee: { $not: { $in: employees } } }, + { assignee: null } + )) }, async upgrade (client: MigrationUpgradeClient): Promise<void> { console.log('Recruit: Performing model upgrades') - - const ops = new TxOperations(client, core.account.System) - - const outdatedApplications = (await client.findAll(recruit.class.Applicant, {})) - .filter((x) => x.doneState === undefined) - - await Promise.all( - outdatedApplications.map(async (application) => { - console.info('Upgrade application:', application._id) - - try { - await ops.updateCollection( - application._class, - application.space, - application._id, - application.attachedTo, - application.attachedToClass, - application.collection, - { doneState: null } - ) - } catch (err: unknown) { - console.error(err) - } - }) - ) } } diff --git a/models/task/src/migration.ts b/models/task/src/migration.ts index 544b9aaa14..28a8551860 100644 --- a/models/task/src/migration.ts +++ b/models/task/src/migration.ts @@ -14,7 +14,13 @@ // import { Class, Doc, Domain, DOMAIN_TX, Ref, TxCUD, TxOperations } from '@anticrm/core' -import { MigrateOperation, MigrateUpdate, MigrationClient, MigrationResult, MigrationUpgradeClient } from '@anticrm/model' +import { + MigrateOperation, + MigrateUpdate, + MigrationClient, + MigrationResult, + MigrationUpgradeClient +} from '@anticrm/model' import core from '@anticrm/model-core' import { createProjectKanban } from '@anticrm/task' import { DOMAIN_TASK, DOMAIN_STATE, DOMAIN_KANBAN } from '.' @@ -22,14 +28,22 @@ import task from './plugin' function logInfo (msg: string, result: MigrationResult): void { if (result.updated > 0) { - console.log(`Tasks: Migrate ${msg} ${result.updated}`) + console.log(`Task: Migrate ${msg} ${result.updated}`) } } -async function migrateClass<T extends Doc> (client: MigrationClient, domain: Domain, from: Ref<Class<Doc>>, to: Ref<Class<T>>, extraOps: MigrateUpdate<T> = {}, txExtraOps: MigrateUpdate<TxCUD<Doc>> = {}): Promise<void> { - logInfo(`Migrate ${from} => ${to}: `, - await client.update<Doc>(domain, { _class: from }, { ...extraOps, _class: to })) - logInfo(`Migrate ${from} => ${to} Transactions`, - await client.update<TxCUD<Doc>>(DOMAIN_TX, { objectClass: from }, { ...txExtraOps, objectClass: to })) +async function migrateClass<T extends Doc> ( + client: MigrationClient, + domain: Domain, + from: Ref<Class<Doc>>, + to: Ref<Class<T>>, + extraOps: MigrateUpdate<T> = {}, + txExtraOps: MigrateUpdate<TxCUD<Doc>> = {} +): Promise<void> { + logInfo(`${from} => ${to}: `, await client.update<Doc>(domain, { _class: from }, { ...extraOps, _class: to })) + logInfo( + `${from} => ${to} Transactions`, + await client.update<TxCUD<Doc>>(DOMAIN_TX, { objectClass: from }, { ...txExtraOps, objectClass: to }) + ) } export const taskOperation: MigrateOperation = { @@ -40,30 +54,62 @@ export const taskOperation: MigrateOperation = { await migrateClass(client, DOMAIN_STATE, 'core:class:WonState' as Ref<Class<Doc>>, task.class.WonState) await migrateClass(client, DOMAIN_STATE, 'core:class:LostState' as Ref<Class<Doc>>, task.class.LostState) await migrateClass(client, DOMAIN_KANBAN, 'view:class:Kanban' as Ref<Class<Doc>>, task.class.Kanban) - await migrateClass(client, DOMAIN_KANBAN, 'view:class:Sequence' as Ref<Class<Doc>>, task.class.Sequence, { space: task.space.Sequence }, { objectSpace: task.space.Sequence }) + await migrateClass( + client, + DOMAIN_KANBAN, + 'view:class:Sequence' as Ref<Class<Doc>>, + task.class.Sequence, + { space: task.space.Sequence }, + { objectSpace: task.space.Sequence } + ) // Update attached to for task - await client.update(DOMAIN_KANBAN, { _class: task.class.Sequence, attachedTo: task.class.Task }, { attachedTo: task.class.Issue }) + await client.update( + DOMAIN_KANBAN, + { _class: task.class.Sequence, attachedTo: task.class.Task }, + { attachedTo: task.class.Issue } + ) await migrateClass(client, DOMAIN_KANBAN, 'view:class:KanbanTemplate' as Ref<Class<Doc>>, task.class.KanbanTemplate) await migrateClass(client, DOMAIN_KANBAN, 'view:class:StateTemplate' as Ref<Class<Doc>>, task.class.StateTemplate) - await migrateClass(client, DOMAIN_KANBAN, 'view:class:DoneStateTemplate' as Ref<Class<Doc>>, task.class.DoneStateTemplate) - await migrateClass(client, DOMAIN_KANBAN, 'view:class:LostStateTemplate' as Ref<Class<Doc>>, task.class.LostStateTemplate) + await migrateClass( + client, + DOMAIN_KANBAN, + 'view:class:DoneStateTemplate' as Ref<Class<Doc>>, + task.class.DoneStateTemplate + ) + await migrateClass( + client, + DOMAIN_KANBAN, + 'view:class:LostStateTemplate' as Ref<Class<Doc>>, + task.class.LostStateTemplate + ) - await client.move('recruit' as Domain, { - _class: 'recruit:class:Applicant' as Ref<Class<Doc>> - }, DOMAIN_TASK) + await client.move( + 'recruit' as Domain, + { + _class: 'recruit:class:Applicant' as Ref<Class<Doc>> + }, + DOMAIN_TASK + ) - await client.move('lead' as Domain, { - _class: 'lead:class:Lead' as Ref<Class<Doc>> - }, DOMAIN_TASK) + await client.move( + 'lead' as Domain, + { + _class: 'lead:class:Lead' as Ref<Class<Doc>> + }, + DOMAIN_TASK + ) + + // Update done states for tasks + await client.update(DOMAIN_TASK, { _class: task.class.Issue, doneState: { $exists: false } }, { doneState: null }) }, async upgrade (client: MigrationUpgradeClient): Promise<void> { console.log('Task: Performing model upgrades') const ops = new TxOperations(client, core.account.System) - if (await client.findOne(task.class.Sequence, { attachedTo: task.class.Issue }) === undefined) { - console.info('Create sequence for default task project.') + if ((await client.findOne(task.class.Sequence, { attachedTo: task.class.Issue })) === undefined) { + console.info('Task: Create sequence for default task project.') // We need to create sequence await ops.createDoc(task.class.Sequence, task.space.Sequence, { attachedTo: task.class.Issue, @@ -72,8 +118,8 @@ export const taskOperation: MigrateOperation = { } else { console.log('Task: => sequence is ok') } - if (await client.findOne(task.class.Kanban, { attachedTo: task.space.TasksPublic }) === undefined) { - console.info('Create kanban for default task project.') + if ((await client.findOne(task.class.Kanban, { attachedTo: task.space.TasksPublic })) === undefined) { + console.info('Task: Create kanban for default task project.') await createProjectKanban(task.space.TasksPublic, async (_class, space, data, id) => { const doc = await ops.findOne<Doc>(_class, { _id: id }) if (doc === undefined) { @@ -88,41 +134,26 @@ export const taskOperation: MigrateOperation = { console.log('View: Performing model upgrades') - const kanbans = (await client.findAll(task.class.Kanban, {})) - .filter((kanban) => kanban.doneStates == null) + const kanbans = (await client.findAll(task.class.Kanban, {})).filter((kanban) => kanban.doneStates == null) await Promise.all( - kanbans - .map(async (kanban) => { - console.log(`Updating kanban: ${kanban._id}`) - try { - const doneStates = await Promise.all([ - ops.createDoc(task.class.WonState, kanban.space, { - title: 'Won' - }), - ops.createDoc(task.class.LostState, kanban.space, { - title: 'Lost' - }) - ]) - - await ops.updateDoc(kanban._class, kanban.space, kanban._id, { - doneStates - }) - } catch (e) { - console.error(e) - } - })) - - const outdatedTasks = (await client.findAll(task.class.Task, {})) - .filter((x) => x.doneState === undefined) - - await Promise.all( - outdatedTasks.map(async (task) => { - console.info('Upgrade task:', task._id) + kanbans.map(async (kanban) => { + console.log(`Updating kanban: ${kanban._id}`) try { - await ops.updateDoc(task._class, task.space, task._id, { doneState: null }) - } catch (err: unknown) { - console.error(err) + const doneStates = await Promise.all([ + ops.createDoc(task.class.WonState, kanban.space, { + title: 'Won' + }), + ops.createDoc(task.class.LostState, kanban.space, { + title: 'Lost' + }) + ]) + + await ops.updateDoc(kanban._class, kanban.space, kanban._id, { + doneStates + }) + } catch (e) { + console.error(e) } }) )