diff --git a/src/meta/assessment/activityLog/index.ts b/src/meta/assessment/activityLog/index.ts index 71c87199db..3ded4b0458 100644 --- a/src/meta/assessment/activityLog/index.ts +++ b/src/meta/assessment/activityLog/index.ts @@ -32,7 +32,8 @@ export enum ActivityLogMessage { originalDataPointRemove = 'originalDataPointRemove', originalDataPointUpdate = 'originalDataPointUpdate', originalDataPointUpdateDataSources = 'originalDataPointUpdateDataSources', - originalDataPointUpdateDescription = 'originalDataPointUpdateDescription', + originalDataPointUpdateCommentExtentOfForest = 'originalDataPointUpdateCommentExtentOfForest', + originalDataPointUpdateCommentForestCharacteristics = 'originalDataPointUpdateCommentForestCharacteristics', originalDataPointUpdateNationalClasses = 'originalDataPointUpdateNationalClasses', originalDataPointUpdateOriginalData = 'originalDataPointUpdateOriginalData', originalDataPointUpdateYear = 'originalDataPointUpdateYear', diff --git a/src/meta/assessment/activityLogs/index.ts b/src/meta/assessment/activityLogs/index.ts index c9d040e2bb..5e748ce718 100644 --- a/src/meta/assessment/activityLogs/index.ts +++ b/src/meta/assessment/activityLogs/index.ts @@ -7,7 +7,7 @@ import { Cycle, CycleName } from 'meta/assessment/cycle' import { Labels } from 'meta/assessment/labels' import { SectionName, SectionNames, SubSection } from 'meta/assessment/section' import { Routes } from 'meta/routes' -import { Users } from 'meta/user' +import { RoleName, Users } from 'meta/user' const messageToKey: { [key in keyof typeof ActivityLogMessage]?: string } = { [ActivityLogMessage.assessmentStatusUpdate]: 'updateAssessmentStatus', @@ -21,7 +21,8 @@ const messageToKey: { [key in keyof typeof ActivityLogMessage]?: string } = { [ActivityLogMessage.originalDataPointCreate]: 'added', [ActivityLogMessage.originalDataPointRemove]: 'deleted', [ActivityLogMessage.originalDataPointUpdateDataSources]: 'updated', - [ActivityLogMessage.originalDataPointUpdateDescription]: 'updated', + [ActivityLogMessage.originalDataPointUpdateCommentExtentOfForest]: 'updated', + [ActivityLogMessage.originalDataPointUpdateCommentForestCharacteristics]: 'updated', [ActivityLogMessage.originalDataPointUpdateNationalClasses]: 'updated', [ActivityLogMessage.originalDataPointUpdateOriginalData]: 'updated', [ActivityLogMessage.originalDataPointUpdateYear]: 'updated', @@ -29,7 +30,7 @@ const messageToKey: { [key in keyof typeof ActivityLogMessage]?: string } = { [ActivityLogMessage.topicStatusChange]: 'resolved', } -const _getLabelActionKey = (activity: ActivityLog) => { +const _getLabelActionKey = (activity: ActivityLog): string => { const { message } = activity const key = messageToKey[message] @@ -39,25 +40,33 @@ const _getLabelActionKey = (activity: ActivityLog) => { return 'landing.recentActivity.actions.edited' } -const _getLabelActionParams = (activity: ActivityLog, t: TFunction) => { +const _getLabelActionParams = (activity: ActivityLog, t: TFunction): Record => { const { target } = activity - let params = {} - const { assessment, file, role, status, user } = target ?? {} - if (user) - params = { - user, - role: role ? t(Users.getI18nRoleLabelKey(role)) : null, + let params: Record = {} + + if (target && typeof target === 'object') { + if ('user' in target && target.user) { + const { role, user } = target as { user: string; role?: RoleName } + params = { + user, + role: role ? t(Users.getI18nRoleLabelKey(role)) : null, + } + } else if ('assessment' in target && target.assessment) { + const { assessment, status } = target as { assessment: string; status: string } + params = { + assessment: t(`assessment.${assessment}`), + status: t(`assessment.status.${status}.label`), + } + } else if ('file' in target && target.file) { + const { file } = target as { file: string } + params = { file } } - else if (assessment) - params = { - assessment: t(`assessment.${assessment}`), - status: t(`assessment.status.${status}.label`), - } - else if (file) params = { file } + } + return params } -const getLabelAction = (props: { activity: ActivityLog; t: TFunction }) => { +const getLabelAction = (props: { activity: ActivityLog; t: TFunction }): string => { const { activity, t } = props const labelActionKey = _getLabelActionKey(activity) const messageParams = _getLabelActionParams(activity, t) @@ -65,7 +74,7 @@ const getLabelAction = (props: { activity: ActivityLog; t: TFunction }) => return label !== labelActionKey ? label : t('landing.recentActivity.actions.edited') } -const getLabelSectionKey = (activity: ActivityLog) => { +const getLabelSectionKey = (activity: ActivityLog): string => { const { section } = activity if (section.indexOf('odp') !== -1) { return 'nationalDataPoint.nationalDataPoint' @@ -78,18 +87,23 @@ const getLabelSectionKey = (activity: ActivityLog) => { return `${section}.${section}` } -const hasSectionLink = (activity: ActivityLog) => { +const hasSectionLink = (activity: ActivityLog): boolean => { const { section } = activity return !['users', 'assessment'].includes(section) } -const isSectionLinkDisabled = (activity: ActivityLog) => { +const isSectionLinkDisabled = (activity: ActivityLog): boolean => { const { section } = activity const labelSectionKey = getLabelSectionKey(activity) return ['fileRepository', 'messageBoard', 'odp'].includes(section) || labelSectionKey === 'dashboard.actions.deleted' } -const getLabelSection = (props: { cycle: Cycle; section?: SubSection; activity: ActivityLog; t: TFunction }) => { +const getLabelSection = (props: { + activity: ActivityLog + cycle: Cycle + section?: SubSection + t: TFunction +}): string => { const { activity, cycle, section, t } = props const labels = section?.props?.labels const labelSectionKey = labels ? Labels.getCycleLabel({ cycle, labels, t }) : getLabelSectionKey(activity) diff --git a/src/server/controller/cycleData/originalDataPoint/updateOriginalDataPointDescription.ts b/src/server/controller/cycleData/originalDataPoint/updateOriginalDataPointDescription.ts index 2b04256f05..fa9cfec5ac 100644 --- a/src/server/controller/cycleData/originalDataPoint/updateOriginalDataPointDescription.ts +++ b/src/server/controller/cycleData/originalDataPoint/updateOriginalDataPointDescription.ts @@ -3,6 +3,7 @@ import { ActivityLogMessage } from 'meta/assessment/activityLog' import { Assessment } from 'meta/assessment/assessment' import { Cycle } from 'meta/assessment/cycle' import { OriginalDataPoint, OriginalDataPointCommentKey } from 'meta/assessment/originalDataPoint' +import { TableNames } from 'meta/assessment/table' import { User } from 'meta/user' import { BaseProtocol, DB } from 'server/db' @@ -19,6 +20,11 @@ type Props = { user: User } +const activities: Record = { + [TableNames.extentOfForest]: ActivityLogMessage.originalDataPointUpdateCommentExtentOfForest, + [TableNames.forestCharacteristics]: ActivityLogMessage.originalDataPointUpdateCommentForestCharacteristics, +} + export const updateOriginalDataPointDescription = async ( props: Props, client: BaseProtocol = DB @@ -32,10 +38,12 @@ export const updateOriginalDataPointDescription = async ( t ) + const message = activities[field] + const activityLog = { target: updatedOriginalDataPoint, section: 'odp', - message: ActivityLogMessage.originalDataPointUpdateDescription, + message, countryIso, user, } diff --git a/src/server/repository/adapter/originalDataPoint.ts b/src/server/repository/adapter/originalDataPoint.ts new file mode 100644 index 0000000000..e0fd53a71d --- /dev/null +++ b/src/server/repository/adapter/originalDataPoint.ts @@ -0,0 +1,52 @@ +import { Objects } from 'utils/objects' + +import { CountryIso } from 'meta/area' +import { ODPNationalClass, OriginalDataPoint, OriginalDataPointComments } from 'meta/assessment/originalDataPoint' +import { + OriginalDataPointCommentKey, + OriginalDataPointValues, +} from 'meta/assessment/originalDataPoint/originalDataPoint' +import { TableNames } from 'meta/assessment/table' + +import { ODPCommentColumns } from 'server/repository/assessmentCycle/originalDataPoint/commentColumns' + +type ODPCommentColName = `comments_${Lowercase}` + +export type OriginalDataPointDB = { + [K in ODPCommentColName]: string +} & { + country_iso: CountryIso + data_source_additional_comments: string | null + data_source_methods: string | null + data_source_references: string | null + id_legacy: number | null + id: number + national_classes: Array + values: OriginalDataPointValues + year: number +} + +const commentColumnExtent = ODPCommentColumns[TableNames.extentOfForest] as ODPCommentColName +const commentColumnForestCharacteristics = ODPCommentColumns[ + TableNames.forestCharacteristics +] as ODPCommentColName + +export const OriginalDataPointAdapter = (row: OriginalDataPointDB): OriginalDataPoint => { + if (Objects.isNil(row)) return null + + const { + [commentColumnExtent]: commentsExtentOfForest, + [commentColumnForestCharacteristics]: commentsForestCharacteristics, + ...rest + } = row + + const comments: OriginalDataPointComments = { + [TableNames.extentOfForest]: commentsExtentOfForest, + [TableNames.forestCharacteristics]: commentsForestCharacteristics, + } + + return { + ...(Objects.camelize(rest) as OriginalDataPoint), + comments, + } +} diff --git a/src/server/repository/assessment/assessment/getCreateSchemaDDL.ts b/src/server/repository/assessment/assessment/getCreateSchemaDDL.ts index 52a5a9cf89..4284aa49c8 100644 --- a/src/server/repository/assessment/assessment/getCreateSchemaDDL.ts +++ b/src/server/repository/assessment/assessment/getCreateSchemaDDL.ts @@ -1,9 +1,11 @@ import { CountryStatus } from 'meta/area' import { Assessment } from 'meta/assessment/assessment' import { Cycle } from 'meta/assessment/cycle' +import { TableNames } from 'meta/assessment/table' import { Schemas } from 'server/db' import { NodeExtQueries } from 'server/repository/assessmentCycle/nodeExt/queries' +import { ODPCommentColumns } from 'server/repository/assessmentCycle/originalDataPoint/commentColumns' import { OriginalDataPointQueries } from 'server/repository/assessmentCycle/originalDataPoint/queries' export const getCreateSchemaDDL = (schemaName: string): string => { @@ -123,7 +125,8 @@ export const getCreateSchemaCycleDDL = (assessmentSchemaName: string, assessment data_source_additional_comments varchar, data_source_methods jsonb, data_source_references text, - comments jsonb not null default '{}'::jsonb, + ${ODPCommentColumns[TableNames.extentOfForest]} text default '' not null, + ${ODPCommentColumns[TableNames.forestCharacteristics]} text default '' not null, national_classes jsonb, values jsonb, id_legacy bigint diff --git a/src/server/repository/assessmentCycle/countryActivityLog/_common/acceptedMessages.ts b/src/server/repository/assessmentCycle/countryActivityLog/_common/acceptedMessages.ts index 06abc600e4..c85580e0b3 100644 --- a/src/server/repository/assessmentCycle/countryActivityLog/_common/acceptedMessages.ts +++ b/src/server/repository/assessmentCycle/countryActivityLog/_common/acceptedMessages.ts @@ -16,7 +16,8 @@ export const acceptedMessages = [ ActivityLogMessage.originalDataPointRemove, ActivityLogMessage.originalDataPointUpdate, ActivityLogMessage.originalDataPointUpdateDataSources, - ActivityLogMessage.originalDataPointUpdateDescription, + ActivityLogMessage.originalDataPointUpdateCommentExtentOfForest, + ActivityLogMessage.originalDataPointUpdateCommentForestCharacteristics, ActivityLogMessage.originalDataPointUpdateNationalClasses, ActivityLogMessage.originalDataPointUpdateOriginalData, ActivityLogMessage.originalDataPointUpdateYear, diff --git a/src/server/repository/assessmentCycle/countrySummary/_lastEditActivities.ts b/src/server/repository/assessmentCycle/countrySummary/_lastEditActivities.ts index e92a7ba701..dfa5756071 100644 --- a/src/server/repository/assessmentCycle/countrySummary/_lastEditActivities.ts +++ b/src/server/repository/assessmentCycle/countrySummary/_lastEditActivities.ts @@ -11,7 +11,8 @@ export const activitiesLastEdit = [ ActivityLogMessage.originalDataPointRemove, ActivityLogMessage.originalDataPointUpdate, ActivityLogMessage.originalDataPointUpdateDataSources, - ActivityLogMessage.originalDataPointUpdateDescription, + ActivityLogMessage.originalDataPointUpdateCommentExtentOfForest, + ActivityLogMessage.originalDataPointUpdateCommentForestCharacteristics, ActivityLogMessage.originalDataPointUpdateNationalClasses, ActivityLogMessage.originalDataPointUpdateOriginalData, ActivityLogMessage.originalDataPointUpdateYear, @@ -25,7 +26,8 @@ export const activitiesLastEditOdpData = [ ActivityLogMessage.originalDataPointRemove, ActivityLogMessage.originalDataPointUpdate, ActivityLogMessage.originalDataPointUpdateDataSources, - ActivityLogMessage.originalDataPointUpdateDescription, + ActivityLogMessage.originalDataPointUpdateCommentExtentOfForest, + ActivityLogMessage.originalDataPointUpdateCommentForestCharacteristics, ActivityLogMessage.originalDataPointUpdateNationalClasses, ActivityLogMessage.originalDataPointUpdateOriginalData, ActivityLogMessage.originalDataPointUpdateYear, diff --git a/src/server/repository/assessmentCycle/originalDataPoint/commentColumns.ts b/src/server/repository/assessmentCycle/originalDataPoint/commentColumns.ts new file mode 100644 index 0000000000..14c2c2020c --- /dev/null +++ b/src/server/repository/assessmentCycle/originalDataPoint/commentColumns.ts @@ -0,0 +1,7 @@ +import { OriginalDataPointCommentKey } from 'meta/assessment/originalDataPoint' +import { TableNames } from 'meta/assessment/table' + +export const ODPCommentColumns: Record = { + [TableNames.extentOfForest]: `comments_${TableNames.extentOfForest.toLocaleLowerCase()}`, + [TableNames.forestCharacteristics]: `comments_${TableNames.forestCharacteristics.toLocaleLowerCase()}`, +} diff --git a/src/server/repository/assessmentCycle/originalDataPoint/create.ts b/src/server/repository/assessmentCycle/originalDataPoint/create.ts index fd45a6cca8..2db582d44a 100644 --- a/src/server/repository/assessmentCycle/originalDataPoint/create.ts +++ b/src/server/repository/assessmentCycle/originalDataPoint/create.ts @@ -1,10 +1,11 @@ -import { Objects } from 'utils/objects' - import { Assessment } from 'meta/assessment/assessment' import { Cycle } from 'meta/assessment/cycle' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' +import { TableNames } from 'meta/assessment/table' import { BaseProtocol, DB, Schemas } from 'server/db' +import { OriginalDataPointAdapter } from 'server/repository/adapter/originalDataPoint' +import { ODPCommentColumns } from 'server/repository/assessmentCycle/originalDataPoint/commentColumns' export const create = async ( params: { @@ -31,6 +32,9 @@ export const create = async ( const schemaName = Schemas.getNameCycle(assessment, cycle) + const commentColumnExtent = ODPCommentColumns[TableNames.extentOfForest] + const commentColumnForestCharacteristics = ODPCommentColumns[TableNames.forestCharacteristics] + return client.one( ` insert into ${schemaName}.original_data_point ( @@ -39,20 +43,22 @@ export const create = async ( data_source_additional_comments, data_source_methods, data_source_references, - comments, + ${commentColumnExtent}, + ${commentColumnForestCharacteristics}, national_classes, values - ) values ($1, $2, $3, $4::jsonb, $5, $6::jsonb, $7::jsonb, $8::jsonb) returning *;`, + ) values ($1, $2, $3, $4::jsonb, $5, $6, $7, $8::jsonb, $9::jsonb) returning *;`, [ countryIso, year, dataSourceAdditionalComments || '', dataSourceMethods ? JSON.stringify(dataSourceMethods) : '[]', dataSourceReferences || '', - JSON.stringify(comments ?? {}), + comments?.[TableNames.extentOfForest] ?? '', + comments?.[TableNames.forestCharacteristics] ?? '', nationalClasses ? JSON.stringify(nationalClasses) : '[]', values ? JSON.stringify(values) : '{}', ], - Objects.camelize + OriginalDataPointAdapter ) } diff --git a/src/server/repository/assessmentCycle/originalDataPoint/getLastAccepted.ts b/src/server/repository/assessmentCycle/originalDataPoint/getLastAccepted.ts index b0df678fc6..a572c988da 100644 --- a/src/server/repository/assessmentCycle/originalDataPoint/getLastAccepted.ts +++ b/src/server/repository/assessmentCycle/originalDataPoint/getLastAccepted.ts @@ -4,6 +4,7 @@ import { Cycle } from 'meta/assessment/cycle' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' import { BaseProtocol, DB } from 'server/db' +import { OriginalDataPointAdapter, OriginalDataPointDB } from 'server/repository/adapter/originalDataPoint' import { OriginalDataPointQueries } from 'server/repository/assessmentCycle/originalDataPoint/queries' type Props = { @@ -25,6 +26,6 @@ export const getLastAccepted = async (props: Props, client: BaseProtocol = DB): where a.row_number = 1 `, [], - ({ odp }) => odp + (row?: { odp: OriginalDataPointDB } | null) => (row ? OriginalDataPointAdapter(row.odp) : null) ) } diff --git a/src/server/repository/assessmentCycle/originalDataPoint/getMany.ts b/src/server/repository/assessmentCycle/originalDataPoint/getMany.ts index 3b66c90b8f..73403e43ce 100644 --- a/src/server/repository/assessmentCycle/originalDataPoint/getMany.ts +++ b/src/server/repository/assessmentCycle/originalDataPoint/getMany.ts @@ -1,11 +1,10 @@ -import { Objects } from 'utils/objects' - import { CountryIso } from 'meta/area' import { Assessment } from 'meta/assessment/assessment' import { Cycle } from 'meta/assessment/cycle' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' import { BaseProtocol, DB, Schemas } from 'server/db' +import { OriginalDataPointAdapter } from 'server/repository/adapter/originalDataPoint' export const getMany = async ( props: { assessment: Assessment; cycle: Cycle; countryIso: CountryIso }, @@ -18,6 +17,6 @@ export const getMany = async ( return client.map( `select * from ${schemaName}.original_data_point where country_iso = $1;`, [countryIso], - (row) => Objects.camelize(row) + OriginalDataPointAdapter ) } diff --git a/src/server/repository/assessmentCycle/originalDataPoint/getManyWithDescriptionLinks.ts b/src/server/repository/assessmentCycle/originalDataPoint/getManyWithDescriptionLinks.ts index bc9ab7046e..c31c7c982e 100644 --- a/src/server/repository/assessmentCycle/originalDataPoint/getManyWithDescriptionLinks.ts +++ b/src/server/repository/assessmentCycle/originalDataPoint/getManyWithDescriptionLinks.ts @@ -1,11 +1,12 @@ -import { Objects } from 'utils/objects' - import { Assessment } from 'meta/assessment/assessment' import { Cycle } from 'meta/assessment/cycle' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' import { TableNames } from 'meta/assessment/table' import { BaseProtocol, DB, Schemas } from 'server/db' +import { OriginalDataPointAdapter } from 'server/repository/adapter/originalDataPoint' + +import { ODPCommentColumns } from './commentColumns' type Props = { assessment: Assessment @@ -20,13 +21,16 @@ export const getManyWithDescriptionLinks = async ( const schemaName = Schemas.getNameCycle(assessment, cycle) + const commentColumnExtent = ODPCommentColumns[TableNames.extentOfForest] + const commentColumnForestCharacteristics = ODPCommentColumns[TableNames.forestCharacteristics] + return client.map( ` select * from ${schemaName}.original_data_point - where coalesce(comments ->> '${TableNames.extentOfForest}', '') ilike '%href%' - or coalesce(comments ->> '${TableNames.forestCharacteristics}', '') ilike '%href%' + where coalesce(${commentColumnExtent}, '') ilike '%href%' + or coalesce(${commentColumnForestCharacteristics}, '') ilike '%href%' `, [], - (row) => Objects.camelize(row) + OriginalDataPointAdapter ) } diff --git a/src/server/repository/assessmentCycle/originalDataPoint/getManyWithReferenceLinks.ts b/src/server/repository/assessmentCycle/originalDataPoint/getManyWithReferenceLinks.ts index ab8a6390b2..724ffddd48 100644 --- a/src/server/repository/assessmentCycle/originalDataPoint/getManyWithReferenceLinks.ts +++ b/src/server/repository/assessmentCycle/originalDataPoint/getManyWithReferenceLinks.ts @@ -1,10 +1,9 @@ -import { Objects } from 'utils/objects' - import { Assessment } from 'meta/assessment/assessment' import { Cycle } from 'meta/assessment/cycle' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' import { BaseProtocol, DB, Schemas } from 'server/db' +import { OriginalDataPointAdapter } from 'server/repository/adapter/originalDataPoint' type Props = { assessment: Assessment @@ -25,6 +24,6 @@ export const getManyWithReferenceLinks = async ( where data_source_references ilike '%href%' `, [], - (row) => Objects.camelize(row) + OriginalDataPointAdapter ) } diff --git a/src/server/repository/assessmentCycle/originalDataPoint/getOne.ts b/src/server/repository/assessmentCycle/originalDataPoint/getOne.ts index 3dd7010829..a96cbac6bc 100644 --- a/src/server/repository/assessmentCycle/originalDataPoint/getOne.ts +++ b/src/server/repository/assessmentCycle/originalDataPoint/getOne.ts @@ -1,11 +1,10 @@ -import { Objects } from 'utils/objects' - import { CountryIso } from 'meta/area' import { Assessment } from 'meta/assessment/assessment' import { Cycle } from 'meta/assessment/cycle' import { OriginalDataPoint } from 'meta/assessment/originalDataPoint' import { BaseProtocol, DB, Schemas } from 'server/db' +import { OriginalDataPointAdapter } from 'server/repository/adapter/originalDataPoint' type Props = { assessment: Assessment @@ -22,6 +21,6 @@ export const getOne = async (props: Props, client: BaseProtocol = DB): Promise( `select * from ${schemaName}.original_data_point where country_iso = $1 and year = $2;`, [countryIso, year], - Objects.camelize + OriginalDataPointAdapter ) } diff --git a/src/server/repository/assessmentCycle/originalDataPoint/queries/_lastAcceptedActivity.ts b/src/server/repository/assessmentCycle/originalDataPoint/queries/_lastAcceptedActivity.ts index e481102d96..d4ab6c0c32 100644 --- a/src/server/repository/assessmentCycle/originalDataPoint/queries/_lastAcceptedActivity.ts +++ b/src/server/repository/assessmentCycle/originalDataPoint/queries/_lastAcceptedActivity.ts @@ -11,7 +11,8 @@ const activityMessages = [ ActivityLogMessage.originalDataPointCreate, ActivityLogMessage.originalDataPointRemove, ActivityLogMessage.originalDataPointUpdate, - ActivityLogMessage.originalDataPointUpdateDescription, + ActivityLogMessage.originalDataPointUpdateCommentExtentOfForest, + ActivityLogMessage.originalDataPointUpdateCommentForestCharacteristics, ActivityLogMessage.originalDataPointUpdateDataSources, ActivityLogMessage.originalDataPointUpdateOriginalData, ActivityLogMessage.originalDataPointUpdateNationalClasses, diff --git a/src/server/repository/assessmentCycle/originalDataPoint/updateDescription.ts b/src/server/repository/assessmentCycle/originalDataPoint/updateDescription.ts index e712b4fd89..b5dcb229cb 100644 --- a/src/server/repository/assessmentCycle/originalDataPoint/updateDescription.ts +++ b/src/server/repository/assessmentCycle/originalDataPoint/updateDescription.ts @@ -3,7 +3,9 @@ import { Cycle } from 'meta/assessment/cycle' import { OriginalDataPoint, OriginalDataPointCommentKey } from 'meta/assessment/originalDataPoint' import { BaseProtocol, DB, Schemas } from 'server/db' +import { OriginalDataPointAdapter } from 'server/repository/adapter/originalDataPoint' +import { ODPCommentColumns } from './commentColumns' import { getOne } from './getOne' export const updateDescription = async ( @@ -23,17 +25,18 @@ export const updateDescription = async ( } = props const schemaName = Schemas.getNameCycle(assessment, cycle) + const columnName = ODPCommentColumns[field] const value = comments?.[field] ?? '' - const path = `{${field}}` await client.one( ` update ${schemaName}.original_data_point - set comments = jsonb_set(coalesce(comments, '{}'::jsonb), $2::text[], to_jsonb($3::text), true) + set ${columnName} = $2 where id = $1 returning * `, - [id, path, value] + [id, value], + OriginalDataPointAdapter ) return getOne({ assessment, cycle, countryIso, year: String(year) }, client) diff --git a/src/tools/migrations/steps/steps/20251023213324-step-separate-odp-comments.ts b/src/tools/migrations/steps/steps/20251023213324-step-separate-odp-comments.ts index ba0a0deb07..3806cf6a0f 100644 --- a/src/tools/migrations/steps/steps/20251023213324-step-separate-odp-comments.ts +++ b/src/tools/migrations/steps/steps/20251023213324-step-separate-odp-comments.ts @@ -1,9 +1,12 @@ import { Promises } from 'utils/promises' +import { ActivityLogMessage } from 'meta/assessment/activityLog' +import { AssessmentNames } from 'meta/assessment/assessment' import { TableNames } from 'meta/assessment/table' import { AssessmentController } from 'server/controller/assessment' import { BaseProtocol, DB, Schemas } from 'server/db' +import { ODPCommentColumns } from 'server/repository/assessmentCycle/originalDataPoint/commentColumns' const TABLE = 'original_data_point' @@ -37,37 +40,97 @@ type UpdateTableProps = { const _updateOriginalDataPointTable = async (props: UpdateTableProps): Promise => { const { client, schemaName } = props const tableName = `${schemaName}.${TABLE}` - - const hasComments = await _columnExists({ client, columnName: 'comments', schemaName }) - if (!hasComments) { - await DB.query(`alter table ${tableName} add column comments jsonb not null default '{}'::jsonb`) - } + const commentColumnExtent = ODPCommentColumns[TableNames.extentOfForest] + const commentColumnForestCharacteristics = ODPCommentColumns[TableNames.forestCharacteristics] const hasDescription = await _columnExists({ client, columnName: 'description', schemaName }) if (hasDescription) { await DB.none(` - update ${tableName} - set comments = jsonb_strip_nulls( - jsonb_build_object( - '${TableNames.extentOfForest}', - description, - '${TableNames.forestCharacteristics}', - description - ) - ) - where description is not null - `) - await DB.query(`alter table ${tableName} drop column description`) + alter table ${tableName} rename column description to ${commentColumnExtent}; + alter table ${tableName} + alter column ${commentColumnExtent} type text using coalesce(${commentColumnExtent}, ''), + alter column ${commentColumnExtent} set default '', + alter column ${commentColumnExtent} set not null;`) + } + + const hasExtentOfForestComments = await _columnExists({ + client, + columnName: commentColumnExtent, + schemaName, + }) + + if (!hasExtentOfForestComments) { + throw new Error(`Column ${commentColumnExtent} not found in ${tableName}`) + } + + const hasForestCharacteristicsComments = await _columnExists({ + client, + columnName: commentColumnForestCharacteristics, + schemaName, + }) + + if (!hasForestCharacteristicsComments) { + await DB.none(`alter table ${tableName} add column ${commentColumnForestCharacteristics} text default '' not null`) + await client.none(`update ${tableName} set ${commentColumnForestCharacteristics} = ${commentColumnExtent}`) } } +type UpdateActivityLogProps = { + client: BaseProtocol +} + +const _updateActivityLog = async (props: UpdateActivityLogProps): Promise => { + const { client } = props + + const odpActivityMessagesSql = [ + ActivityLogMessage.originalDataPointCreate, + ActivityLogMessage.originalDataPointRemove, + ActivityLogMessage.originalDataPointUpdate, + ActivityLogMessage.originalDataPointUpdateCommentExtentOfForest, + ActivityLogMessage.originalDataPointUpdateCommentForestCharacteristics, + ActivityLogMessage.originalDataPointUpdateDataSources, + ActivityLogMessage.originalDataPointUpdateNationalClasses, + ActivityLogMessage.originalDataPointUpdateOriginalData, + ActivityLogMessage.originalDataPointUpdateYear, + 'originalDataPointUpdateDescription', + ] + .map((message) => `'${message}'`) + .join(',') + + await client.none(` + update public.activity_log al + set message = '${ActivityLogMessage.originalDataPointUpdateCommentExtentOfForest}' + where al.message = 'originalDataPointUpdateDescription' + `) + + await client.none(` + update public.activity_log al + set target = jsonb_set( + jsonb_set( + coalesce(al.target, '{}'::jsonb) - 'description', + '{comments,${TableNames.extentOfForest}}', + to_jsonb(coalesce(coalesce(al.target, '{}'::jsonb) ->> 'description', '')), + true + ), + '{comments,${TableNames.forestCharacteristics}}', + to_jsonb(coalesce(coalesce(al.target, '{}'::jsonb) ->> 'description', '')), + true + ) + where coalesce(al.target, '{}'::jsonb) ? 'description' + and al.message in (${odpActivityMessagesSql}) + `) +} + export default async (client: BaseProtocol): Promise => { + await _updateActivityLog({ client }) + const assessments = await AssessmentController.getAll({}, client) - await Promises.each(assessments, async (assessment) => - Promises.each(assessment.cycles, async (cycle) => { + await Promises.each(assessments, async (assessment) => { + if (assessment.props.name === AssessmentNames.panEuropean) return + await Promises.each(assessment.cycles, async (cycle) => { const schemaName = Schemas.getNameCycle(assessment, cycle) await _updateOriginalDataPointTable({ client, schemaName }) }) - ) + }) }