From 1e3ab2d31a1034183c572ead9ef8a51e60462b50 Mon Sep 17 00:00:00 2001 From: guillermo Date: Thu, 29 Aug 2024 10:07:02 +0200 Subject: [PATCH 1/6] feat: refs #7905 Added param toCsv --- modules/entry/back/methods/entry/getBuys.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/modules/entry/back/methods/entry/getBuys.js b/modules/entry/back/methods/entry/getBuys.js index 245dada09..65fb047c6 100644 --- a/modules/entry/back/methods/entry/getBuys.js +++ b/modules/entry/back/methods/entry/getBuys.js @@ -1,5 +1,6 @@ const UserError = require('vn-loopback/util/user-error'); const mergeFilters = require('vn-loopback/util/filter').mergeFilters; +const {toCSV} = require('vn-loopback/util/csv'); module.exports = Self => { Self.remoteMethodCtx('getBuys', { @@ -16,6 +17,11 @@ module.exports = Self => { arg: 'filter', type: 'object', description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string' + }, + { + arg: 'toCsv', + type: 'boolean', + description: 'If true, return the data in CSV format' } ], returns: { @@ -28,7 +34,7 @@ module.exports = Self => { } }); - Self.getBuys = async(ctx, id, filter, options) => { + Self.getBuys = async(ctx, id, filter, toCsv, options) => { const userId = ctx.req.accessToken.userId; const models = Self.app.models; const myOptions = {}; @@ -129,6 +135,15 @@ module.exports = Self => { }; defaultFilter = mergeFilters(defaultFilter, filter); - return models.Buy.find(defaultFilter, myOptions); + const data = models.Buy.find(defaultFilter, myOptions); + + if (toCsv) { + return [ + toCSV(data), + 'text/csv', + `attachment; filename="${id}.csv"` + ]; + } else + return data; }; }; From 72b4607d54344cf49d37d627d0e4a804e0e06927 Mon Sep 17 00:00:00 2001 From: guillermo Date: Thu, 29 Aug 2024 12:19:06 +0200 Subject: [PATCH 2/6] feat: refs #7905 Added new method getBuysCsv --- .../11206-turquoiseCyca/00-firstScript.sql | 2 + modules/entry/back/methods/entry/getBuys.js | 19 +---- .../entry/back/methods/entry/getBuysCsv.js | 75 +++++++++++++++++++ modules/entry/back/models/entry.js | 1 + 4 files changed, 80 insertions(+), 17 deletions(-) create mode 100644 db/versions/11206-turquoiseCyca/00-firstScript.sql create mode 100644 modules/entry/back/methods/entry/getBuysCsv.js diff --git a/db/versions/11206-turquoiseCyca/00-firstScript.sql b/db/versions/11206-turquoiseCyca/00-firstScript.sql new file mode 100644 index 000000000..c1d63fcec --- /dev/null +++ b/db/versions/11206-turquoiseCyca/00-firstScript.sql @@ -0,0 +1,2 @@ +INSERT INTO salix.ACL (model,property,principalId) + VALUES ('Entry','getBuysCsv','supplier'); diff --git a/modules/entry/back/methods/entry/getBuys.js b/modules/entry/back/methods/entry/getBuys.js index 65fb047c6..245dada09 100644 --- a/modules/entry/back/methods/entry/getBuys.js +++ b/modules/entry/back/methods/entry/getBuys.js @@ -1,6 +1,5 @@ const UserError = require('vn-loopback/util/user-error'); const mergeFilters = require('vn-loopback/util/filter').mergeFilters; -const {toCSV} = require('vn-loopback/util/csv'); module.exports = Self => { Self.remoteMethodCtx('getBuys', { @@ -17,11 +16,6 @@ module.exports = Self => { arg: 'filter', type: 'object', description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string' - }, - { - arg: 'toCsv', - type: 'boolean', - description: 'If true, return the data in CSV format' } ], returns: { @@ -34,7 +28,7 @@ module.exports = Self => { } }); - Self.getBuys = async(ctx, id, filter, toCsv, options) => { + Self.getBuys = async(ctx, id, filter, options) => { const userId = ctx.req.accessToken.userId; const models = Self.app.models; const myOptions = {}; @@ -135,15 +129,6 @@ module.exports = Self => { }; defaultFilter = mergeFilters(defaultFilter, filter); - const data = models.Buy.find(defaultFilter, myOptions); - - if (toCsv) { - return [ - toCSV(data), - 'text/csv', - `attachment; filename="${id}.csv"` - ]; - } else - return data; + return models.Buy.find(defaultFilter, myOptions); }; }; diff --git a/modules/entry/back/methods/entry/getBuysCsv.js b/modules/entry/back/methods/entry/getBuysCsv.js new file mode 100644 index 000000000..76b9cdc57 --- /dev/null +++ b/modules/entry/back/methods/entry/getBuysCsv.js @@ -0,0 +1,75 @@ +const UserError = require('vn-loopback/util/user-error'); +const {toCSV} = require('vn-loopback/util/csv'); + +module.exports = Self => { + Self.remoteMethodCtx('getBuys', { + description: 'Returns buys for one entry', + accessType: 'READ', + accepts: [{ + arg: 'id', + type: 'number', + required: true, + description: 'The entry id', + http: {source: 'path'} + } + ], + returns: [ + { + arg: 'body', + type: 'file', + root: true + }, { + arg: 'Content-Type', + type: 'String', + http: {target: 'header'} + }, { + arg: 'Content-Disposition', + type: 'String', + http: {target: 'header'} + } + ], + http: { + path: `/:id/getBuysCsv`, + verb: 'GET' + } + }); + + Self.getBuys = async(ctx, id, options) => { + const userId = ctx.req.accessToken.userId; + const models = Self.app.models; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const client = await models.Client.findById(userId, myOptions); + const supplier = await models.Supplier.findOne({where: {nif: client.fi}}, myOptions); + if (supplier) { + const isEntryOwner = (await Self.findById(id)).supplierFk === supplier.id; + if (!isEntryOwner) throw new UserError('Access Denied'); + } + + const data = await Self.rawSql(` + SELECT b.id, + b.itemFk, + i.name, + b.stickers, + b.packing, + b.grouping, + b.packing, + b.groupingMode, + b.quantity, + b.packagingFk, + b.weight, + b.buyingValue, + b.price2, + b.price3, + b.printedStickers + FROM buy b + JOIN item i ON i.id = b.itemFk + WHERE b.entryFk = ? + `, [id]); + + return [toCSV(data), 'text/csv', `inline; filename="buys-${id}.csv"`]; + }; +}; diff --git a/modules/entry/back/models/entry.js b/modules/entry/back/models/entry.js index b11d64415..8ca79f531 100644 --- a/modules/entry/back/models/entry.js +++ b/modules/entry/back/models/entry.js @@ -3,6 +3,7 @@ module.exports = Self => { require('../methods/entry/filter')(Self); require('../methods/entry/getEntry')(Self); require('../methods/entry/getBuys')(Self); + require('../methods/entry/getBuysCsv')(Self); require('../methods/entry/importBuys')(Self); require('../methods/entry/importBuysPreview')(Self); require('../methods/entry/lastItemBuys')(Self); From e50c67c3058bacb56c7964a0c52dc5d9aaff1109 Mon Sep 17 00:00:00 2001 From: guillermo Date: Thu, 29 Aug 2024 12:22:29 +0200 Subject: [PATCH 3/6] feat: refs #7905 Added new method getBuysCsv --- db/versions/11206-turquoiseCyca/00-firstScript.sql | 2 +- modules/entry/back/methods/entry/getBuysCsv.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/db/versions/11206-turquoiseCyca/00-firstScript.sql b/db/versions/11206-turquoiseCyca/00-firstScript.sql index c1d63fcec..ab6b35a0f 100644 --- a/db/versions/11206-turquoiseCyca/00-firstScript.sql +++ b/db/versions/11206-turquoiseCyca/00-firstScript.sql @@ -1,2 +1,2 @@ -INSERT INTO salix.ACL (model,property,principalId) +INSERT IGNORE INTO salix.ACL (model,property,principalId) VALUES ('Entry','getBuysCsv','supplier'); diff --git a/modules/entry/back/methods/entry/getBuysCsv.js b/modules/entry/back/methods/entry/getBuysCsv.js index 76b9cdc57..541179a1d 100644 --- a/modules/entry/back/methods/entry/getBuysCsv.js +++ b/modules/entry/back/methods/entry/getBuysCsv.js @@ -2,8 +2,8 @@ const UserError = require('vn-loopback/util/user-error'); const {toCSV} = require('vn-loopback/util/csv'); module.exports = Self => { - Self.remoteMethodCtx('getBuys', { - description: 'Returns buys for one entry', + Self.remoteMethodCtx('getBuysCsv', { + description: 'Returns buys for one entry in CSV file format', accessType: 'READ', accepts: [{ arg: 'id', @@ -34,7 +34,7 @@ module.exports = Self => { } }); - Self.getBuys = async(ctx, id, options) => { + Self.getBuysCsv = async(ctx, id, options) => { const userId = ctx.req.accessToken.userId; const models = Self.app.models; const myOptions = {}; From 0f4bc3f83b33e320bdd7cd748d1e26716902f45c Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Fri, 30 Aug 2024 09:42:50 +0200 Subject: [PATCH 4/6] feat(salix): refs #7905 #7905 use getBuys toCSV flattened --- loopback/util/flatten.js | 28 ++++++++ .../entry/back/methods/entry/getBuysCsv.js | 65 ++++++++----------- 2 files changed, 56 insertions(+), 37 deletions(-) create mode 100644 loopback/util/flatten.js diff --git a/loopback/util/flatten.js b/loopback/util/flatten.js new file mode 100644 index 000000000..90e9184b7 --- /dev/null +++ b/loopback/util/flatten.js @@ -0,0 +1,28 @@ + +function flatten(dataArray) { + return dataArray.map(item => flatten(item.__data)); +} +function flattenObj(data, prefix = '') { + let result = {}; + try { + for (let key in data) { + if (!data[key]) continue; + + const newKey = prefix ? `${prefix}_${key}` : key; + const value = data[key]; + + if (typeof value === 'object' && value !== null && !Array.isArray(value)) + Object.assign(result, flattenObj(value.__data, newKey)); + else + result[newKey] = value; + } + } catch (error) { + console.error(error); + } + + return result; +} +module.exports = { + flatten, + flattenObj, +}; diff --git a/modules/entry/back/methods/entry/getBuysCsv.js b/modules/entry/back/methods/entry/getBuysCsv.js index 541179a1d..647f41d22 100644 --- a/modules/entry/back/methods/entry/getBuysCsv.js +++ b/modules/entry/back/methods/entry/getBuysCsv.js @@ -1,5 +1,5 @@ -const UserError = require('vn-loopback/util/user-error'); const {toCSV} = require('vn-loopback/util/csv'); +const {flatten} = require('vn-loopback/util/flatten'); module.exports = Self => { Self.remoteMethodCtx('getBuysCsv', { @@ -35,41 +35,32 @@ module.exports = Self => { }); Self.getBuysCsv = async(ctx, id, options) => { - const userId = ctx.req.accessToken.userId; - const models = Self.app.models; - const myOptions = {}; - - if (typeof options == 'object') - Object.assign(myOptions, options); - - const client = await models.Client.findById(userId, myOptions); - const supplier = await models.Supplier.findOne({where: {nif: client.fi}}, myOptions); - if (supplier) { - const isEntryOwner = (await Self.findById(id)).supplierFk === supplier.id; - if (!isEntryOwner) throw new UserError('Access Denied'); - } - - const data = await Self.rawSql(` - SELECT b.id, - b.itemFk, - i.name, - b.stickers, - b.packing, - b.grouping, - b.packing, - b.groupingMode, - b.quantity, - b.packagingFk, - b.weight, - b.buyingValue, - b.price2, - b.price3, - b.printedStickers - FROM buy b - JOIN item i ON i.id = b.itemFk - WHERE b.entryFk = ? - `, [id]); - - return [toCSV(data), 'text/csv', `inline; filename="buys-${id}.csv"`]; + const data = await Self.getBuys(ctx, id, null, options); + const dataFlatted = flatten(data); + return [toCSV(dataFlatted), 'text/csv', `inline; filename="buys-${id}.csv"`]; }; }; +// function flattenJSON(dataArray) { +// return dataArray.map(item => flatten(item.__data)); +// } +// function flatten(data, prefix = '') { +// let result = {}; +// try { +// for (let key in data) { +// if (!data[key]) continue; + +// const newKey = prefix ? `${prefix}_${key}` : key; +// const value = data[key]; + +// if (typeof value === 'object' && value !== null && !Array.isArray(value)) +// Object.assign(result, flatten(value.__data, newKey)); +// else +// result[newKey] = value; +// } +// } catch (error) { +// console.error(error); +// } + +// return result; +// } + From d49707828b22169ed88be14b1e987f08f1d23d99 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Thu, 5 Sep 2024 09:13:33 +0200 Subject: [PATCH 5/6] fix(salix): refs #7905 #7905 use right fn to flatten data --- loopback/util/flatten.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loopback/util/flatten.js b/loopback/util/flatten.js index 90e9184b7..d6030f7d0 100644 --- a/loopback/util/flatten.js +++ b/loopback/util/flatten.js @@ -1,6 +1,6 @@ function flatten(dataArray) { - return dataArray.map(item => flatten(item.__data)); + return dataArray.map(item => flattenObj(item.__data)); } function flattenObj(data, prefix = '') { let result = {}; From 2aeff1957811614c5523f8eb67dde70972528d95 Mon Sep 17 00:00:00 2001 From: guillermo Date: Thu, 5 Sep 2024 09:21:00 +0200 Subject: [PATCH 6/6] fix: refs #7905 added comments to flatten.js --- loopback/util/flatten.js | 15 ++++++++++++ .../entry/back/methods/entry/getBuysCsv.js | 24 ------------------- 2 files changed, 15 insertions(+), 24 deletions(-) diff --git a/loopback/util/flatten.js b/loopback/util/flatten.js index d6030f7d0..35c368d3b 100644 --- a/loopback/util/flatten.js +++ b/loopback/util/flatten.js @@ -1,7 +1,22 @@ +/** + * Flattens an array of objects by converting each object into a flat structure. + * + * @param {Array} dataArray Array of objects to be flattened + * @return {Array} Array of flattened objects + */ function flatten(dataArray) { return dataArray.map(item => flattenObj(item.__data)); } + +/** + * Recursively flattens an object, converting nested properties into a single level object + * with keys representing the original nested structure. + * + * @param {Object} data The object to be flattened + * @param {String} [prefix=''] Optional prefix for nested keys + * @return {Object} Flattened object + */ function flattenObj(data, prefix = '') { let result = {}; try { diff --git a/modules/entry/back/methods/entry/getBuysCsv.js b/modules/entry/back/methods/entry/getBuysCsv.js index 647f41d22..a46f09c66 100644 --- a/modules/entry/back/methods/entry/getBuysCsv.js +++ b/modules/entry/back/methods/entry/getBuysCsv.js @@ -40,27 +40,3 @@ module.exports = Self => { return [toCSV(dataFlatted), 'text/csv', `inline; filename="buys-${id}.csv"`]; }; }; -// function flattenJSON(dataArray) { -// return dataArray.map(item => flatten(item.__data)); -// } -// function flatten(data, prefix = '') { -// let result = {}; -// try { -// for (let key in data) { -// if (!data[key]) continue; - -// const newKey = prefix ? `${prefix}_${key}` : key; -// const value = data[key]; - -// if (typeof value === 'object' && value !== null && !Array.isArray(value)) -// Object.assign(result, flatten(value.__data, newKey)); -// else -// result[newKey] = value; -// } -// } catch (error) { -// console.error(error); -// } - -// return result; -// } -