157 lines
4.9 KiB
JavaScript
157 lines
4.9 KiB
JavaScript
|
|
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
|
|
|
|
module.exports = Self => {
|
|
Self.remoteMethod('getLeaves', {
|
|
description: 'Returns the first shipped and landed possible for params',
|
|
accessType: '',
|
|
accepts: [{
|
|
arg: 'zoneFk',
|
|
type: 'Number',
|
|
required: true,
|
|
},
|
|
{
|
|
arg: 'parentFk',
|
|
type: 'Number',
|
|
default: 1,
|
|
required: false,
|
|
},
|
|
{
|
|
arg: 'filter',
|
|
type: 'Object',
|
|
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
|
http: {source: 'query'}
|
|
}],
|
|
returns: {
|
|
type: ['object'],
|
|
root: true
|
|
},
|
|
http: {
|
|
path: `/getLeaves`,
|
|
verb: 'GET'
|
|
}
|
|
});
|
|
|
|
Self.getLeaves = async(zoneFk, parentFk = 1, filter) => {
|
|
let conn = Self.dataSource.connector;
|
|
let stmts = [];
|
|
|
|
stmts.push(`DROP TEMPORARY TABLE IF EXISTS tmp.checkedChilds`);
|
|
stmts.push(new ParameterizedSQL(
|
|
`CREATE TEMPORARY TABLE tmp.checkedChilds (
|
|
id INT,
|
|
name VARCHAR(100),
|
|
lft INT,
|
|
rgt INT,
|
|
depth BIGINT(22),
|
|
sons DECIMAL(10, 0),
|
|
isIncluded TINYINT
|
|
) ENGINE = MEMORY`));
|
|
|
|
if (parentFk === 1) {
|
|
stmts.push(new ParameterizedSQL(
|
|
`INSERT INTO tmp.checkedChilds
|
|
SELECT
|
|
zg.id,
|
|
zg.name,
|
|
zg.lft,
|
|
zg.rgt,
|
|
zg.depth,
|
|
zg.sons,
|
|
zi.isIncluded
|
|
FROM zoneGeo zg
|
|
JOIN zoneIncluded zi ON zi.geoFk = zg.id
|
|
AND zoneFk = ?`, [zoneFk]));
|
|
}
|
|
|
|
let stmt = new ParameterizedSQL(
|
|
`SELECT * FROM (
|
|
SELECT
|
|
zg.id,
|
|
zg.name,
|
|
zg.lft,
|
|
zg.rgt,
|
|
zg.depth,
|
|
zg.sons,
|
|
IF(ch.id = zg.id, isIncluded, null) isIncluded
|
|
FROM zoneGeo zg
|
|
JOIN tmp.checkedChilds ch
|
|
ON zg.lft <= ch.lft AND zg.rgt >= ch.rgt
|
|
AND zg.depth > 0
|
|
UNION ALL
|
|
SELECT
|
|
child.id,
|
|
child.name,
|
|
child.lft,
|
|
child.rgt,
|
|
child.depth,
|
|
child.sons,
|
|
zi.isIncluded
|
|
FROM zoneGeo parent
|
|
JOIN zoneGeo child ON child.lft > parent.lft
|
|
AND child.rgt < parent.rgt
|
|
AND child.depth = parent.depth + 1
|
|
LEFT JOIN zoneIncluded zi ON zi.geoFk = child.id
|
|
AND zoneFk = ?
|
|
WHERE parent.id = ?) AS nst`, [zoneFk, parentFk]);
|
|
|
|
// Get nodes from depth greather than Origin
|
|
stmt.merge(conn.makeSuffix(filter));
|
|
stmt.merge('GROUP BY nst.id');
|
|
|
|
const resultIndex = stmts.push(stmt) - 1;
|
|
|
|
const sql = ParameterizedSQL.join(stmts, ';');
|
|
const result = await Self.rawStmt(sql);
|
|
const nodes = result[resultIndex];
|
|
|
|
if (nodes.length == 0)
|
|
return nodes;
|
|
|
|
// Get parent nodes
|
|
const minorDepth = nodes.reduce((a, b) => {
|
|
return b < a ? b : a;
|
|
}).depth;
|
|
|
|
const parentNodes = nodes.filter(element => {
|
|
return element.depth === minorDepth;
|
|
});
|
|
const leaves = Object.assign([], sortNodes(parentNodes));
|
|
|
|
nestLeaves(leaves);
|
|
|
|
function nestLeaves(elements) {
|
|
elements.forEach(element => {
|
|
element.childs = Object.assign([], getLeaves(element));
|
|
|
|
nestLeaves(element.childs);
|
|
});
|
|
}
|
|
|
|
function getLeaves(parent) {
|
|
let elements = nodes.filter(element => {
|
|
return element.lft > parent.lft && element.rgt < parent.rgt
|
|
&& element.depth === parent.depth + 1;
|
|
});
|
|
|
|
return sortNodes(elements);
|
|
}
|
|
|
|
return leaves;
|
|
};
|
|
|
|
function sortNodes(nodes) {
|
|
return nodes.sort((a, b) => {
|
|
if (b.isIncluded !== a.isIncluded) {
|
|
if (a.isIncluded == null)
|
|
return 1;
|
|
if (b.isIncluded == null)
|
|
return -1;
|
|
return b.isIncluded - a.isIncluded;
|
|
}
|
|
|
|
return a.name.localeCompare(b.name);
|
|
});
|
|
}
|
|
};
|