feat: refs #7905 getBuysCsv #2900

Merged
guillermo merged 10 commits from 7905-getBuysCsv into dev 2024-09-05 09:44:39 +00:00
4 changed files with 88 additions and 0 deletions

View File

@ -0,0 +1,2 @@
INSERT IGNORE INTO salix.ACL (model,property,principalId)
VALUES ('Entry','getBuysCsv','supplier');

43
loopback/util/flatten.js Normal file
View File

@ -0,0 +1,43 @@
/**
* 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 {
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,
};

View File

@ -0,0 +1,42 @@
const {toCSV} = require('vn-loopback/util/csv');
guillermo marked this conversation as resolved
Review

@jsegarra se quiere que los proveedores puedan tener sus buys. Ya lo hicimos via json, ahora lo quieren via csv, pero con este enfoque duplicamos codigo, hay forma de tenerlo unificado o por parametros ?

@jsegarra se quiere que los proveedores puedan tener sus buys. Ya lo hicimos via json, ahora lo quieren via csv, pero con este enfoque duplicamos codigo, hay forma de tenerlo unificado o por parametros ?
Review

Si, esto ya lo he visto pero tengo que buscar el commit
El ejemplo que tengo en la cabeza es cuando se planteo la necesidad de que printReport, según la cabecera generase un pdf o un html

Si, esto ya lo he visto pero tengo que buscar el commit El ejemplo que tengo en la cabeza es cuando se planteo la necesidad de que printReport, según la cabecera generase un pdf o un html
Review

Creo que la cabecera que buscamos es la de accept

Creo que la cabecera que buscamos es la de accept
Review

El commit
bb96125bbd

El commit https://gitea.verdnatura.es/verdnatura/salix/commit/bb96125bbda28164046ce7148aee6ccc934f9114
Review
https://gitea.verdnatura.es/verdnatura/salix/pulls/2900#issuecomment-61247
const {flatten} = require('vn-loopback/util/flatten');
module.exports = Self => {
Self.remoteMethodCtx('getBuysCsv', {
description: 'Returns buys for one entry in CSV file format',
accessType: 'READ',
accepts: [{
arg: 'id',
type: 'number',
required: true,
description: 'The entry id',
http: {source: 'path'}
}
],
returns: [
guillermo marked this conversation as resolved
Review

El problema que veo en mi propuesta es con respecto al return

El problema que veo en mi propuesta es con respecto al return
Review

Aunqaue puedes hacer que cuando tengas los datos o el stream, modificar ctx mediante
ctx.res.setHeader('Content-Type', 'text/csv'); ctx.res.setHeader('Content-Disposition', 'attachment; filename="discounted_price.csv"'); o ctx.res.setHeader('Content-Type', 'application/json');

Aunqaue puedes hacer que cuando tengas los datos o el stream, modificar ctx mediante `ctx.res.setHeader('Content-Type', 'text/csv'); ctx.res.setHeader('Content-Disposition', 'attachment; filename="discounted_price.csv"'); ` o ` ctx.res.setHeader('Content-Type', 'application/json');`
Review

Ya me he pegado de "ostias" para intentar tenerlo todo en un método, al final lo separé por el return como bien has dicho.

El segundo problema es que al retornar un JSON, claro el JSON puede tener objetos anidados, cosa que el CSV no, ya que es plano.

Por eso también obté por hacer la query directamente, ya que, a parte de lo mencionado, al utilizan loopback te crea objetos metadata en la variable que luego hay que eliminar y no se...

Ya me he pegado de "ostias" para intentar tenerlo todo en un método, al final lo separé por el return como bien has dicho. El segundo problema es que al retornar un JSON, claro el JSON puede tener objetos anidados, cosa que el CSV no, ya que es plano. Por eso también obté por hacer la query directamente, ya que, a parte de lo mencionado, al utilizan loopback te crea objetos metadata en la variable que luego hay que eliminar y no se...
Review

En ese caso eztraeria el core de la función getbuys a una función aparte y haría llamadas a esta nueva
Tipo lo que se hace en dms y docuware

En ese caso eztraeria el core de la función getbuys a una función aparte y haría llamadas a esta nueva Tipo lo que se hace en dms y docuware
Review

Ya te sigo, por lo que veo, cuando se usa toCSV no hay relaciones/includes
Sin embargo, modules/invoiceOut/back/methods/invoiceOut/negativeBasesCsv.js, obtiene datos y luego hace un map de los resultados
A lo mejor podriamos invertir tiempo para que dato un objeto(label:path), montar un csv

csv= {
   nombre: 'name',
   colorItem: 'item.color'
}
Ya te sigo, por lo que veo, cuando se usa toCSV no hay relaciones/includes Sin embargo, modules/invoiceOut/back/methods/invoiceOut/negativeBasesCsv.js, obtiene datos y luego hace un map de los resultados A lo mejor podriamos invertir tiempo para que dato un objeto(label:path), montar un csv ``` csv= { nombre: 'name', colorItem: 'item.color' } ```
Review

El tema de que el CSV no tenga objetos anidados No hay que darle una solución técnica sino hablar con el proveedor ya que implica que tenga que recuperar los datos de forma distinta

El tema de que el CSV no tenga objetos anidados No hay que darle una solución técnica sino hablar con el proveedor ya que implica que tenga que recuperar los datos de forma distinta
{
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.getBuysCsv = async(ctx, id, options) => {
const data = await Self.getBuys(ctx, id, null, options);
const dataFlatted = flatten(data);
return [toCSV(dataFlatted), 'text/csv', `inline; filename="buys-${id}.csv"`];
};
};

View File

@ -3,6 +3,7 @@ module.exports = Self => {
require('../methods/entry/filter')(Self); require('../methods/entry/filter')(Self);
require('../methods/entry/getEntry')(Self); require('../methods/entry/getEntry')(Self);
require('../methods/entry/getBuys')(Self); require('../methods/entry/getBuys')(Self);
require('../methods/entry/getBuysCsv')(Self);
require('../methods/entry/importBuys')(Self); require('../methods/entry/importBuys')(Self);
require('../methods/entry/importBuysPreview')(Self); require('../methods/entry/importBuysPreview')(Self);
require('../methods/entry/lastItemBuys')(Self); require('../methods/entry/lastItemBuys')(Self);