newmax-utils
Version:
Utils & Libs for Newmax Tech
324 lines (323 loc) • 16.8 kB
JavaScript
;
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();