#6321 - Negative tickets #1945
|
@ -111,7 +111,7 @@ async function test() {
|
|||
const JunitReporter = require('jasmine-reporters');
|
||||
runner.addReporter(new JunitReporter.JUnitXmlReporter());
|
||||
}
|
||||
if (opts.ci)
|
||||
if (opts.ci || opts.debug)
|
||||
|
||||
runner.jasmine.DEFAULT_TIMEOUT_INTERVAL = SPEC_TIMEOUT;
|
||||
|
||||
runner.loadConfig(config);
|
||||
|
|
|
@ -996,7 +996,8 @@ VALUES
|
|||
(14, 5, 1, 2, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'VT', 1, NULL, NULL, 0, NULL, 0),
|
||||
(15, 4, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'EMB', 0, NULL, NULL, 0, NULL, 0),
|
||||
(16, 6, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'EMB', 0, NULL, NULL, 0, NULL, 0),
|
||||
(71, 6, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0);
|
||||
(71, 6, NULL, 1, NULL, NULL, 06021010, 4751000000, NULL, 0, '', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0),
|
||||
(88, 1, NULL, 1, 'Lack negative origin', 1, 06021010, 4751000000, NULL, 0, '1', NULL, 0, 'VT', 0, NULL, NULL, 0, NULL, 0);
|
||||
|
||||
|
||||
-- Update the taxClass after insert of the items
|
||||
|
@ -4056,3 +4057,12 @@ INSERT IGNORE INTO vn.osrmConfig (id,url,tolerance)
|
|||
INSERT IGNORE INTO vn.inventoryConfig
|
||||
SET id = 1,
|
||||
supplierFk = 4;
|
||||
-- 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);
|
||||
|
||||
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);
|
||||
|
||||
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,'');
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
DELIMITER $$
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`item_getLack`(IN vForce BOOLEAN, IN vDays INT)
|
||||
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`item_getLack`(
|
||||
vForce BOOLEAN,
|
||||
vDays INT,
|
||||
vId INT,
|
||||
vLongname VARCHAR(255),
|
||||
vSupplierFk VARCHAR(255),
|
||||
vColor VARCHAR(255),
|
||||
vSize INT,
|
||||
vOrigen INT,
|
||||
vLack INT,
|
||||
vWarehouseFk INT
|
||||
)
|
||||
BEGIN
|
||||
/**
|
||||
* Calcula una tabla con el máximo negativo visible para cada producto y almacen
|
||||
*
|
||||
*
|
||||
* @param vForce Fuerza el recalculo del stock
|
||||
* @param vDays Numero de dias a considerar
|
||||
**/
|
||||
|
@ -13,33 +24,33 @@ BEGIN
|
|||
CALL item_getMinETD();
|
||||
CALL item_zoneClosure();
|
||||
|
||||
SELECT i.id itemFk,
|
||||
SELECT i.id itemFk,
|
||||
i.longName,
|
||||
w.id warehouseFk,
|
||||
p.`name` producer,
|
||||
p.`name` producer,
|
||||
i.`size`,
|
||||
i.category,
|
||||
w.name warehouse,
|
||||
w.name warehouse,
|
||||
SUM(IFNULL(sub.amount,0)) lack,
|
||||
i.inkFk,
|
||||
IFNULL(im.timed, util.midnight()) timed,
|
||||
IFNULL(izc.timed, util.midnight()) minTimed,
|
||||
o.name originFk
|
||||
FROM (SELECT item_id,
|
||||
warehouse_id,
|
||||
FROM (SELECT item_id,
|
||||
warehouse_id,
|
||||
amount
|
||||
FROM cache.stock
|
||||
WHERE amount > 0
|
||||
UNION ALL
|
||||
SELECT itemFk,
|
||||
warehouseFk,
|
||||
SELECT itemFk,
|
||||
warehouseFk,
|
||||
amount
|
||||
FROM tmp.itemMinacum
|
||||
) sub
|
||||
JOIN warehouse w ON w.id = sub.warehouse_id
|
||||
JOIN item i ON i.id = sub.item_id
|
||||
LEFT JOIN producer p ON p.id = i.producerFk
|
||||
JOIN itemType it ON it.id = i.typeFk
|
||||
LEFT JOIN producer p ON p.id = i.producerFk
|
||||
JOIN itemType it ON it.id = i.typeFk
|
||||
JOIN itemCategory ic ON ic.id = it.categoryFk
|
||||
LEFT JOIN tmp.itemMinETD im ON im.itemFk = i.id
|
||||
LEFT JOIN tmp.itemZoneClosure izc ON izc.itemFk = i.id
|
||||
|
@ -47,6 +58,14 @@ BEGIN
|
|||
WHERE w.isForTicket
|
||||
AND ic.display
|
||||
AND it.code != 'GEN'
|
||||
AND (vId IS NULL OR i.id = vId)
|
||||
AND (vLongname IS NULL OR i.name = vLongname)
|
||||
AND (vSupplierFk IS NULL OR p.`name` LIKE CONCAT('%', vSupplierFk, '%'))
|
||||
AND (vColor IS NULL OR vColor = i.inkFk)
|
||||
AND (vSize IS NULL OR vSize = i.`size`)
|
||||
AND (vOrigen IS NULL OR vOrigen = w.id)
|
||||
AND (vLack IS NULL OR vLack = sub.amount)
|
||||
AND (vWarehouseFk IS NULL OR vWarehouseFk = w.id)
|
||||
GROUP BY i.id, w.id
|
||||
HAVING lack < 0;
|
||||
|
||||
|
|
|
@ -82,21 +82,26 @@ BEGIN
|
|||
AND it.priority = vPriority
|
||||
LEFT JOIN vn.tag t ON t.id = it.tagFk
|
||||
LEFT JOIN vn.buy b ON b.id = bu.buyFk
|
||||
LEFT JOIN vn.itemShelvingStock iss ON iss.itemFk = i.id
|
||||
AND iss.warehouseFk = vWarehouseFk
|
||||
LEFT JOIN vn.ink ink ON ink.id = i.tag5
|
||||
JOIN itemTags its
|
||||
WHERE a.available > 0
|
||||
AND (i.typeFk = its.typeFk OR NOT vShowType)
|
||||
AND i.id <> vSelf
|
||||
ORDER BY `counter` DESC,
|
||||
(t.name = its.name) DESC,
|
||||
(it.value = its.value) DESC,
|
||||
(i.tag5 = its.tag5) DESC,
|
||||
match5 DESC,
|
||||
(i.tag6 = its.tag6) DESC,
|
||||
match6 DESC,
|
||||
(i.tag7 = its.tag7) DESC,
|
||||
match7 DESC,
|
||||
(i.tag8 = its.tag8) DESC,
|
||||
match8 DESC
|
||||
ORDER BY (a.available > 0) DESC,
|
||||
`counter` DESC,
|
||||
(t.name = its.name) DESC,
|
||||
(it.value = its.value) DESC,
|
||||
(i.tag5 = its.tag5) DESC,
|
||||
(ink.`showOrder`) DESC,
|
||||
match5 DESC,
|
||||
(i.tag6 = its.tag6) DESC,
|
||||
match6 DESC,
|
||||
(i.tag7 = its.tag7) DESC,
|
||||
match7 DESC,
|
||||
(i.tag8 = its.tag8) DESC,
|
||||
match8 DESC
|
||||
LIMIT 100;
|
||||
|
||||
DROP TEMPORARY TABLE tmp.buyUltimate;
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
INSERT IGNORE INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
|
||||
VALUES
|
||||
('Ticket','itemLack','READ','ALLOW','ROLE','employee'),
|
||||
('Ticket','itemLackDetail','READ','ALLOW','ROLE','employee'),
|
||||
('Ticket','itemLackOrigin','WRITE','ALLOW','ROLE','employee'),
|
||||
('Ticket','split','WRITE','ALLOW','ROLE','employee'),
|
||||
('Ticket','negativeOrigin','READ','ALLOW','ROLE','employee'),
|
||||
('Sale','replaceItem','READ','ALLOW','ROLE','employee');
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE vn.negativeOrigin MODIFY COLUMN `type` enum('FALTAS','CONTENEDOR','ENTRADAS','OVERBOOKING', 'SUSTITUCION') CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NOT NULL;
|
|
@ -234,6 +234,7 @@
|
|||
"It has been invoiced but the PDF of refund not be generated": "It has been invoiced but the PDF of refund not be generated",
|
||||
"Cannot add holidays on this day": "Cannot add holidays on this day",
|
||||
"Cannot send mail": "Cannot send mail",
|
||||
"This worker already exists": "This worker already exists",
|
||||
"CONSTRAINT `chkParkingCodeFormat` failed for `vn`.`parking`": "CONSTRAINT `chkParkingCodeFormat` failed for `vn`.`parking`",
|
||||
"This postcode already exists": "This postcode already exists",
|
||||
"Original invoice not found": "Original invoice not found",
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('getSimilar', {
|
||||
description: 'Returns the ',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'filter',
|
||||
type: 'Object',
|
||||
required: true,
|
||||
description: 'Filter defining where and paginated data',
|
||||
http: {source: 'query'}
|
||||
}],
|
||||
returns: {
|
||||
type: ['Object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/getSimilar`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.getSimilar = async(ctx, filter, options) => {
|
||||
const myOptions = {userId: ctx.req.accessToken.userId};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
const where = filter.where;
|
||||
const today =
|
||||
new Date().toLocaleDateString('es-ES', {year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit'});
|
||||
const query = [
|
||||
where.itemFk,
|
||||
where.warehouseFk,
|
||||
where.date ?? today,
|
||||
where.showType ?? true,
|
||||
where.scopeDays ?? 2
|
||||
];
|
||||
const [results] = await Self.rawSql('CALL vn.item_getSimilar(?, ?, ?, ?, ?)', query, myOptions);
|
||||
|
||||
return [
|
||||
{
|
||||
'id': 1,
|
||||
'longName': 'Ranged weapon longbow 50cm',
|
||||
'subName': 'Stark Industries',
|
||||
'tag5': 'Color',
|
||||
'value5': 'Brown',
|
||||
'match5': 0,
|
||||
'match6': 0,
|
||||
'match7': 0,
|
||||
'match8': 1,
|
||||
'tag6': 'Categoria',
|
||||
'value6': '+1 precission',
|
||||
'tag7': 'Tallos',
|
||||
'value7': '1',
|
||||
'tag8': null,
|
||||
'value8': null,
|
||||
'available': 20,
|
||||
'calc_id': 6,
|
||||
'counter': 0,
|
||||
'minQuantity': 1,
|
||||
'visible': null,
|
||||
'price2': 1
|
||||
},
|
||||
{
|
||||
'id': 2,
|
||||
'longName': 'Ranged weapon longbow 100cm',
|
||||
'subName': 'Stark Industries',
|
||||
'tag5': 'Color',
|
||||
'value5': 'Brown',
|
||||
'match5': 0,
|
||||
'match6': 1,
|
||||
'match7': 0,
|
||||
'match8': 1,
|
||||
'tag6': 'Categoria',
|
||||
'value6': '+1 precission',
|
||||
'tag7': 'Tallos',
|
||||
'value7': '1',
|
||||
'tag8': null,
|
||||
'value8': null,
|
||||
'available': 50,
|
||||
'calc_id': 6,
|
||||
'counter': 1,
|
||||
'minQuantity': 5,
|
||||
'visible': null,
|
||||
'price2': 10
|
||||
},
|
||||
{
|
||||
'id': 3,
|
||||
'longName': 'Ranged weapon longbow 200cm',
|
||||
'subName': 'Stark Industries',
|
||||
'tag5': 'Color',
|
||||
'value5': 'Brown',
|
||||
'match5': 1,
|
||||
'match6': 1,
|
||||
'match7': 1,
|
||||
'match8': 1,
|
||||
'tag6': 'Categoria',
|
||||
'value6': '+1 precission',
|
||||
'tag7': 'Tallos',
|
||||
'value7': '1',
|
||||
'tag8': null,
|
||||
'value8': null,
|
||||
'available': 185,
|
||||
'calc_id': 6,
|
||||
'counter': 10,
|
||||
'minQuantity': 10,
|
||||
'visible': null,
|
||||
'price2': 100
|
||||
}
|
||||
|
||||
];
|
||||
};
|
||||
};
|
|
@ -5,6 +5,7 @@ module.exports = Self => {
|
|||
require('../methods/item/clone')(Self);
|
||||
require('../methods/item/updateTaxes')(Self);
|
||||
require('../methods/item/getBalance')(Self);
|
||||
require('../methods/item/getSimilar')(Self);
|
||||
require('../methods/item/lastEntriesFilter')(Self);
|
||||
require('../methods/item/getSummary')(Self);
|
||||
require('../methods/item/getCard')(Self);
|
||||
|
|
|
@ -414,6 +414,6 @@ module.exports = Self => {
|
|||
const sql = ParameterizedSQL.join(stmts, ';');
|
||||
const result = await conn.executeStmt(sql, myOptions);
|
||||
|
||||
return result[ticketsIndex];
|
||||
return Array(19).fill().flatMap(() => result[ticketsIndex]);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -31,7 +31,7 @@ describe('route getSuggestedTickets()', () => {
|
|||
const length = result.length;
|
||||
const anyResult = result[Math.floor(Math.random() * Math.floor(length))];
|
||||
|
||||
expect(result.length).toEqual(4);
|
||||
expect(result.length).toEqual(5);
|
||||
expect(anyResult.zoneFk).toEqual(1);
|
||||
expect(anyResult.agencyModeFk).toEqual(8);
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ describe('route unlink()', () => {
|
|||
let tickets = await models.Route.getSuggestedTickets(routeId, options);
|
||||
|
||||
expect(zoneAgencyModes.length).toEqual(4);
|
||||
expect(tickets.length).toEqual(3);
|
||||
expect(tickets.length).toEqual(4);
|
||||
|
||||
await models.Route.unlink(agencyModeId, zoneId, options);
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('replaceItem', {
|
||||
description: 'Replace item from sale',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'saleFk',
|
||||
type: 'number',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
arg: 'substitutionFk',
|
||||
type: 'number',
|
||||
required: true
|
||||
},
|
||||
{
|
||||
arg: 'quantity',
|
||||
type: 'number',
|
||||
required: true
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/replaceItem`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.replaceItem = async(ctx, saleFk, substitutionFk, quantity, options) => {
|
||||
const myOptions = {userId: ctx.req.accessToken.userId};
|
||||
let tx;
|
||||
const $t = ctx.req.__;
|
||||
|
||||
const models = Self.app.models;
|
||||
|
||||
// const {_saleFk, _substitutionFk, _quantity} = ctx.args;
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
if (!myOptions.transaction) {
|
||||
tx = await Self.beginTransaction({});
|
||||
myOptions.transaction = tx;
|
||||
}
|
||||
|
||||
try {
|
||||
const _replaceItem = {sql: 'CALL sale_replaceItem(?,?,?)', query: [saleFk, substitutionFk, quantity]};
|
||||
const result = await Self.rawSql(_replaceItem.sql, _replaceItem.query, myOptions);
|
||||
const _salesPerson = {sql: 'SELECT vn.client_getSalesPersonByTicket(?)', query: [saleFk.ticket.id]};
|
||||
const salesPerson = await Self.rawSql(_salesPerson.query, _salesPerson.sql, myOptions);
|
||||
const message = $t('negativeReplaced', {
|
||||
old: itemFk,
|
||||
oldUrl: `${url}item/${itemFk}/summary`,
|
||||
new: itemFk,
|
||||
newUrl: `${url}item/${itemFk}/summary`,
|
||||
ticket: ticketFk,
|
||||
ticketUrl: `${url}ticket/${ticketFk}/sale`,
|
||||
});
|
||||
await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message);
|
||||
|
||||
return result;
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -0,0 +1,103 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethod('itemLack', {
|
||||
description: 'Get tickets as negative status',
|
||||
accessType: 'READ',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'ctx',
|
||||
alexm
commented
Cambiar descripccion Cambiar descripccion
|
||||
type: 'object',
|
||||
http: {source: 'context'}
|
||||
},
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'object',
|
||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'itemFk',
|
||||
type: 'number',
|
||||
description: 'The item id',
|
||||
},
|
||||
{
|
||||
arg: 'longname',
|
||||
type: 'string',
|
||||
description: 'Article name',
|
||||
},
|
||||
{
|
||||
arg: 'supplier',
|
||||
type: 'string',
|
||||
description: 'Supplier id',
|
||||
},
|
||||
{
|
||||
arg: 'colour',
|
||||
type: 'string',
|
||||
description: 'Colour\'s item',
|
||||
},
|
||||
{
|
||||
arg: 'size',
|
||||
type: 'string',
|
||||
description: 'Size\'s item',
|
||||
},
|
||||
{
|
||||
arg: 'origen',
|
||||
type: 'string',
|
||||
description: 'origen id',
|
||||
},
|
||||
{
|
||||
arg: 'warehouseFk',
|
||||
type: 'number',
|
||||
description: 'The warehouse id',
|
||||
},
|
||||
{
|
||||
arg: 'lack',
|
||||
type: 'number',
|
||||
description: 'The item id',
|
||||
},
|
||||
{
|
||||
arg: 'days',
|
||||
type: 'number',
|
||||
description: 'The range days',
|
||||
}
|
||||
],
|
||||
returns: [
|
||||
{
|
||||
arg: 'body',
|
||||
type: ['object'],
|
||||
root: true
|
||||
}
|
||||
],
|
||||
http: {
|
||||
path: `/itemLack`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.itemLack = async(ctx, filter, options) => {
|
||||
const myOptions = {};
|
||||
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
const filterKeyOrder = ['days', 'itemFk', 'longname', 'supplier', 'colour', 'size', 'origen', 'lack', 'warehouseFk'];
|
||||
|
||||
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));
|
||||
|
||||
if (!procedureParams[1])procedureParams[1] = 2;
|
||||
const procedureArgs = Array(procedureParams.length).fill('?').join(', ');
|
||||
|
||||
let query = `CALL vn.item_getLack(${procedureArgs})`;
|
||||
jsegarra marked this conversation as resolved
Outdated
jgallego
commented
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
jsegarra
commented
Lo anoto para hablar con el Lo anoto para hablar con el
jsegarra
commented
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
jsegarra
commented
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
|
||||
|
||||
const result = await Self.rawSql(query, procedureParams, myOptions);
|
||||
|
||||
const itemsIndex = 0;
|
||||
return result[itemsIndex];
|
||||
};
|
||||
};
|
|
@ -0,0 +1,153 @@
|
|||
const {ParameterizedSQL} = require('loopback-connector');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('itemLackDetail', {
|
||||
description: 'Retrieve detail from ticket',
|
||||
jsegarra marked this conversation as resolved
Outdated
jgallego
commented
esta descripcion corresponde ? esta descripcion corresponde ?
|
||||
accessType: 'READ',
|
||||
accepts: [
|
||||
{
|
||||
arg: 'itemFk',
|
||||
jsegarra marked this conversation as resolved
Outdated
jgallego
commented
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',
|
||||
},
|
||||
{
|
||||
arg: 'warehouseFk',
|
||||
type: 'number',
|
||||
description: 'The warehouse id',
|
||||
},
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'object',
|
||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
||||
http: {source: 'query'}
|
||||
}
|
||||
],
|
||||
returns: [
|
||||
{
|
||||
arg: 'body',
|
||||
type: ['object'],
|
||||
root: true,
|
||||
},
|
||||
],
|
||||
http: {
|
||||
path: `/itemLack/:itemFk`,
|
||||
verb: 'GET',
|
||||
},
|
||||
});
|
||||
|
||||
Self.itemLackDetail = async(itemFk, warehouseFk, filter, options) => {
|
||||
const conn = Self.dataSource.connector;
|
||||
|
||||
const myOptions = {};
|
||||
if (typeof options == 'object') Object.assign(myOptions, options);
|
||||
|
||||
const stmt = new ParameterizedSQL(
|
||||
`
|
||||
SELECT
|
||||
s.id,
|
||||
st.code,
|
||||
t.id,
|
||||
t.nickname,
|
||||
t.shipped,
|
||||
s.quantity,
|
||||
ag.name,
|
||||
IF(ISNULL(tls.alertLevel),0,tls.alertLevel) alertLevel,
|
||||
IF(ISNULL(st.name),'Libre',st.name) stateName,
|
||||
s.id stateId,
|
||||
s.itemFk,
|
||||
al.code AS alertLevelCode,
|
||||
z.name,
|
||||
Format(z.hour, "hh:mm") theoreticalhour,
|
||||
cn.isRookie,
|
||||
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,
|
||||
substitution.hasSubstitution,
|
||||
IF(d.code = 'spainTeamVip', 1, 0) hasToIgnore
|
||||
FROM sale s
|
||||
LEFT JOIN saleGroupDetail sgd ON sgd.saleFk = s.id
|
||||
INNER JOIN ticket t ON t.id =s.ticketFk
|
||||
LEFT JOIN zone z ON z.id = t.zoneFk
|
||||
LEFT JOIN zoneClosure zc ON zc.zoneFk = t.zoneFk
|
||||
AND zc.dated = DATE(t.shipped)
|
||||
INNER JOIN client c ON c.id=t.clientFk
|
||||
LEFT JOIN bs.clientNewBorn cn ON cn.clientFk=c.id
|
||||
INNER JOIN agencyMode ag ON ag.id=t.agencyModeFk
|
||||
INNER JOIN ticketState tls ON tls.ticketFk=t.id
|
||||
LEFT JOIN state st ON st.id=tls.state
|
||||
LEFT JOIN alertLevel al ON al.id = st.alertLevel
|
||||
LEFT JOIN saleCloned sc ON sc.saleClonedFk = s.id
|
||||
LEFT JOIN ticketRequest tr ON tr.saleFk = s.id
|
||||
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
|
||||
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 >= CURDATE()
|
||||
AND t.shipped < DATE_ADD(CURDATE(), INTERVAL ? DAY)
|
||||
AND sgd.saleFk IS NULL
|
||||
AND (al.code IN ('FREE', 'ON_PREVIOUS') OR al.code IS NULL)
|
||||
UNION ALL
|
||||
SELECT r.id,
|
||||
NULL,
|
||||
r.orderFk,
|
||||
c.name,
|
||||
r.shipment,
|
||||
r.amount,
|
||||
ag.name,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
r.itemFk,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
cn.isRookie,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
substitution.hasSubstitution,
|
||||
IF(d.code = 'spainTeamVip', 1, 0)
|
||||
FROM hedera.orderRow r
|
||||
INNER JOIN hedera.order o ON o.id = r.orderFk
|
||||
INNER JOIN client c ON c.id = o.customer_id
|
||||
INNER JOIN agencyMode ag ON ag.id=o.agency_id
|
||||
LEFT JOIN bs.clientNewBorn cn ON cn.clientFk=c.id
|
||||
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) 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 r.shipment >= CURDATE()
|
||||
AND r.shipment < DATE_ADD(CURDATE(), INTERVAL ? DAY)
|
||||
AND r.warehouseFk = ?
|
||||
AND r.created >= STR_TO_DATE(CURDATE(), '%Y-%m-%d %H:%i:%s')
|
||||
AND NOT o.confirmed
|
||||
AND r.itemFk = ?
|
||||
AND r.amount <> 0
|
||||
ORDER BY hasToIgnore, isBasket;`,
|
||||
[itemFk, warehouseFk, 2, 2, warehouseFk, itemFk]);
|
||||
|
||||
// if (filter.where.alertLevel) {
|
||||
// stmt.merge({
|
||||
// sql: `AND ${filter.where.alertLevel ? '' : 'NOT'} ts.alertLevel=?`, params: [0]});
|
||||
// }
|
||||
// stmt.merge(conn.makeWhere(filter.where));
|
||||
const sql = ParameterizedSQL.join([stmt], ';');
|
||||
const result = await conn.executeStmt(sql, myOptions);
|
||||
return result;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,40 @@
|
|||
const {ParameterizedSQL} = require('loopback-connector');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('itemLackOrigin', {
|
||||
description: 'Insert ticket negative into negativeOrigin',
|
||||
accessType: 'WRITE',
|
||||
accepts: [{
|
||||
arg: 'ctx',
|
||||
type: 'Object',
|
||||
http: {source: 'context'}
|
||||
}, {arg: 'tickets', type: 'array', http: {source: 'body'}}],
|
||||
returns:
|
||||
{
|
||||
type: 'boolean',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/itemLackOrigin`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.itemLackOrigin = async(ctx, data, options) => {
|
||||
const myOptions = {};
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
if (!myOptions.transaction) {
|
||||
tx = await Self.beginTransaction({});
|
||||
myOptions.transaction = tx;
|
||||
}
|
||||
const conn = Self.dataSource.connector;
|
||||
const stmts = data.map(({itemFk, negativeType, lack}) =>
|
||||
`INSERT INTO vn.negativeOrigin (itemFk, type, quantity)
|
||||
VALUES (${itemFk}, "${negativeType}", ${lack})
|
||||
ON DUPLICATE KEY UPDATE quantity = quantity + VALUES(quantity)`) ?? [];
|
||||
const sql = ParameterizedSQL.join(stmts, ';');
|
||||
const result = await conn.executeStmt(sql, myOptions);
|
||||
return result;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('negativeOrigin', {
|
||||
description: 'Get tickets from negativeOrigin',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'ctx',
|
||||
type: 'Object',
|
||||
http: {source: 'context'}
|
||||
}],
|
||||
returns: {
|
||||
type: 'object',
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/negativeOrigin`,
|
||||
verb: 'GET'
|
||||
}
|
||||
});
|
||||
|
||||
Self.negativeOrigin = async(ctx, data, options) => {
|
||||
const myOptions = {};
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
if (!myOptions.transaction) {
|
||||
tx = await Self.beginTransaction({});
|
||||
myOptions.transaction = tx;
|
||||
}
|
||||
const negativesOrigin = await Self.app.models.NegativeOrigin.find();
|
||||
return negativesOrigin;
|
||||
};
|
||||
jsegarra marked this conversation as resolved
jgallego
commented
esto no puede ser un find de loopback? esto no puede ser un find de loopback?
jsegarra
commented
La tabla negativeOrigin no está publicada en el model-config.json. La tabla negativeOrigin no está publicada en el model-config.json.
Pensé lo mismo, y supuse que si no se hizo fue por un motivo
jgallego
commented
porque serás el primero que la necesita, publicala. porque serás el primero que la necesita, publicala.
jsegarra
commented
Okey, tomo nota para ahcer las modificaciones necesarias Okey, tomo nota para ahcer las modificaciones necesarias
|
||||
};
|
|
@ -0,0 +1,154 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('Item Lack', () => {
|
||||
beforeEach(async() => {
|
||||
ctx = {
|
||||
req: {
|
||||
accessToken: {},
|
||||
headers: {origin: 'http://localhost'},
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
expect(result.length).toEqual(2);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return data with filter.id', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
const options = {transaction: tx};
|
||||
const filter = {
|
||||
id: 88
|
||||
};
|
||||
try {
|
||||
const result = await models.Ticket.itemLack(ctx, filter, options);
|
||||
|
||||
expect(result.length).toEqual(2);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return data with filter.longname', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
const options = {transaction: tx};
|
||||
const filter = {
|
||||
longname: 'Lack negative'
|
||||
};
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
xit('should return data with filter.name', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
const options = {transaction: tx};
|
||||
const filter = {
|
||||
name: 1
|
||||
};
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
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);
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return data with filter.origen', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
const options = {transaction: tx};
|
||||
const filter = {
|
||||
origen: 1
|
||||
};
|
||||
try {
|
||||
const result = await models.Ticket.itemLack(ctx, filter, options);
|
||||
|
||||
expect(result.length).toEqual(2);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return data with filter.size', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
const options = {transaction: tx};
|
||||
const filter = {
|
||||
size: '200'
|
||||
};
|
||||
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;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return data with filter.lack', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
const options = {transaction: tx};
|
||||
const filter = {
|
||||
lack: '-155'
|
||||
};
|
||||
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;
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,52 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('Item Lack Detail', () => {
|
||||
it('should return false if id is null', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
const id = null;
|
||||
|
||||
const result = await models.Ticket.itemLackDetail(id, options);
|
||||
|
||||
expect(result.length).toEqual(0);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return data if id exists', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
const id = 1167;
|
||||
const result = await models.Ticket.itemLackDetail(id, options);
|
||||
|
||||
expect(result.length).toEqual(0);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return error is if not exists', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
const id = 0;
|
||||
const result = await models.Ticket.itemLackDetail(id, options);
|
||||
|
||||
expect(result.length).toEqual(0);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,51 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('NegativeOrigin', () => {
|
||||
it('should return OK', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
const ctx = {req: {accessToken: {userId: 9}}};
|
||||
|
||||
const options = {transaction: tx};
|
||||
const data = [
|
||||
{itemFk: 1, negativeType: 'FALTAS', lack: 1},
|
||||
{itemFk: 1, negativeType: 'FALTAS', lack: 2}
|
||||
];
|
||||
try {
|
||||
await models.Ticket.itemLackOrigin(ctx, data, options);
|
||||
const query = 'SELECT * FROM vn.negativeOrigin';
|
||||
|
||||
const negativeOrigin = await models.Application.rawSql(query, null, options);
|
||||
|
||||
expect(negativeOrigin.length).toEqual(1);
|
||||
expect(negativeOrigin[0].quantity).toEqual(3);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should add 2 lines', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
const ctx = {req: {accessToken: {userId: 9}}};
|
||||
|
||||
const options = {transaction: tx};
|
||||
const data = [
|
||||
{itemFk: 2, negativeType: 'FALTAS', lack: 1},
|
||||
{itemFk: 3, negativeType: 'FALTAS', lack: 2}
|
||||
];
|
||||
try {
|
||||
await models.Ticket.itemLackOrigin(ctx, data, options);
|
||||
const query = 'SELECT * FROM vn.negativeOrigin';
|
||||
|
||||
const negativeOrigin = await models.Application.rawSql(query, null, options);
|
||||
|
||||
expect(negativeOrigin.length).toEqual(2);
|
||||
expect(negativeOrigin[0].quantity).toEqual(1);
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,98 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('Split', () => {
|
||||
beforeAll(async() => {
|
||||
ctx = {
|
||||
req: {
|
||||
accessToken: {},
|
||||
headers: {origin: 'http://localhost'},
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
it('should split tickets with count 1', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
const options = {transaction: tx};
|
||||
const data = [
|
||||
{ticketFk: 7}
|
||||
];
|
||||
try {
|
||||
const result = await models.Ticket.split(ctx, data, options);
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0].ticket).toEqual(7);
|
||||
expect(result[0].status).toEqual('noSplit');
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should split tickets with count 2 and error', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
const options = {transaction: tx};
|
||||
const data = [
|
||||
{ticketFk: 8}
|
||||
];
|
||||
try {
|
||||
const result = await models.Ticket.split(ctx, data, options);
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0].ticket).toEqual(8);
|
||||
expect(result[0].status).toEqual('error');
|
||||
expect(result[0].message).toEqual('This ticket is not editable.');
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should split tickets with count 2 and other error', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
const options = {transaction: tx};
|
||||
const data = [
|
||||
{ticketFk: 16}
|
||||
];
|
||||
try {
|
||||
const result = await models.Ticket.split(ctx, data, options);
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0].ticket).toEqual(16);
|
||||
expect(result[0].status).toEqual('error');
|
||||
expect(result[0].message).toEqual('Can\'t transfer claimed sales');
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should split tickets with count 2 and success', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
const options = {transaction: tx};
|
||||
const data = [
|
||||
{ticketFk: 32}
|
||||
];
|
||||
try {
|
||||
const result = await models.Ticket.split(ctx, data, options);
|
||||
|
||||
expect(result.length).toEqual(1);
|
||||
expect(result[0].ticket).toEqual(32);
|
||||
expect(result[0].status).toEqual('split');
|
||||
|
||||
await tx.rollback();
|
||||
} catch (e) {
|
||||
await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
|
@ -0,0 +1,82 @@
|
|||
module.exports = Self => {
|
||||
Self.remoteMethodCtx('split', {
|
||||
description: 'Split n tickets',
|
||||
accessType: 'WRITE',
|
||||
accepts: [
|
||||
{
|
||||
|
||||
type: ['Object'],
|
||||
required: true,
|
||||
http: {source: 'body'}
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: ['Object'],
|
||||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/split`,
|
||||
verb: 'POST'
|
||||
}
|
||||
});
|
||||
|
||||
Self.split = async(ctx, tickets, options) => {
|
||||
const models = Self.app.models;
|
||||
const myOptions = {};
|
||||
let tx;
|
||||
let results = [];
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
|
||||
if (!myOptions.transaction) {
|
||||
tx = await Self.beginTransaction({});
|
||||
myOptions.transaction = tx;
|
||||
}
|
||||
|
||||
jsegarra marked this conversation as resolved
Outdated
jgallego
commented
quitar comentarios quitar comentarios
jsegarra
commented
Resuelto Resuelto
|
||||
try {
|
||||
const ticketsIds = tickets.map(({ticketFk}, index) => ticketFk);
|
||||
const ticketsCount = await Self.rawSql(`
|
||||
jgallego
commented
si el objetivo es contar tickets te sobraria la tabla sale, si el objetivo es contar tickets te sobraria la tabla sale,
si el objetivo es contar sales te sobraria la tabla ticket
|
||||
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 IN (?) GROUP BY t.id;`,
|
||||
[ticketsIds], myOptions);
|
||||
|
||||
for (const {tid, count} of ticketsCount) {
|
||||
try {
|
||||
if (count === 1) {
|
||||
results.push({ticket: tid, status: 'noSplit'});
|
||||
continue;
|
||||
}
|
||||
const [, [{vNewTicket}]] = await Self.rawSql(`
|
||||
CALL vn.ticket_clone(?, @vNewTicket);
|
||||
SELECT @vNewTicket vNewTicket;`,
|
||||
[tid], myOptions);
|
||||
|
||||
if (vNewTicket === 0) continue;
|
||||
jgallego
commented
en que caso devuelve un ticket = 0? en que caso devuelve un ticket = 0?
jsegarra
commented
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
|
||||
const sales = await models.Sale.find({
|
||||
where: {ticketFk: tid}
|
||||
}, myOptions);
|
||||
|
||||
const updateIsPicked = sales.map(({sid}) => Self.rawSql(`
|
||||
UPDATE vn.sale SET isPicked = (id = ?) WHERE ticketFk = ?`,
|
||||
[sid, tid], myOptions));
|
||||
await Promise.all(updateIsPicked);
|
||||
await Self.transferSales(ctx, tid, vNewTicket, sales, myOptions);
|
||||
|
||||
await Self.rawSql(`CALL vn.ticket_setState(?, ?)`, [tid, 'FIXING'], myOptions);
|
||||
results.push({ticket: tid, newTicket: vNewTicket, status: 'split'});
|
||||
await tx.commit();
|
||||
} catch ({message}) {
|
||||
results.push({ticket: tid, status: 'error', message});
|
||||
}
|
||||
}
|
||||
return results;
|
||||
} catch (e) {
|
||||
if (tx) await tx.rollback();
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
};
|
|
@ -35,6 +35,9 @@
|
|||
"PackingSiteConfig": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"NegativeOrigin": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
"ExpeditionMistake": {
|
||||
"dataSource": "vn"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "NegativeOrigin",
|
||||
"base": "VnModel",
|
||||
"options": {
|
||||
"mysql": {
|
||||
"table": "negativeOrigin"
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"id": {
|
||||
"id": true,
|
||||
"type": "number",
|
||||
"description": "Identifier"
|
||||
}
|
||||
},
|
||||
"relations": {
|
||||
"item": {
|
||||
"type": "belongsTo",
|
||||
"model": "Item",
|
||||
"foreignKey": "itemFk"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,7 @@ module.exports = Self => {
|
|||
require('../methods/sale/usesMana')(Self);
|
||||
require('../methods/sale/clone')(Self);
|
||||
require('../methods/sale/getFromSectorCollection')(Self);
|
||||
// require('../methods/sale/replaceItem')(Self);
|
||||
|
||||
Self.validatesPresenceOf('concept', {
|
||||
message: `Concept cannot be blank`
|
||||
|
|
|
@ -46,4 +46,9 @@ module.exports = function(Self) {
|
|||
require('../methods/ticket/docuwareDownload')(Self);
|
||||
require('../methods/ticket/myLastModified')(Self);
|
||||
require('../methods/ticket/setWeight')(Self);
|
||||
require('../methods/ticket/itemLack')(Self);
|
||||
require('../methods/ticket/itemLackDetail')(Self);
|
||||
require('../methods/ticket/itemLackOrigin')(Self);
|
||||
require('../methods/ticket/negativeOrigin')(Self);
|
||||
require('../methods/ticket/split')(Self);
|
||||
};
|
||||
|
|
|
@ -113,7 +113,7 @@
|
|||
"yaml-loader": "^0.5.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test:back": "nodemon -q back/tests.js --config back/nodemonConfig.json",
|
||||
"test:back": "nodemon -q back/tests.js --config back/nodemonConfig.json --debug",
|
||||
"test:e2e": "node e2e/tests.js",
|
||||
"test:front": "jest --watch",
|
||||
"back": "nodemon --inspect -w modules ./node_modules/gulp/bin/gulp.js back",
|
||||
|
|
Quitar supongo