#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 -- 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 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);
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 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 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 -- Negativos
-- Item proposal -- Item proposal

View File

@ -1,8 +1,8 @@
DELIMITER $$ DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`item_getLack`( CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`item_getLack`(
vSelf INT,
vForce BOOLEAN, vForce BOOLEAN,
vDays INT, 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), vLongname VARCHAR(255),
vSupplierFk VARCHAR(255), vSupplierFk VARCHAR(255),
vColor VARCHAR(255), vColor VARCHAR(255),
@ -58,7 +58,7 @@ BEGIN
WHERE w.isForTicket WHERE w.isForTicket
AND ic.display AND ic.display
AND it.code != 'GEN' 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 (vLongname IS NULL OR i.name = vLongname)
AND (vSupplierFk IS NULL OR p.`name` LIKE CONCAT('%', vSupplierFk, '%')) 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) AND (vColor IS NULL OR vColor = i.inkFk)

View File

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

View File

@ -73,10 +73,12 @@ module.exports = Self => {
query: [sale.ticketFk] query: [sale.ticketFk]
}; };
const salesPerson = await Self.rawSql(salesPersonQuery.sql, salesPersonQuery.query, myOptions); const salesPerson = await Self.rawSql(salesPersonQuery.sql, salesPersonQuery.query, myOptions);
if (tx) await tx.commit();
const url = await models.Url.getUrl(); const url = await models.Url.getUrl();
const substitution = await models.Item.findById(substitutionFk, { const substitution = await models.Item.findById(substitutionFk, {
fields: ['id', 'name', 'longName'] fields: ['id', 'name', 'longName']
}, myOptions); }, myOptions);
const message = $t('negativeReplaced', { const message = $t('negativeReplaced', {
oldItemId: sale.itemFk, oldItemId: sale.itemFk,
oldItem: sale.item().longName, 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'} http: {source: 'query'}
}, },
{ {
arg: 'itemFk', arg: 'id',
type: 'number', type: 'number',
description: 'The item id', description: 'The item id',
}, },
@ -80,7 +80,7 @@ module.exports = Self => {
Object.assign(myOptions, options); Object.assign(myOptions, options);
const filterKeyOrder = [ const filterKeyOrder = [
'days', 'itemFk', 'longname', 'supplier', 'id', 'force', 'days', 'longname', 'supplier',
'colour', 'size', 'originFk', 'colour', 'size', 'originFk',
'lack', 'warehouseFk' 'lack', 'warehouseFk'
]; ];
@ -88,13 +88,17 @@ module.exports = Self => {
delete ctx?.args?.ctx; delete ctx?.args?.ctx;
delete ctx?.args?.filter; delete ctx?.args?.filter;
if (filter)
ctx.args = Object.assign(ctx.args ?? {}, filter);
let procedureParams = [true]; Object.assign(filter, ctx.args ?? {});
procedureParams.push(...filterKeyOrder.map(clave => ctx.args[clave] ?? null));
if (!procedureParams[1])procedureParams[1] = 2; let procedureParams = [];
procedureParams.push(...filterKeyOrder.map(clave => filter[clave] ?? null));
// 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(', '); const procedureArgs = Array(procedureParams.length).fill('?').join(', ');
let query = `CALL vn.item_getLack(${procedureArgs})`; let query = `CALL vn.item_getLack(${procedureArgs})`;

View File

@ -8,7 +8,7 @@ module.exports = Self => {
{ {
arg: 'itemFk', arg: 'itemFk',
type: 'number', type: 'number',
description: 'The item id', description: 'The item as negative status',
}, },
{ {
arg: 'filter', arg: 'filter',
@ -43,6 +43,7 @@ module.exports = Self => {
st.code, st.code,
t.id, t.id,
t.nickname, t.nickname,
c.id customerId,
t.shipped, t.shipped,
s.quantity, s.quantity,
ag.name, ag.name,
@ -52,7 +53,7 @@ module.exports = Self => {
s.id saleFk, s.id saleFk,
s.itemFk, s.itemFk,
s.price price, s.price price,
al.code AS alertLevelCode, al.code alertLevelCode,
z.name zoneName, z.name zoneName,
z.id zoneFk, z.id zoneFk,
Format(z.hour, "hh:mm") theoreticalhour, Format(z.hour, "hh:mm") theoreticalhour,
@ -60,7 +61,7 @@ module.exports = Self => {
IF(ISNULL(sc.saleClonedFk),0,1) turno, IF(ISNULL(sc.saleClonedFk),0,1) turno,
IF(ISNULL(tr.saleFk),0,1) peticionCompra, 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, 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, substitution.hasSubstitution,
IF(d.code = 'spainTeamVip', 1, 0) hasToIgnore IF(d.code = 'spainTeamVip', 1, 0) hasToIgnore
FROM sale s FROM sale s
@ -80,24 +81,24 @@ module.exports = Self => {
LEFT JOIN workerDepartment wd ON wd.workerFk = c.salesPersonFk LEFT JOIN workerDepartment wd ON wd.workerFk = c.salesPersonFk
LEFT JOIN department d ON d.id = wd.departmentFk LEFT JOIN department d ON d.id = wd.departmentFk
LEFT JOIN ( LEFT JOIN (
SELECT co.clientFk, IF(COUNT(*) > 0, FALSE, TRUE) AS hasSubstitution SELECT co.clientFk, IF(COUNT(*) > 0, FALSE, TRUE) hasSubstitution
FROM clientObservation co FROM clientObservation co
INNER JOIN observationType ot ON ot.id = co.observationTypeFk INNER JOIN observationType ot ON ot.id = co.observationTypeFk
WHERE ot.code = 'substitution' WHERE ot.code = 'substitution'
GROUP BY co.clientFk GROUP BY co.clientFk
) AS substitution ON substitution.clientFk = c.id ) substitution ON substitution.clientFk = c.id
WHERE warehouseFk = ? WHERE t.warehouseFk = ?
AND s.itemFk = ? AND s.itemFk = ?
AND s.quantity <> 0 AND s.quantity <> 0
AND t.shipped >= util.VN_CURDATE() AND t.shipped BETWEEN util.VN_CURDATE() AND DATE_ADD(util.VN_CURDATE(), INTERVAL ? DAY)
AND t.shipped < DATE_ADD(util.VN_CURDATE(), INTERVAL ? DAY)
AND sgd.saleFk IS NULL 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)
UNION ALL UNION ALL
SELECT r.id, SELECT r.id,
Review

AND s.quantity
para proximas

AND s.quantity para proximas
NULL, NULL,
r.orderFk, r.orderFk,
c.name, c.name customerName,
c.id customerId,
r.shipment, r.shipment,
r.amount, r.amount,
ag.name, ag.name,
@ -131,21 +132,15 @@ module.exports = Self => {
INNER JOIN observationType ot ON ot.id = co.observationTypeFk INNER JOIN observationType ot ON ot.id = co.observationTypeFk
WHERE ot.code = 'substitution' WHERE ot.code = 'substitution'
GROUP BY co.clientFk GROUP BY co.clientFk
) AS substitution ON substitution.clientFk = c.id ) substitution ON substitution.clientFk = c.id
WHERE r.shipment >= util.VN_CURDATE() WHERE r.shipment BETWEEN util.VN_CURDATE() AND DATE_ADD(util.VN_CURDATE(), INTERVAL ? DAY)
AND r.warehouseFk = ? AND r.warehouseFk = ?
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') AND r.created >= STR_TO_DATE(util.VN_CURDATE(), '%Y-%m-%d %H:%i:%s')
AND NOT o.confirmed AND NOT o.confirmed
AND r.itemFk = ? AND r.itemFk = ?
AND r.amount <> 0 AND r.amount <> 0
ORDER BY hasToIgnore, isBasket;`, ORDER BY hasToIgnore, isBasket;`,
[filter.where.warehouseFk, itemFk, 2, filter.where.warehouseFk, 2, itemFk]); [filter.where.warehouseFk, itemFk, 2, filter.where.stateFk ?? 0, 2, filter.where.warehouseFk, itemFk]);
if (filter.where.stateFk) {
stmt.merge({
sql: `AND ts.alertLevel=?`, params: [filter.where.stateFk]});
}
const sql = ParameterizedSQL.join([stmt], ';'); const sql = ParameterizedSQL.join([stmt], ';');
const result = await conn.executeStmt(sql, myOptions); 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', () => { 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() => { beforeEach(async() => {
ctx = { tx = await models.Ticket.beginTransaction({});
req: { options = {transaction: tx};
accessToken: {}, });
headers: {origin: 'http://localhost'},
} afterEach(async() => {
}; if (tx)
await tx.rollback();
}); });
it('should return data with NO filters', async() => { it('should return data with NO filters', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = {}; 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); expect(result.length).toEqual(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return data with filter.id', async() => { it('should return data with filter.id', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = { 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); expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return data with filter.longname', async() => { it('should return data with filter.longname', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = { const filter = {
longname: 'Ranged weapon pistol 9mm' 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); expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return data with filter.color', async() => { it('should return data with filter.color', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = { const filter = {
colour: 'WHT' 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); expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return data with filter.origen', async() => { it('should return data with filter.origen', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = { const filter = {
originFk: 1 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); expect(result.length).toEqual(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return data with filter.size', async() => { it('should return data with filter.size', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = { const filter = {
size: '15' 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); expect(result.length).toEqual(1);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it('should return data with filter.lack', async() => { it('should return data with filter.lack', async() => {
const tx = await models.Ticket.beginTransaction({});
const options = {transaction: tx};
const filter = { const filter = {
lack: '-15' lack: '-15'
}; };
try {
const result = await models.Ticket.itemLack(ctx, filter, options);
expect(result.length).toEqual(1); const result = await models.Ticket.itemLack(ctx, filter, options);
await tx.rollback();
} catch (e) { expect(result.length).toEqual(1);
await tx.rollback();
throw e;
}
}); });
}); });

View File

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

View File

@ -38,52 +38,37 @@ module.exports = Self => {
tx = await Self.beginTransaction({}); tx = await Self.beginTransaction({});
myOptions.transaction = tx; myOptions.transaction = tx;
} }
try { try {
const ticketsCount = await Self.rawSql(` const count = await models.Sale.count({
Select t.id tid, s.id sid, count(s.id) count ticketFk
FROM }, myOptions);
vn.ticket t if (count === 1)
LEFT JOIN vn.sale s return {ticket: ticketFk, status: 'noSplit'};
ON s.ticketFk = t.id // continue;
WHERE t.id =? GROUP BY t.id;`,
[ticketFk], myOptions);
for (const {tid, count} of ticketsCount) { const [, [{vNewTicket}]] = await Self.rawSql(`
try {
if (count === 1) {
result.push({ticket: tid, status: 'noSplit'});
continue;
}
const [, [{vNewTicket}]] = await Self.rawSql(`
CALL vn.ticket_clone(?, @vNewTicket); CALL vn.ticket_clone(?, @vNewTicket);
SELECT @vNewTicket vNewTicket;`, SELECT @vNewTicket vNewTicket;`,
[tid], myOptions); [ticketFk], myOptions);
if (vNewTicket === 0) continue; if (vNewTicket === 0) return result;
const sales = await models.Sale.find({ const sales = await models.Sale.find({
where: {id: {inq: ticket.sales}} where: {id: {inq: ticket.sales}}
}, myOptions); }, myOptions);
const updateIsPicked = sales.map(({sid}) => Self.rawSql(` const updateIsPicked = sales.map(({sid}) => Self.rawSql(`
UPDATE vn.sale SET isPicked = (id = ?) WHERE ticketFk = ?`, UPDATE vn.sale SET isPicked = (id = ?) WHERE ticketFk = ?`,
[sid, tid], myOptions)); [sid, ticketFk], myOptions));
await Promise.all(updateIsPicked); await Promise.all(updateIsPicked);
await Self.transferSales(ctx, tid, vNewTicket, sales, myOptions); await Self.transferSales(ctx, ticketFk, vNewTicket, sales, myOptions);
await Self.rawSql(`CALL vn.ticket_setState(?, ?)`, [tid, 'FIXING'], myOptions); await Self.rawSql(`CALL vn.ticket_setState(?, ?)`, [ticketFk, 'FIXING'], myOptions);
result.push({ticket: tid, newTicket: vNewTicket, status: 'split'}); if (tx) await tx.commit();
if (tx) await tx.commit(); return {ticket: ticketFk, newTicket: vNewTicket, status: 'split'};
} catch ({message}) {
result.push({ticket: tid, status: 'error', message});
}
}
return result;
} catch (e) { } catch (e) {
if (tx) await tx.rollback(); if (tx) await tx.rollback();
throw e; return {ticket: ticketFk, status: 'error', message: e.message};
} }
}; };
}; };