#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);
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),
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));
// 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',
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,
al.code AS alertLevelCode,
al.code alertLevelCode,
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,
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
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
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
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)
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 = ?
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 NOT o.confirmed
AND r.itemFk = ?
AND r.itemFk = ?
AND r.amount <> 0
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]);
const sql = ParameterizedSQL.join([stmt], ';');
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({});
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);
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);
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};
}
};
};