#6321 - Negative tickets #1945

Merged
jsegarra merged 146 commits from 6321_negative_tickets into dev 2025-02-11 08:45:33 +00:00
10 changed files with 179 additions and 238 deletions
Showing only changes of commit 550b0871f0 - Show all commits

View File

@ -4073,17 +4073,17 @@ UPDATE vn.worker
-- Negativos
INSERT INTO `vn`.`item` (id,name,`size`,stems,minPrice,isToPrint,family,box,originFk,doPhoto,image,inkFk,intrastatFk,hasMinPrice,created,typeFk,generic,density,relevancy,expenseFk,isActive,longName,subName,tag5,value5,tag6,value6,tag7,value7,minimum,upToDown,hasKgPrice,isFloramondo,isFragile,stemMultiplier,isLaid,lastUsed,editorFk,isBoxPickingMode)
INSERT INTO `vn`.`item` (id, name, `size`, stems, minPrice, isToPrint, family, box, originFk, doPhoto, image, inkFk, intrastatFk, hasMinPrice, created, typeFk, generic, density, relevancy, expenseFk, isActive, longName, subName, tag5, value5, tag6, value6, tag7, value7, minimum, upToDown, hasKgPrice, isFloramondo, isFragile, stemMultiplier, isLaid, lastUsed, editorFk, isBoxPickingMode)
VALUES
(88,'Lack negative',200,1,10.0,0,'VT',0,2,0,'','WHT',6021010,1,'2024-07-19 11:27:32.000',1,0,167,0,'4751000000',1,'Lack negative origin','Stark Industries','Color','White','Categoria','supply','Tallos','1',3,0,0,0,0,1.0,0,'2024-07-19 11:27:32.000',100,0);
(88, 'Lack negative', 200, 1, 10.0, 0, 'VT', 0, 2, 0, '', 'WHT', 6021010, 1, util.VN_CURDATE(), 1, 0, 167, 0, '4751000000', 1, 'Lack negative origin', 'Stark Industries', 'Color', 'White', 'Categoria', 'supply', 'Tallos', '1', 3, 0, 0, 0, 0, 1.0, 0, util.VN_CURDATE(), 100, 0);
jsegarra marked this conversation as resolved Outdated

deja un espacio despues de cada coma igual que el resto del archivo
No puedes hacer el insert de este item junto con los otros?

Año 2024 no

deja un espacio despues de cada coma igual que el resto del archivo No puedes hacer el insert de este item junto con los otros? Año 2024 no

Con esto lo he cambiado rapdiamente ,(?!\s)

Con esto lo he cambiado rapdiamente `,(?!\s) `
INSERT INTO `vn`.`ticket` (id, clientFk,warehouseFk,shipped,nickname,refFk,addressFk,workerFk,observations,isSigned,isLabeled,isPrinted,packages,location,`hour`,created,isBlocked,solution,routeFk,priority,hasPriority,companyFk,agencyModeFk,landed,isBoxed,isDeleted,zoneFk,zonePrice,zoneBonus,totalWithVat,totalWithoutVat,weight,clonedFrom,cmrFk,editorFk,problem,risk)
INSERT INTO `vn`.`ticket` (id, clientFk, warehouseFk, shipped, nickname, refFk, addressFk, workerFk, observations, isSigned, isLabeled, isPrinted, packages, location, `hour`, created, isBlocked, solution, routeFk, priority, hasPriority, companyFk, agencyModeFk, landed, isBoxed, isDeleted, zoneFk, zonePrice, zoneBonus, totalWithVat, totalWithoutVat, weight, clonedFrom, cmrFk, editorFk, problem, risk)
VALUES
(1000000, 1,1,'2001-01-01 00:00:00.000','employee',NULL,131,NULL,NULL,0,0,0,0,NULL,0,'2024-07-19 23:32:48.000',1,NULL,NULL,NULL,1,442,1,'2001-01-01',0,0,1,1.00,0.00,0.00,NULL,NULL,NULL,NULL,9,'',NULL);
(1000000, 1, 1, util.VN_CURDATE(), 'employee', NULL, 131, NULL, NULL, 0, 0, 0, 0, NULL, 0, CURDATE(), 1, NULL, NULL, NULL, 1, 442, 1, util.VN_CURDATE(), 0, 0, 1, 1.00, 0.00, 0.00, NULL, NULL, NULL, NULL, 9, '', NULL);
INSERT INTO `vn`.`sale` (id, itemFk,ticketFk,concept,quantity,originalQuantity,price,discount,priceFixed,reserved,isPicked,isPriceFixed,created,isAdded,total,editorFk,problem)
INSERT INTO `vn`.`sale` (id, itemFk, ticketFk, concept, quantity, originalQuantity, price, discount, priceFixed, reserved, isPicked, isPriceFixed, created, isAdded, total, editorFk, problem)
VALUES
(43, 88,1000000,'Chest medical box 2',15.00,155.0,10.00,0,0.00,0,0,0,'2024-07-19 23:33:08.000',0,1550.00,100,'');
(43, 88, 1000000, 'Chest medical box 2', 15.00, 155.0, 10.00, 0, 0.00, 0, 0, 0, CURDATE(), 0, 1550.00, 100, '');
-- Negativos
-- Item proposal

