UNPKG

newmax-utils

Version:
324 lines (323 loc) 16.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ScriptSQL = void 0; const ApiError_1 = require("./ApiError"); const Moment_1 = require("./libs/Moment"); class Script { basicColumns = { nomId: (el = 'nomId') => ({ orig: 'CN.id', as: `CN.id as "${el}"` }), sizeId: (el = 'sizeId') => ({ orig: 'fk_size_id', as: `fk_size_id as "${el}"` }), companyName: (el = 'companyName') => ({ orig: 'SC.name', as: `SC.name as "${el}"` }), companyId: (el = 'companyId') => ({ orig: 'SC.id', as: `SC.id as "${el}"` }), group: (el = 'group') => ({ orig: 'SG.art_group', as: `SG.art_group as "${el}"` }), category: (el = 'category') => ({ orig: 'WC.id', as: `WC.id as "${el}"` }), abcSales: (el = 'abcSales') => ({ orig: 'VA.tag_amount', as: `VA.tag_amount as "${el}"` }), abcMargin: (el = 'abcMargin') => ({ orig: 'VA.tag_margin', as: `VA.tag_margin as "${el}"` }), article: (el = 'article') => ({ orig: 'ONOM.article', as: `ONOM.article as "${el}"` }), code: (el = 'code') => ({ orig: 'ONOM.code', as: `ONOM.code as "${el}"` }), sku: (el = 'sku') => ({ orig: 'ONOM.sku', as: `ONOM.sku as "${el}"` }), oSize: (el = 'oSize') => ({ orig: 'ONOM.size', as: `ONOM.size as "${el}"` }), nomType: (el = 'nomType') => ({ orig: 'ONOM.type', as: `ONOM.type as "${el}"` }), barcodes: (el = 'barcodes') => ({ orig: 'CS.barcodes', as: `CS.barcodes as "${el}"` }), vendorCode: (el = 'vendorCode') => ({ orig: 'CN.vendor_code', as: `CN.vendor_code as "${el}"`, }), color: (el = 'color') => ({ orig: 'CN.color', as: `CN.color as "${el}"` }), nmid: (el = 'nmid') => ({ orig: 'CN.nmid', as: `CN.nmid as "${el}"` }), brand: (el = 'brand') => ({ orig: 'CN.brand', as: `CN.brand as "${el}"` }), title: (el = 'title') => ({ orig: 'CN.title', as: `CN.title as "${el}"` }), size: (el = 'size') => ({ orig: 'CS.size', as: `CS.size as "${el}"` }), altSize: (el = 'altSize') => ({ orig: 'CS.alt_size', as: `CS.alt_size as "${el}"` }), whName: (el = 'whName') => ({ orig: 'CW.ru_name', as: `CW.ru_name as "${el}"` }), whId: (el = 'whId') => ({ orig: 'CW.id', as: `CW.id as "${el}"` }), tDate: (el = 'tDate') => ({ orig: 'WD.id', as: `WD.id as "${el}"` }), date: (el = 'date') => ({ orig: 'WD.date', as: `WD.date as "${el}"` }), month: (el = 'month') => ({ orig: 'WD.month', as: `WD.month as "${el}"` }), year: (el = 'year') => ({ orig: 'WD.year', as: `WD.year as "${el}"` }), week: (el = 'week') => ({ orig: 'WD.week', as: `WD.week as "${el}"` }), market: (el = 'market') => ({ orig: 'CN.mp', as: `CN.mp as "${el}"` }), region: (el = 'region') => ({ orig: 'WA.region', as: `WA.region as "${el}"` }), state: (el = 'state') => ({ orig: 'WA.state', as: `WA.state as "${el}"` }), packSize: (el = 'packSize') => ({ orig: 'ONOM.pcs_in_pack', as: `ONOM.pcs_in_pack as "${el}"`, }), supplier: (el = 'supplier') => ({ orig: 'ONOM.supplier', as: `ONOM.supplier as "${el}"` }), }; where = (filters, columns) => { return ('WHERE ' + filters.reduce((prev, { id, value, type = 'LIKE' }, i, arr) => { if (!columns[id]) throw new ApiError_1.ApiError(400, `Attribute "${id}" not found`, { attribute: id }); const attr = id.replace(id, columns[id]()?.orig || id); let result = `${prev}${attr} `; let currentValue = ''; if (value instanceof Array) { currentValue = type === '!=' ? `NOT IN (${value.map((item) => (typeof item === 'string' ? `'${item}'` : item)).join(', ')})` : `= ANY('{${value.join(', ')}}')`; } if (typeof value === 'number') { currentValue = `${type} ${value}`; } if (typeof value === 'string') { value = ['=', '!='].includes(type) ? `'${value}'` : `'%${value}%'`; currentValue = `${type} ${value}`; } if (['NULL', 'NOT NULL'].includes(type)) { currentValue = `IS ${type}`; } if (i !== arr.length - 1) currentValue += ' AND '; return result + currentValue; }, '')); }; basicWhere = ({ dateFrom, dateTo }) => { dateFrom ||= Moment_1.Moment.subtractToCurrentDate(1, 'day'); dateTo ||= Moment_1.Moment.subtractToCurrentDate(1, 'day'); return `WD.id BETWEEN '${Moment_1.Moment.convertDateToTimestamp(dateFrom, 'YYYY-MM-DD', 'x')}' AND '${Moment_1.Moment.convertDateToTimestamp(dateTo, 'YYYY-MM-DD', 'x')}' `; }; leftJoin = (leftjoin, attributes, filters, sorting) => { const SGRP = { name: 'group', table: 'LEFT JOIN static_group SG ON SG.id = CN.id', col: ['group'], }; const WCAT = { name: 'category', table: 'LEFT JOIN worker_category WC ON WC.id = fk_category_id', col: ['category'], }; const SSER = { name: 'service', table: `LEFT JOIN static_service SS ON SS.id = (fk_date_id || 'packing')`, col: ['service'], }; const STAX = { name: 'tax', table: 'LEFT JOIN static_tax ST ON ST.id = (fk_date_id || CN.fk_company_id)', col: ['tax'], }; const WADD = { name: 'address', table: 'LEFT JOIN worker_address WA ON WA.id = fk_address_id', col: ['city', 'region', 'state'], }; const CWAR = { name: 'warehouse', table: 'LEFT JOIN common.warehouse CW ON CW.id = fk_wh_id', col: ['whName', 'whId', 'isBasic'], }; const ONOM = { name: 'onec_nomenclature', table: 'LEFT JOIN (SELECT id, supplier, code, article, sku, size, type, pcs_in_pack FROM ONOM) ONOM ON ONOM.id = CS.id', col: ['supplier', 'article', 'code', 'sku', 'oSize', 'nomType', 'packSize', 'ocCategory'], }; const OPUR = { name: 'onec_purch', table: 'LEFT JOIN (SELECT id, price FROM OPUR) OPUR ON OPUR.id = CS.id', col: ['purch'], }; const setter = new Set(); attributes.forEach((el) => (el instanceof Array ? setter.add(el[0]) : setter.add(el))); filters.forEach((el) => setter.add(el)); sorting.forEach((el) => setter.add(el)); const filterArr = [CWAR, SGRP, WCAT, WADD, SSER, STAX, ONOM, OPUR]; filterArr.forEach(({ col, table }) => { if (this.isIncludeColumn(col, Array.from(setter))) leftjoin.push(table); }); return leftjoin.join('\n'); }; withAs = (attributes, filters, sorting) => { const withas = []; const ONOM = { table: `ONOM AS (SELECT DISTINCT(CS.id), ONOM.supplier, ONOM.code, ONOM.article, ONOM.sku, ONOM.size, ONOM.type, ONOM.pcs_in_pack FROM common.sizes CS LEFT JOIN LATERAL unnest(CS.barcodes) AS BAR ON TRUE LEFT JOIN onec_nomenclature ONOM ON ONOM.id = BAR WHERE ONOM.article IS NOT NULL)`, col: ['supplier', 'code', 'article', 'sku', 'oSize', 'nomType', 'packSize', 'ocCategory'], }; const OPUR = { table: `OPUR AS (SELECT DISTINCT(CS.id), PUR.price FROM common.sizes CS LEFT JOIN LATERAL unnest(CS.barcodes) AS BAR ON TRUE LEFT JOIN (SELECT id, price FROM onec_purch) PUR ON PUR.id = BAR WHERE PUR.price IS NOT NULL)`, col: ['purch'], }; // const CVOL = { // table: `CVOL AS (SELECT ONOM.sku, MAX(CN.volume) as maxvolume FROM common.nomenclature CN // LEFT JOIN common.sizes CS ON CS.fk_nom_id = CN.id // LEFT JOIN (SELECT DISTINCT(id), article, sku, size FROM ONOM) ONOM ON ONOM.id = CS.id // GROUP BY ONOM.sku // )`, // col: ['volume'] // }; const setter = new Set(); attributes.forEach((el) => (el instanceof Array ? setter.add(el[0]) : setter.add(el))); filters.forEach((el) => setter.add(el)); sorting.forEach((el) => setter.add(el)); [ONOM, OPUR].forEach(({ col, table }) => { if (this.isIncludeColumn(col, Array.from(setter))) withas.push(table); }); return withas.length ? 'WITH ' + withas.join(',\n') : ''; }; /** * Метод проверки атрибутов. * @param {string | Array<string>} columns - Проверяющий список колонок * @param {Array<string | Array<string>>} attrList - Проверяемый список колонок * @returns {boolean} Возвращает флаг - существует ли аттрибут в списке */ isIncludeColumn = (columns, attrList) => { return columns instanceof Array ? columns.some((column) => attrList.includes(column)) : attrList.includes(columns); }; /** * Метод получение SQL скрипта вывода данных. * @param {string} table - Имя таблицы. (required) * @param {Pick<TScriptDetails, "data">} data - Объект с атрибутами и QUERY параметрами запроса. (required) * @param {object} columns - Проверяющий и переименовывающий колонки объект. (optional) * @param {Array<string>} leftjoinOn - Тип таблиц связывания. (optional) * @returns {string} Возвращает готовый для запроса SQL скрипт */ details = (table, { attributes, ...query }, columns, leftjoinOn = []) => { const filtredAttr = attributes.filter((attr) => attr instanceof Array ? !columns.orig[attr[0]] : !columns.orig[attr]); const filtredFilter = query.filters ? query.filters.filter(({ id }) => !columns.orig[id]).map(({ id }) => id) : []; const filtredSort = query.sorting ? query.sorting.filter(({ id }) => !columns.orig[id]).map(({ id }) => id) : []; const leftjoin = this.leftJoin([...leftjoinOn], filtredAttr, filtredFilter, filtredSort); const withas = this.withAs(filtredAttr, filtredFilter, filtredSort); const fullcolumns = { ...this.basicColumns, ...columns.orig, ...columns.foreign, }; fullcolumns['year']; const limit = query.limit ? `LIMIT ${query.limit}` : ''; const offset = query.offset ? `OFFSET ${query.offset}` : ''; const whereBasic = query.dateFrom || query.dateTo ? (!query.filters?.length ? 'WHERE ' : ' AND ') + this.basicWhere(query) : ''; const where = query.filters?.length ? this.where(query.filters, fullcolumns) + whereBasic : whereBasic; const orderby = query.sorting?.length ? 'ORDER BY ' + query.sorting.reduce((prev, { id, desc }, i, arr) => { if (!fullcolumns[id]) throw new ApiError_1.ApiError(400, `Attribute "${id}" not found`, { attribute: id }); const attr = id.replace(id, fullcolumns[id]()?.orig || id); let result = `${prev}${attr} ${desc ? 'DESC' : 'ASC'}`; if (i !== arr.length - 1) result += ', '; return result; }, '') : ''; const attr = attributes .filter((attr) => { attr = attr instanceof Array ? attr[0] : attr; if (!fullcolumns[attr]) throw new ApiError_1.ApiError(400, `Attribute "${attr}" not found`, { attribute: attr }); return !!fullcolumns[attr]().as; }) .map((attr) => { const attrOrig = attr instanceof Array ? attr[0] : attr; const attrRe = attr instanceof Array ? attr[1] : attr; return attrOrig.replace(attrOrig, fullcolumns[attrOrig](attrRe)?.as || fullcolumns[attrOrig](attrRe)?.orig); }) .join(', '); let groupby = attributes .filter((attr) => { attr = attr instanceof Array ? attr[0] : attr; if (!fullcolumns[attr]) throw new ApiError_1.ApiError(400, `Attribute "${attr}" not found`, { attribute: attr }); return !!fullcolumns[attr]().orig; }) .map((attr) => { const attrOrig = attr instanceof Array ? attr[0] : attr; const attrRe = attr instanceof Array ? attr[1] : attr; return attrOrig.replace(attrOrig, fullcolumns[attrOrig](attrRe).orig); }) .join(', '); if (groupby) groupby = 'GROUP BY ' + groupby; return ` ${withas} SELECT ${attr}, COUNT(*) OVER() as "totalRow" FROM ${table} ${leftjoin} ${where} ${groupby} ${orderby} ${limit} ${offset} `; }; /** * Метод получение SQL скрипта для вывода сумм с группировкой. * @param {string} table - Имя таблицы. (required) * @param {Pick<TScriptSummary, "data">} data - Объект с атрибутами и QUERY параметрами запроса. (required) * @param {object} columns - Проверяющий и переименовывающий колонки объект. (optional) * @param {string} type - Тип таблиц связывания. (optional) * @returns {string} Возвращает готовый для запроса SQL скрипт */ summary = (table, { attributes, ...query }, columns, leftjoinOn = []) => { const filtredAttr = attributes.filter((attr) => attr instanceof Array ? !columns.orig[attr[0]] : !columns.orig[attr]); const filtredFilter = query.filters ? query.filters.filter(({ id }) => !columns.orig[id]).map(({ id }) => id) : []; const leftjoin = this.leftJoin([...leftjoinOn], filtredAttr, filtredFilter, []); const withas = this.withAs(filtredAttr, filtredFilter, []); const fullcolumns = { ...this.basicColumns, ...columns.orig, ...columns.foreign, }; const whereBasic = query.dateFrom || query.dateTo ? (!query.filters?.length ? 'WHERE ' : ' AND ') + this.basicWhere(query) : ''; const where = query.filters?.length ? this.where(query.filters, fullcolumns) + whereBasic : whereBasic; const attrSum = attributes ? attributes .filter((attr) => (attr instanceof Array ? !fullcolumns[attr[0]]().orig : !fullcolumns[attr]().orig) || (query.sumby && query.sumby.find((item) => item === attr))) .map((attr) => { const attrOrig = attr instanceof Array ? attr[0] : attr; const attrRe = attr instanceof Array ? attr[1] : attr; return attrOrig.replace(attrOrig, fullcolumns[attrOrig](attrRe)?.as || fullcolumns[attrOrig](attrRe)?.orig); }) .join(', ') : null; const groupbySum = query.sumby?.length ? 'GROUP BY ' + attributes .filter((attr) => query.sumby && query.sumby.find((item) => item === attr)) .map((attr) => { const attrOrig = attr instanceof Array ? attr[0] : attr; const attrRe = attr instanceof Array ? attr[1] : attr; return attrOrig.replace(attrOrig, fullcolumns[attrOrig](attrRe).orig); }) .join(', ') : ''; return ` SELECT ${attrSum} FROM ${table} ${leftjoin} ${where} ${groupbySum} `; }; } exports.ScriptSQL = new Script();