UNPKG

@opengis/fastify-table

Version:

core-plugins

122 lines (106 loc) 4.73 kB
import { createHash } from 'node:crypto'; import getTemplate from '../../../table/funcs/getTemplate.js'; import metaFormat from '../../../table/funcs/metaFormat/index.js'; const defaultTitles = { editor_date: 'Дата оновлення', editor_id: 'Редактор', сdate: 'Дата створення', uid: 'Автор', body: 'Зміст', entity_id: 'ID Сутності', entity_type: 'Таблиця сутності', file_path: 'Шлях до файлу', uploaded_name: 'Назва файлу', size: 'Розмір файлу', ext: 'Розширення файлу', }; function getValue(val, tableName) { if (!val) return null; if (['crm.files'].includes(tableName)) { return typeof val === 'object' ? JSON.stringify(val) : val; } return typeof val === 'object' ? JSON.stringify(val)?.substring?.(0, 30) : val?.toString?.()?.substring?.(0, 30); } // extract titles and cls from form schema // alt: extract table template from referer -> form export default async function logChanges({ pg, table: table1, tokenData, referer, id, data, uid = 1, type, }) { const table = table1.replace(/"/g, ''); if (!id) { console.error('param id is required'); return null; } if (!table || !pg.pk?.[table]) { console.error('table not found'); return null; } if (!pg.pk?.['log.table_changes'] || !pg.pk?.['log.table_changes_data']) { console.error('log table not found'); return null; } if (!type) { console.error('invalid type'); return null; } try { const { change_id: changeId } = await pg.query(`insert into log.table_changes(change_date,change_type,change_user_id,entity_type,entity_id) values(CURRENT_DATE, $1, $2, $3, $4) returning change_id`, [type, uid, table, id]).then((res) => res.rows?.[0] || {}); const q = `select json_object_agg(entity_key, value_hash) from ( select entity_key, value_hash, ( rank() over (partition by entity_key order by cdate desc) = 1 ) as is_latest from log.table_changes_data where change_id in ( select change_id from log.table_changes where entity_id=$1 and entity_type=$2 ) )q where is_latest`; // console.log(q, type, id); const old = type !== 'INSERT' ? await pg.query(q, [id, table]).then(el => el.rows?.[0]?.json_object_agg || {}) : {}; const body = await getTemplate('form', tokenData?.form); const schema = body?.schema || body || {}; const titles = Object.keys(schema) .reduce((acc, curr) => Object.assign(acc, { [curr]: schema[curr].title || schema[curr].ua }), {}); const cls = Object.keys(schema) .filter(el => schema[el]?.data) .reduce((acc, curr) => Object.assign(acc, { [curr]: schema[curr].data }), {}); const data1 = data ? await metaFormat({ rows: [data], cls, sufix: false, reassign: false, }, pg) : null; const newObj = Object.fromEntries(Object.entries(data1?.[0] || {}).map(el => ([[titles[el[0]] || defaultTitles[el[0]] || el[0]], el[1]]))); const changesData = Object.keys(newObj || {}).map(el => ({ change_id: changeId, entity_key: el, value_old: getValue(old?.[el], table), value_new: type === 'DELETE' ? null : getValue(newObj?.[el], table), value_hash: newObj?.[el] ? createHash('md5').update(JSON.stringify(newObj?.[el])).digest('hex') : null, uid, })).filter(el => (old?.[el.entity_key] !== el.value_hash)); const res = await Promise.all(changesData.map(async (el) => { const insertQuery = `insert into log.table_changes_data (${Object.entries(el)?.map((key) => `"${key[0]}"`).join(',')}) values (${Object.entries(el)?.map((key, i) => `$${i + 1}`).join(',')}) returning *`; const { rows = [] } = await pg.query(insertQuery, [...Object.entries(el).map((el1) => (el1[1] && typeof el1[1] === 'object' && (!Array.isArray(el1[1]) || typeof el1[1]?.[0] === 'object') ? JSON.stringify(el1[1]) : el1[1]))]) || {}; return rows[0]; })); const newData = type === 'DELETE' ? {} : (Array.isArray(res) ? res : [res]).reduce((acc, curr) => Object.assign(acc, { [curr.entity_key]: curr.value_new }), {}); // console.log('logChanges OK', type); return { change_id: changeId, entity_type: table, entity_id: id, uid, change_type: type, old, new: newData, }; } catch (err) { console.error('logChanges error', type, table, id, data, err.toString()); return { error: err.toString(), entity_type: table, entity_id: id, uid, change_type: type, }; } }