View File

@ -1,8 +1,8 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`item_getLack`(
vSelf INT,
vForce BOOLEAN,
vDays INT,
jsegarra marked this conversation as resolved
Review

si esto es el id del artículo, lo ponemos en primer lugar y se llama vSelf

si esto es el id del artículo, lo ponemos en primer lugar y se llama vSelf
vId INT,
vLongname VARCHAR(255),
vSupplierFk VARCHAR(255),
jgallego marked this conversation as resolved Outdated

si es varchar no es un Fk, mirando el codigo deduzco que producerName

si es varchar no es un Fk, mirando el codigo deduzco que producerName

cambiado

cambiado
vColor VARCHAR(255),
@ -58,7 +58,7 @@ BEGIN
WHERE w.isForTicket
AND ic.display
AND it.code != 'GEN'
AND (vId IS NULL OR i.id = vId)
AND (vSelf IS NULL OR i.id = vSelf)
AND (vLongname IS NULL OR i.name = vLongname)
AND (vSupplierFk IS NULL OR p.`name` LIKE CONCAT('%', vSupplierFk, '%'))
Review

estas seguro que quieren esto? si hay un productor que se llama flor, saldran tambien todos los floral, floristeria... yo creo que conviene dejar el =

estas seguro que quieren esto? si hay un productor que se llama flor, saldran tambien todos los floral, floristeria... yo creo que conviene dejar el =
AND (vColor IS NULL OR vColor = i.inkFk)

View File

@ -25,9 +25,11 @@ BEGIN
DECLARE vNewSaleFk INT;
DECLARE vFinalPrice DECIMAL(10,2);
DECLARE vIsRequiredTx BOOL DEFAULT NOT @@in_transaction;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
CALL util.tx_rollback(vIsRequiredTx);
RESIGNAL;
END;
@ -62,7 +64,7 @@ BEGIN
WHERE tmp.itemFk = vNewItemFk AND tmp.WarehouseFk = vWarehouseFk;
DROP TEMPORARY TABLE tmp.buyUltimate;
IF vGroupingMode = 'packing' AND vPacking > 0 THEN
SET vRoundQuantity = vPacking;
END IF;
@ -129,6 +131,6 @@ BEGIN
VALUES(vItemFk, vNewItemFk, 1)
ON DUPLICATE KEY UPDATE counter = counter + 1;
COMMIT;
CALL util.tx_commit(vIsRequiredTx);
END$$
DELIMITER ;

View File

@ -73,10 +73,12 @@ module.exports = Self => {
query: [sale.ticketFk]
};
const salesPerson = await Self.rawSql(salesPersonQuery.sql, salesPersonQuery.query, myOptions);
if (tx) await tx.commit();
const url = await models.Url.getUrl();
const substitution = await models.Item.findById(substitutionFk, {
fields: ['id', 'name', 'longName']
}, myOptions);
const message = $t('negativeReplaced', {
oldItemId: sale.itemFk,
oldItem: sale.item().longName,

View File

@ -0,0 +1,61 @@
const {models} = require('vn-loopback/server/server');
describe('Sale - replaceItem function', () => {
let options;
let tx;
const ctx = beforeAll.getCtx();
beforeAll.mockLoopBackContext();
beforeEach(async() => {
tx = await models.Sale.beginTransaction({});
options = {transaction: tx};
});
afterEach(async() => {
if (tx)
await tx.rollback();
});
it('should replace full item in sale and send notification', async() => {
const saleFk = 43;
const substitutionFk = 3;
const quantity = 15;
const ticketFk = 1000000;
const salesBefore = await models.Sale.find({where: {ticketFk}}, options);
const salesLength = salesBefore.length;
expect(1).toEqual(salesBefore.length);
await models.Sale.replaceItem(ctx, saleFk, substitutionFk, quantity, options);
const salesAfter = await models.Sale.find({where: {ticketFk}}, options);
expect(salesLength).toBeLessThan(salesAfter.length);
expect(salesAfter[0].id).toEqual(saleFk);
expect(salesAfter[salesLength].itemFk).toEqual(substitutionFk);
expect(salesAfter[salesLength].quantity).toEqual(quantity);
expect(salesAfter[0].quantity).toEqual(0);
expect(salesAfter[salesLength].concept).toMatch(/^\+/);
});
it('should replace half item in sale and send notification', async() => {
const saleFk = 43;
const substitutionFk = 3;
const quantity = 10;
const ticketFk = 1000000;
const salesBefore = await models.Sale.find({where: {ticketFk}}, options);
const salesLength = salesBefore.length;
expect(1).toEqual(salesBefore.length);
await models.Sale.replaceItem(ctx, saleFk, substitutionFk, quantity, options);
const salesAfter = await models.Sale.find({where: {ticketFk}}, options);
expect(salesLength).toBeLessThan(salesAfter.length);
expect(salesAfter[0].id).toEqual(saleFk);
expect(salesAfter[salesLength].itemFk).toEqual(substitutionFk);
expect(salesAfter[salesLength].quantity).toEqual(quantity);
expect(salesAfter[0].quantity).toEqual(5);
expect(salesAfter[salesLength].concept).toMatch(/^\+/);
});
});

View File

@ -15,7 +15,7 @@ module.exports = Self => {
http: {source: 'query'}
},
{
arg: 'itemFk',
arg: 'id',
type: 'number',
description: 'The item id',
},
@ -80,7 +80,7 @@ module.exports = Self => {
Object.assign(myOptions, options);
const filterKeyOrder = [
'days', 'itemFk', 'longname', 'supplier',
'id', 'force', 'days', 'longname', 'supplier',
'colour', 'size', 'originFk',
'lack', 'warehouseFk'
];
@ -88,13 +88,17 @@ module.exports = Self => {
delete ctx?.args?.ctx;
delete ctx?.args?.filter;
if (filter)
ctx.args = Object.assign(ctx.args ?? {}, filter);
let procedureParams = [true];
procedureParams.push(...filterKeyOrder.map(clave => ctx.args[clave] ?? null));
Object.assign(filter, ctx.args ?? {});
if (!procedureParams[1])procedureParams[1] = 2;
let procedureParams = [];
procedureParams.push(...filterKeyOrder.map(clave => filter[clave] ?? null));
jsegarra marked this conversation as resolved Outdated

si se va a migrar el proc tal cual confirmar con Juan pero yo no lo moveria que se llame a item_getLack de la BBDD directamente

si se va a migrar el proc tal cual confirmar con Juan pero yo no lo moveria que se llame a item_getLack de la BBDD directamente

Lo anoto para hablar con el

Lo anoto para hablar con el

La idea de hacer este movimiento, es poder aplicar filtros a la consulta. Esto justo se esta haciendo en "Monitor de ventas". Hay mucho código SQL definido en el método para poder aplicar los filtros que vienen por parámetros

La idea de hacer este movimiento, es poder aplicar filtros a la consulta. Esto justo se esta haciendo en "Monitor de ventas". Hay mucho código SQL definido en el método para poder aplicar los filtros que vienen por parámetros

Tras hablar con Juan, consideramos mejor enfoque modificar el procedimiento añadiendo tantos argumentos como filtros tengamos

Tras hablar con Juan, consideramos mejor enfoque modificar el procedimiento añadiendo tantos argumentos como filtros tengamos
// Default values
const forceIndex = filterKeyOrder.indexOf('force');
if (!procedureParams[forceIndex])procedureParams[forceIndex] = true;
const daysIndex = filterKeyOrder.indexOf('days');
if (!procedureParams[daysIndex])procedureParams[daysIndex] = 2;
const procedureArgs = Array(procedureParams.length).fill('?').join(', ');
let query = `CALL vn.item_getLack(${procedureArgs})`;

View File

@ -8,7 +8,7 @@ module.exports = Self => {
{
arg: 'itemFk',
jsegarra marked this conversation as resolved Outdated

si estamos en la seccion ticket, yo el argumento lo llamaria itemFk, porque a mitad codigo, id puede dar confusion a que es el id de la entidad, en este caso ticket

si estamos en la seccion ticket, yo el argumento lo llamaria itemFk, porque a mitad codigo, id puede dar confusion a que es el id de la entidad, en este caso ticket
type: 'number',
description: 'The item id',
description: 'The item as negative status',
},
{
arg: 'filter',
@ -43,6 +43,7 @@ module.exports = Self => {
st.code,
t.id,
t.nickname,
c.id customerId,
t.shipped,
s.quantity,
ag.name,
@ -52,7 +53,7 @@ module.exports = Self => {
s.id saleFk,
s.itemFk,
s.price price,
jsegarra marked this conversation as resolved Outdated

es una chorrada pero comovas a cambiar cosas, no solemos poner los AS en los select

es una chorrada pero comovas a cambiar cosas, no solemos poner los AS en los select
al.code AS alertLevelCode,
al.code alertLevelCode,
jsegarra marked this conversation as resolved Outdated

tls.alertLevel

tls.alertLevel
z.name zoneName,
z.id zoneFk,
Format(z.hour, "hh:mm") theoreticalhour,
@ -60,7 +61,7 @@ module.exports = Self => {
IF(ISNULL(sc.saleClonedFk),0,1) turno,
jgallego marked this conversation as resolved Outdated

aqui puedes devolver el codigo y en front gestionas como necesites, sino estas haciendo 2 funciones por cada linea..lo cual tiene un coste en velocidad al select

aqui puedes devolver el codigo y en front gestionas como necesites, sino estas haciendo 2 funciones por cada linea..lo cual tiene un coste en velocidad al select

cual select? al de zona? El siguiente es de hora y a continuación son booleanos

cual select? al de zona? El siguiente es de hora y a continuación son booleanos

cambiado

cambiado
IF(ISNULL(tr.saleFk),0,1) peticionCompra,
DATE_FORMAT(IF(HOUR(t.shipped), t.shipped, IF(zc.hour, zc.hour, z.hour)),'%H:%i') minTimed,
FALSE AS isBasket,
FALSE isBasket,
substitution.hasSubstitution,
IF(d.code = 'spainTeamVip', 1, 0) hasToIgnore
jgallego marked this conversation as resolved Outdated

esto lo confirmamos con ellos, yo intentaria llevarlo a front sin este campo hasToIgnore y que se lo filtren, de lo contrario..mañana cuando cambien codigos esto habra que cambiarlo

esto lo confirmamos con ellos, yo intentaria llevarlo a front sin este campo hasToIgnore y que se lo filtren, de lo contrario..mañana cuando cambien codigos esto habra que cambiarlo

La consulta que estas viendo está copiada y traducida desde access
Solo la he migrado.
Este campo sirve para ordenar los resultados

La consulta que estas viendo está copiada y traducida desde access Solo la he migrado. Este campo sirve para ordenar los resultados

cambiado

cambiado
FROM sale s
@ -80,24 +81,24 @@ module.exports = Self => {
LEFT JOIN workerDepartment wd ON wd.workerFk = c.salesPersonFk
LEFT JOIN department d ON d.id = wd.departmentFk
LEFT JOIN (
SELECT co.clientFk, IF(COUNT(*) > 0, FALSE, TRUE) AS hasSubstitution
SELECT co.clientFk, IF(COUNT(*) > 0, FALSE, TRUE) hasSubstitution
jgallego marked this conversation as resolved Outdated

esto seria hasObservation

esto seria hasObservation

Okey, reemplazaré

Okey, reemplazaré

cambiado

cambiado
FROM clientObservation co
INNER JOIN observationType ot ON ot.id = co.observationTypeFk
WHERE ot.code = 'substitution'
GROUP BY co.clientFk
) AS substitution ON substitution.clientFk = c.id
WHERE warehouseFk = ?
AND s.itemFk = ?
AND s.quantity <> 0
AND t.shipped >= util.VN_CURDATE()
AND t.shipped < DATE_ADD(util.VN_CURDATE(), INTERVAL ? DAY)
) substitution ON substitution.clientFk = c.id
jgallego marked this conversation as resolved Outdated

aqui falta el alias de la tabla, probablemente t.warehouse

aqui falta el alias de la tabla, probablemente t.warehouse

, COUNT(*) hasObservation

Hemos invertido este booleano, ahora hay que mostrar el icono si aqui hay valor

, COUNT(*) hasObservation Hemos invertido este booleano, ahora hay que mostrar el icono si aqui hay valor
WHERE t.warehouseFk = ?
AND s.itemFk = ?
AND s.quantity <> 0
AND t.shipped BETWEEN util.VN_CURDATE() AND DATE_ADD(util.VN_CURDATE(), INTERVAL ? DAY)
AND sgd.saleFk IS NULL
AND (al.code IN ('FREE', 'ON_PREVIOUS') OR al.code IS NULL)
AND (al.id = ? OR al.id IS NULL)
jgallego marked this conversation as resolved Outdated

Valores como estos lo dejamos así o lo movemos a variables/consultas?

Valores como estos lo dejamos así o lo movemos a variables/consultas?

si es alertLevel hay que usar el codigo, no el numero, en este caso 'ON_PREPARATION' o 'DELIVERED'

si es alertLevel hay que usar el codigo, no el numero, en este caso 'ON_PREPARATION' o 'DELIVERED'

Okey, hago la modificación aqui y en el front para que se pueda enviar array desde el VnSelect

Okey, hago la modificación aqui y en el front para que se pueda enviar array desde el VnSelect

Resuelto

Resuelto

Y he creado un registro en TicketConfig con valor default a FREE (por si cambian de criterio a futuro)

Y he creado un registro en TicketConfig con valor default a FREE (por si cambian de criterio a futuro)
UNION ALL
SELECT r.id,
Review

AND s.quantity
para proximas

AND s.quantity para proximas
NULL,
r.orderFk,
c.name,
c.name customerName,
c.id customerId,
r.shipment,
r.amount,
ag.name,
@ -131,21 +132,15 @@ module.exports = Self => {
INNER JOIN observationType ot ON ot.id = co.observationTypeFk
WHERE ot.code = 'substitution'
GROUP BY co.clientFk
) AS substitution ON substitution.clientFk = c.id
WHERE r.shipment >= util.VN_CURDATE()
) substitution ON substitution.clientFk = c.id
WHERE r.shipment BETWEEN util.VN_CURDATE() AND DATE_ADD(util.VN_CURDATE(), INTERVAL ? DAY)
AND r.warehouseFk = ?
jsegarra marked this conversation as resolved Outdated

cambiar este tb

cambiar este tb
AND r.shipment < DATE_ADD(util.VN_CURDATE(), INTERVAL ? DAY)
AND r.created >= STR_TO_DATE(util.VN_CURDATE(), '%Y-%m-%d %H:%i:%s')
jgallego marked this conversation as resolved Outdated

igual que arriba, comparar esto es lentitud en el select, ahi puedes poner (util) curdate o now lo que tenga que ser

igual que arriba, comparar esto es lentitud en el select, ahi puedes poner (util) curdate o now lo que tenga que ser

cambiado

cambiado
AND NOT o.confirmed
AND r.itemFk = ?
AND r.itemFk = ?
AND r.amount <> 0
jgallego marked this conversation as resolved Outdated

asumiendo que el amount es unsigned, deja AND r.amount

asumiendo que el amount es unsigned, deja AND r.amount

cambiado

cambiado
ORDER BY hasToIgnore, isBasket;`,
[filter.where.warehouseFk, itemFk, 2, filter.where.warehouseFk, 2, itemFk]);
if (filter.where.stateFk) {
stmt.merge({
sql: `AND ts.alertLevel=?`, params: [filter.where.stateFk]});
}
[filter.where.warehouseFk, itemFk, 2, filter.where.stateFk ?? 0, 2, filter.where.warehouseFk, itemFk]);
jgallego marked this conversation as resolved Outdated

aqui lo dicho, sin numero los ids de los estados van a cambiar en breve

aqui lo dicho, sin numero los ids de los estados van a cambiar en breve

Ahora se usa el código

Ahora se usa el código
const sql = ParameterizedSQL.join([stmt], ';');
jsegarra marked this conversation as resolved Outdated

verias mejor mover el select a un procedimiento? y nos evitamos esta condición?
@jgallego

verias mejor mover el select a un procedimiento? y nos evitamos esta condición? @jgallego

no, con la funcion nativa de loopback va bien

no, con la funcion nativa de loopback va bien

Ok

Ok
const result = await conn.executeStmt(sql, myOptions);

View File

@ -1,136 +1,80 @@
const models = require('vn-loopback/server/server').models;
const {models} = require('vn-loopback/server/server');
describe('Item Lack', () => {
jsegarra marked this conversation as resolved
Review

modules/ticket/back/methods/ticket/specs/closure.spec.js dile a chatgpt que coja este arhcivo como plantilla y cambie el tuyo para dejar los beginTransaction y los rollback en un beforeEach y afterEach

modules/ticket/back/methods/ticket/specs/closure.spec.js dile a chatgpt que coja este arhcivo como plantilla y cambie el tuyo para dejar los beginTransaction y los rollback en un beforeEach y afterEach
let options;
let tx;
const ctx = beforeAll.getCtx();
beforeAll.mockLoopBackContext();
beforeEach(async() => {
ctx = {
req: {
accessToken: {},
headers: {origin: 'http://localhost'},
}
};
tx = await models.Ticket.beginTransaction({});
options = {transaction: tx};
});
afterEach(async() => {
if (tx)
await tx.rollback();
});
it('should return data with NO filters', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = {};
try {
const result = await models.Ticket.itemLack(ctx, filter, options);
const result = await models.Ticket.itemLack(ctx, filter, options);
expect(result.length).toEqual(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result.length).toEqual(2);
});
it('should return data with filter.id', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = {
itemFk: 88
id: 5
};
try {
const result = await models.Ticket.itemLack(ctx, filter, options);
const result = await models.Ticket.itemLack(ctx, filter, options);
expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result.length).toEqual(1);
});
it('should return data with filter.longname', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = {
longname: 'Ranged weapon pistol 9mm'
};
try {
const result = await models.Ticket.itemLack(ctx, filter, options);
const result = await models.Ticket.itemLack(ctx, filter, options);
expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result.length).toEqual(1);
});
it('should return data with filter.color', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = {
colour: 'WHT'
};
try {
const result = await models.Ticket.itemLack(ctx, filter, options);
const result = await models.Ticket.itemLack(ctx, filter, options);
expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result.length).toEqual(1);
});
it('should return data with filter.origen', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = {
originFk: 1
};
try {
const result = await models.Ticket.itemLack(ctx, filter, options);
const result = await models.Ticket.itemLack(ctx, filter, options);
expect(result.length).toEqual(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result.length).toEqual(2);
});
it('should return data with filter.size', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = {
size: '15'
};
try {
const result = await models.Ticket.itemLack(ctx, filter, options);
const result = await models.Ticket.itemLack(ctx, filter, options);
expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(result.length).toEqual(1);
});
it('should return data with filter.lack', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = {
lack: '-15'
};
try {
const result = await models.Ticket.itemLack(ctx, filter, options);
expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
const result = await models.Ticket.itemLack(ctx, filter, options);
expect(result.length).toEqual(1);
});
});

View File

@ -1,99 +1,47 @@
const models = require('vn-loopback/server/server').models;
const {models} = require('vn-loopback/server/server');
describe('Split', () => {
beforeAll(async() => {
ctx = {
req: {
accessToken: {userId: 9},
headers: {origin: 'http://localhost'},
__: () => {}
}
};
let options;
let tx;
const ctx = beforeAll.getCtx();
beforeAll.mockLoopBackContext();
beforeEach(async() => {
tx = await models.Ticket.beginTransaction({});
options = {transaction: tx};
});
afterEach(async() => {
if (tx)
await tx.rollback();
});
it('should split tickets with count 1', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const data =
{ticketFk: 7, sales: [1]}
;
try {
const result = await models.Ticket.split(ctx, data, options);
{ticketFk: 7, sales: [1]};
const result = await models.Ticket.split(ctx, data, options);
expect(1).toEqual(result.length);
expect(data.ticketFk).toEqual(result[0].ticket);
expect('noSplit').toEqual(result[0].status);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(data.ticketFk).toEqual(result.ticket);
expect('noSplit').toEqual(result.status);
});
it('should split tickets with count 2 and error', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const data =
{ticketFk: 11, sales: [7]}
;
try {
const result = await models.Ticket.split(ctx, data, options);
const result = await models.Ticket.split(ctx, data, options);
expect(1).toEqual(result.length);
expect(data.ticketFk).toEqual(result[0].ticket);
expect('error').toEqual(result[0].status);
expect('Can\'t transfer claimed sales').toEqual(result[0].message);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
xit('should split tickets with count 2 and other error', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const data =
{ticketFk: 16, sales: [1, 2]}
;
try {
const result = await models.Ticket.split(ctx, data, options);
expect(1).toEqual(result.length);
expect(data.ticketFk).toEqual(result[0].ticket);
expect('error').toEqual(result[0].status);
expect('Can\'t transfer claimed sales').toEqual(result[0].message);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(data.ticketFk).toEqual(result.ticket);
expect('error').toEqual(result.status);
expect('Can\'t transfer claimed sales').toEqual(result.message);
});
it('should split tickets with count 2 and success', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const data =
{ticketFk: 14, sales: [33]}
;
try {
const result = await models.Ticket.split(ctx, data, options);
{ticketFk: 14, sales: [33]};
const result = await models.Ticket.split(ctx, data, options);
expect(1).toEqual(result.length);
expect(data.ticketFk).toEqual(result[0].ticket);
expect('split').toEqual(result[0].status);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
expect(data.ticketFk).toEqual(result.ticket);
expect('split').toEqual(result.status);
});
});

View File

@ -38,52 +38,37 @@ module.exports = Self => {
tx = await Self.beginTransaction({});

si el objetivo es contar tickets te sobraria la tabla sale,
si el objetivo es contar sales te sobraria la tabla ticket

si el objetivo es contar tickets te sobraria la tabla sale, si el objetivo es contar sales te sobraria la tabla ticket

resuelto

resuelto
myOptions.transaction = tx;
}
try {
const ticketsCount = await Self.rawSql(`
Select t.id tid, s.id sid, count(s.id) count
FROM
vn.ticket t
LEFT JOIN vn.sale s
ON s.ticketFk = t.id
WHERE t.id =? GROUP BY t.id;`,
[ticketFk], myOptions);
const count = await models.Sale.count({
ticketFk
}, myOptions);
jsegarra marked this conversation as resolved Outdated

cambia esto por el /Sales/count asi usamos el nativo

cambia esto por el /Sales/count asi usamos el nativo

Okey, lo tomo de ticket/isEmpty

Okey, lo tomo de ticket/isEmpty
if (count === 1)
return {ticket: ticketFk, status: 'noSplit'};
// continue;
for (const {tid, count} of ticketsCount) {
try {
if (count === 1) {
result.push({ticket: tid, status: 'noSplit'});
continue;
}
const [, [{vNewTicket}]] = await Self.rawSql(`
const [, [{vNewTicket}]] = await Self.rawSql(`
CALL vn.ticket_clone(?, @vNewTicket);
SELECT @vNewTicket vNewTicket;`,
[tid], myOptions);
[ticketFk], myOptions);
if (vNewTicket === 0) continue;
const sales = await models.Sale.find({
where: {id: {inq: ticket.sales}}
}, myOptions);
if (vNewTicket === 0) return result;
const sales = await models.Sale.find({
where: {id: {inq: ticket.sales}}
}, myOptions);

en que caso devuelve un ticket = 0?

en que caso devuelve un ticket = 0?

Diría que en ningún caso. Pero esta condición estaba en access y la puse

Diría que en ningún caso. Pero esta condición estaba en access y la puse

cambiado

cambiado
const updateIsPicked = sales.map(({sid}) => Self.rawSql(`
const updateIsPicked = sales.map(({sid}) => Self.rawSql(`
UPDATE vn.sale SET isPicked = (id = ?) WHERE ticketFk = ?`,
[sid, tid], myOptions));
[sid, ticketFk], myOptions));
await Promise.all(updateIsPicked);
await Self.transferSales(ctx, tid, vNewTicket, sales, myOptions);
await Promise.all(updateIsPicked);
await Self.transferSales(ctx, ticketFk, vNewTicket, sales, myOptions);
await Self.rawSql(`CALL vn.ticket_setState(?, ?)`, [tid, 'FIXING'], myOptions);
result.push({ticket: tid, newTicket: vNewTicket, status: 'split'});
if (tx) await tx.commit();
} catch ({message}) {
result.push({ticket: tid, status: 'error', message});
}
}
return result;
await Self.rawSql(`CALL vn.ticket_setState(?, ?)`, [ticketFk, 'FIXING'], myOptions);
if (tx) await tx.commit();
return {ticket: ticketFk, newTicket: vNewTicket, status: 'split'};
} catch (e) {
if (tx) await tx.rollback();
throw e;
return {ticket: ticketFk, status: 'error', message: e.message};
}
};
};