Merge branch 'app_voz' of verdnatura/salix into dev
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Joan Sanchez 2020-04-17 12:38:16 +00:00 committed by Gitea
commit 202ddd552f
25 changed files with 1668 additions and 1039 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

BIN
back/.DS_Store vendored Normal file

Binary file not shown.

BIN
back/methods/.DS_Store vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,35 @@
module.exports = Self => {
Self.remoteMethod('collectionFaults', {
description: 'Update sale of a collection',
accessType: 'WRITE',
accepts: [{
arg: 'shelvingFk',
type: 'String',
required: true,
description: 'The shalving id'
}, {
arg: 'quantity',
type: 'Number',
required: true,
description: 'The quantity to sale'
}, {
arg: 'itemFk',
type: 'Number',
required: true,
description: 'The ticket id'
}],
returns: {
type: 'Object',
root: true
},
http: {
path: `/collectionFaults`,
verb: 'POST'
}
});
Self.collectionFaults = async(shelvingFk, quantity, itemFk) => {
query = `CALL vn.collection_faults(?,?,?)`;
return await Self.rawSql(query, [shelvingFk, quantity, itemFk]);
};
};

View File

@ -0,0 +1,22 @@
module.exports = Self => {
Self.remoteMethodCtx('getCollection', {
description: 'Get pending collections from a worker',
accessType: 'READ',
returns: {
type: 'Object',
root: true
},
http: {
path: `/getCollection`,
verb: 'GET'
}
});
Self.getCollection = async ctx => {
const userId = ctx.req.accessToken.userId;
const query = `CALL vn.collection_get(?)`;
const [result] = await Self.rawSql(query, [userId]);
return result;
};
};

View File

@ -0,0 +1,20 @@
module.exports = Self => {
Self.remoteMethod('getSectors', {
description: 'Get all sectors',
accessType: 'READ',
returns: {
type: 'Object',
root: true
},
http: {
path: `/getSectors`,
verb: 'GET'
}
});
Self.getSectors = async() => {
const query = `CALL vn.sector_get()`;
const [result] = await Self.rawSql(query);
return result;
};
};

View File

@ -0,0 +1,133 @@
module.exports = Self => {
Self.remoteMethodCtx('newCollection', {
description: 'Make a new collection of tickets',
accessType: 'WRITE',
accepts: [{
arg: 'collectionFk',
type: 'Number',
required: false,
description: 'The collection id'
}, {
arg: 'sectorFk',
type: 'Number',
required: true,
description: 'The sector of worker'
}, {
arg: 'vWagons',
type: 'Number',
required: true,
description: 'The number of wagons'
}],
returns: {
type: 'Object',
root: true
},
http: {
path: `/newCollection`,
verb: 'POST'
}
});
Self.newCollection = async(ctx, collectionFk, sectorFk, vWagons) => {
let query = '';
if (!collectionFk) {
const userId = ctx.req.accessToken.userId;
query = `CALL vn.collectionTrain_newBeta(?,?,?)`;
const [result] = await Self.rawSql(query, [sectorFk, vWagons, userId]);
if (result.length == 0)
throw new Error(`No collections for today`);
collectionFk = result[0].vCollectionFk;
}
query = `CALL vn.collectionTicket_get(?)`;
const [tickets] = await Self.rawSql(query, [collectionFk]);
query = `CALL vn.collectionSale_get(?)`;
const [sales] = await Self.rawSql(query, [collectionFk]);
query = `CALL vn.collectionPlacement_get(?)`;
const [placements] = await Self.rawSql(query, [collectionFk]);
query = `CALL vn.collectionSticker_print(?,?)`;
await Self.rawSql(query, [collectionFk, sectorFk]);
return makeCollection(tickets, sales, placements, collectionFk);
};
/**
* Returns a collection json
* @param {*} tickets - Request tickets
* @param {*} sales - Request sales
* @param {*} placements - Request placements
* @param {*} collectionFk - Request placements
* @return {Object} Collection JSON
*/
async function makeCollection(tickets, sales, placements, collectionFk) {
let collection = [];
for (let i = 0; i < tickets.length; i++) {
let ticket = {};
ticket['ticketFk'] = tickets[i]['ticketFk'];
ticket['level'] = tickets[i]['level'];
ticket['agencyName'] = tickets[i]['agencyName'];
ticket['warehouseFk'] = tickets[i]['warehouseFk'];
ticket['salesPersonFk'] = tickets[i]['salesPersonFk'];
let ticketSales = [];
for (let x = 0; x < sales.length; x++) {
if (sales[x]['ticketFk'] == ticket['ticketFk']) {
let sale = {};
sale['collectionFk'] = collectionFk;
sale['ticketFk'] = sales[x]['ticketFk'];
sale['saleFk'] = sales[x]['saleFk'];
sale['itemFk'] = sales[x]['itemFk'];
sale['quantity'] = sales[x]['quantity'];
if (sales[x]['quantityPicked'] != null)
sale['quantityPicked'] = sales[x]['quantityPicked'];
else
sale['quantityPicked'] = 0;
sale['longName'] = sales[x]['longName'];
sale['size'] = sales[x]['size'];
sale['color'] = sales[x]['color'];
sale['discount'] = sales[x]['discount'];
sale['price'] = sales[x]['price'];
sale['stems'] = sales[x]['stems'];
sale['category'] = sales[x]['category'];
sale['origin'] = sales[x]['origin'];
sale['clientFk'] = sales[x]['clientFk'];
sale['productor'] = sales[x]['productor'];
sale['reserved'] = sales[x]['reserved'];
sale['isPreviousPrepared'] = sales[x]['isPreviousPrepared'];
sale['isPrepared'] = sales[x]['isPrepared'];
sale['isControlled'] = sales[x]['isControlled'];
let salePlacements = [];
for (let z = 0; z < placements.length; z++) {
if (placements[z]['saleFk'] == sale['saleFk']) {
let placement = {};
placement['saleFk'] = placements[z]['saleFk'];
placement['itemFk'] = placements[z]['itemFk'];
placement['placement'] = placements[z]['placement'];
placement['shelving'] = placements[z]['shelving'];
placement['created'] = placements[z]['created'];
placement['visible'] = placements[z]['visible'];
placement['order'] = placements[z]['order'];
placement['grouping'] = placements[z]['grouping'];
salePlacements.push(placement);
}
}
sale['placements'] = salePlacements;
ticketSales.push(sale);
}
}
ticket['sales'] = ticketSales;
collection.push(ticket);
}
return collection;
}
};

View File

@ -0,0 +1,9 @@
const app = require('vn-loopback/server/server');
describe('collectionFaults()', () => {
it('return shelving afected', async() => {
let response = await app.models.Collection.collectionFaults('UXN', 0, 1);
expect(response.length).toBeGreaterThan(0);
expect(response[0][0].shelvingFk).toEqual('UXN');
});
});

View File

@ -0,0 +1,11 @@
const app = require('vn-loopback/server/server');
describe('getCollection()', () => {
it('return list of collection', async() => {
let ctx = {req: {accessToken: {userId: 106}}};
let response = await app.models.Collection.getCollection(ctx);
expect(response.length).toBeGreaterThan(0);
expect(response[0].collectionFk).toEqual(1);
});
});

View File

@ -0,0 +1,11 @@
const app = require('vn-loopback/server/server');
describe('getSectors()', () => {
it('return list of sectors', async() => {
let response = await app.models.Collection.getSectors();
expect(response.length).toBeGreaterThan(0);
expect(response[0].id).toEqual(1);
expect(response[0].description).toEqual('First sector');
});
});

View File

@ -0,0 +1,11 @@
const app = require('vn-loopback/server/server');
describe('newCollection()', () => {
it('return a new collection', async() => {
let ctx = {req: {accessToken: {userId: 106}}};
let response = await app.models.Collection.newCollection(ctx, 1, 1, 1);
expect(response.length).toBeGreaterThan(0);
expect(response[0].ticketFk).toEqual(1);
});
});

View File

@ -0,0 +1,12 @@
const app = require('vn-loopback/server/server');
describe('updateCollectionSale()', () => {
it('return a new collection', async() => {
let ctx = {req: {accessToken: {userId: 106}}};
let response = await app.models.Collection.updateCollectionSale(ctx, 1, 5, 5, 5, 1, 4, false, 'UXN', 1, 1);
expect(response.length).toBeGreaterThan(0);
expect(response[0][0].id).toEqual(1);
expect(response[0][0].quantity).toEqual(5);
});
});

View File

@ -0,0 +1,89 @@
module.exports = Self => {
Self.remoteMethodCtx('updateCollectionSale', {
description: 'Update sale of a collection',
accessType: 'WRITE',
accepts: [{
arg: 'sale',
type: 'Number',
required: true,
description: 'The sale id'
}, {
arg: 'originalQuantity',
type: 'Number',
required: true,
description: 'The quantity to sale'
},
{
arg: 'quantity',
type: 'Number',
required: true,
description: 'The quantity to picked'
},
{
arg: 'quantityPicked',
type: 'Number',
required: true,
description: 'The quantity to picked'
}, {
arg: 'ticketFk',
type: 'Number',
required: true,
description: 'The ticket id'
}, {
arg: 'stateFk',
type: 'Number',
required: true,
description: 'The state id'
}, {
arg: 'isNicho',
type: 'Boolean',
required: true,
description: 'Determine if sale is picked from nicho or not'
}, {
arg: 'shelvingFk',
type: 'String',
required: false,
description: 'The shelving id'
}, {
arg: 'itemFk',
type: 'Number',
required: true,
description: 'The item id'
}, {
arg: 'sectorFk',
type: 'Number',
required: true,
description: 'The sector id'
}],
returns: {
type: 'Object',
root: true
},
http: {
path: `/updateCollectionSale`,
verb: 'POST'
}
});
Self.updateCollectionSale = async(ctx, sale, originalQuantity, quantity, quantityPicked, ticketFk, stateFk, isNicho, shelvingFk, itemFk, sectorFk) => {
const userId = ctx.req.accessToken.userId;
if (originalQuantity == quantity) {
query = `CALL vn.collection_updateSale(?,?,?,?,?)`;
await Self.rawSql(query, [sale, originalQuantity, userId, stateFk, ticketFk]);
}
if (!isNicho) {
query = `CALL vn.collection_faults(?,?,?)`;
await Self.rawSql(query, [shelvingFk, quantityPicked, itemFk]);
} else {
query = `CALL vn.sector_getWarehouse(?)`;
const [result] = await Self.rawSql(query, [sectorFk]);
query = `CALL vn.itemPlacementSave(?,?,?)`;
await Self.rawSql(query, [shelvingFk, quantityPicked, result[0]['warehouseFk']]);
}
query = `CALL vn.sale_updateOriginalQuantity(?,?)`;
return await Self.rawSql(query, [sale, quantity]);
};
};

View File

@ -14,6 +14,9 @@
"Container": {
"dataSource": "storage"
},
"Collection": {
"dataSource": "vn"
},
"Chat": {
"dataSource": "vn"
},

View File

@ -0,0 +1,7 @@
module.exports = Self => {
require('../methods/collection/getCollection')(Self);
require('../methods/collection/newCollection')(Self);
require('../methods/collection/getSectors')(Self);
require('../methods/collection/updateCollectionSale')(Self);
require('../methods/collection/collectionFaults')(Self);
};

View File

@ -0,0 +1,12 @@
{
"name": "Collection",
"base": "VnModel",
"acls": [{
"property": "validations",
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}]
}

View File

@ -0,0 +1,108 @@
DROP procedure IF EXISTS `vn`.`collectionPlacement_get`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`collectionPlacement_get`(vCollectionFk INT)
BEGIN
DECLARE vCalcFk INT;
DECLARE vWarehouseFk INT;
DECLARE vWarehouseAliasFk INT;
SELECT t.warehouseFk, w.aliasFk
INTO vWarehouseFk, vWarehouseAliasFk
FROM vn.ticket t
JOIN vn.ticketCollection tc ON tc.ticketFk = t.id
JOIN vn.warehouse w ON w.id = t.warehouseFk
WHERE tc.collectionFk = vCollectionFk
LIMIT 1;
CALL cache.visible_refresh(vCalcFk,FALSE,vWarehouseFk);
DROP TEMPORARY TABLE IF EXISTS tmp.parked;
CREATE TEMPORARY TABLE tmp.parked
ENGINE MEMORY
SELECT s.itemFk, 0 as quantity
FROM vn.ticketCollection tc
JOIN vn.sale s ON s.ticketFk = tc.ticketFk
WHERE tc.collectionFk = vCollectionFk;
UPDATE tmp.parked pk
JOIN ( SELECT itemFk, sum(visible) as visible
FROM vn.itemShelvingStock iss
JOIN vn.warehouse w ON w.id = iss.warehouseFk
WHERE w.aliasFk = vWarehouseAliasFk
GROUP BY iss.itemFk ) iss ON iss.itemFk = pk.itemFk
SET pk.quantity = iss.visible;
DROP TEMPORARY TABLE IF EXISTS tmp.`grouping`;
CREATE TEMPORARY TABLE tmp.`grouping`
ENGINE MEMORY
SELECT itemFk, `grouping`
FROM (
SELECT itemFk,
CASE groupingMode
WHEN 0 THEN 1
WHEN 2 THEN packing
ELSE `grouping`
END AS `grouping`
FROM buy b
JOIN entry e ON e.id = b.entryFk
JOIN travel tr ON tr.id = e.travelFk
WHERE tr.warehouseInFk = vWarehouseFk
AND landed BETWEEN (SELECT inventoried FROM vn.config LIMIT 1) AND CURDATE()
AND b.isIgnored = FALSE
ORDER BY tr.landed DESC
) sub
GROUP BY sub.itemFk ;
DROP TEMPORARY TABLE IF EXISTS tmp.grouping2;
CREATE TEMPORARY TABLE tmp.grouping2
ENGINE MEMORY
SELECT * FROM tmp.`grouping`;
SELECT s.id as saleFk, s.itemFk,
p.code COLLATE utf8_general_ci as placement ,
sh.code COLLATE utf8_general_ci as shelving,
ish.created,
ish.visible,
0 as `order`,
IF(sc.isPreviousPreparedByPacking, ish.packing, g.`grouping`) as `grouping`
FROM vn.ticketCollection tc
JOIN vn.sale s ON s.ticketFk = tc.ticketFk
JOIN vn.itemShelving ish ON ish.itemFk = s.itemFk
JOIN vn.shelving sh ON sh.code = ish.shelvingFk
JOIN vn.parking p ON p.id = sh.parkingFk
JOIN vn.sector sc ON sc.id = p.sectorFk
JOIN vn.warehouse w ON w.id = sc.warehouseFk
JOIN tmp.`grouping` g ON g.itemFk = s.itemFk
WHERE tc.collectionFk = vCollectionFk
AND w.aliasFk = vWarehouseAliasFk
AND ish.visible > 0
UNION ALL
SELECT s.id as saleFk, s.itemFk,
ip.code COLLATE utf8_general_ci as placement,
'' COLLATE latin1_general_ci as shelving,
modificationDate as created,
v.visible - p.quantity as visible,
0 as `order`,
g.`grouping`
FROM vn.ticketCollection tc
JOIN vn.sale s ON s.ticketFk = tc.ticketFk
JOIN vn.itemPlacement ip ON ip.itemFk = s.itemFk AND ip.warehouseFk = vWarehouseFk
JOIN tmp.parked p ON p.itemFk = s.itemFk
JOIN cache.visible v ON v.item_id = s.itemFk AND v.calc_id = vCalcFk
LEFT JOIN tmp.grouping2 g ON g.itemFk = s.itemFk
WHERE tc.collectionFk = vCollectionFk
AND v.visible - p.quantity > 0;
DROP TEMPORARY TABLE
tmp.parked,
tmp.`grouping`,
tmp.grouping2;
END
$$
DELIMITER ;

View File

@ -0,0 +1,39 @@
DROP procedure IF EXISTS `vn`.`collection_faults`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`collection_faults`(
vShelvingFk VARCHAR(10),
vQuantity INT,
vItemFk INT)
BEGIN
DECLARE vQuantityTotal INT DEFAULT 0;
DECLARE vshelve VARCHAR(2);
DECLARE vdeep INT(11);
DECLARE vpriority INT(11);
DECLARE vgrouping SMALLINT(5);
DECLARE vpacking INT(11);
DECLARE vpackagingFk VARCHAR(10);
DECLARE vlevel VARCHAR(45);
DECLARE vuserFk INT(10);
SELECT SUM(quantity),shelve,deep,priority,`grouping`,packing,packagingFk,`level`,userFk
INTO vQuantityTotal,vshelve,vdeep,vpriority,vgrouping,vpacking,vpackagingFk,vlevel,vuserFk
FROM vn.itemShelving
WHERE shelvingFk = vShelvingFk COLLATE utf8mb4_unicode_ci AND itemFk = vItemFk
GROUP BY itemFk;
SELECT vQuantityTotal - vQuantity INTO vQuantityTotal;
DELETE FROM vn.itemShelving WHERE shelvingFk = vShelvingFk COLLATE utf8mb4_unicode_ci AND itemFk = vItemFk;
INSERT INTO vn.itemShelving (itemFk, shelvingFk,shelve,deep,quantity,visible,available,priority,`grouping`,packing,packagingFk,`level`,userFk )
VALUES (vItemFk,vShelvingFk,vshelve,vdeep,vQuantityTotal,vQuantityTotal,vQuantityTotal,vpriority,vgrouping,vpacking,vpackagingFk,vlevel,vuserFk );
SELECT * FROM vn.itemShelving
WHERE shelvingFk = vShelvingFk COLLATE utf8mb4_unicode_ci AND itemFk = vItemFk;
END$$
DELIMITER ;

View File

@ -0,0 +1,42 @@
DROP procedure IF EXISTS `vn`.`collection_updateSale`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`collection_updateSale`(
vSaleFk INT,
vOriginalQuantity INT,
vWorkerFk INT,
vStateFk INT,
vTicketFk INT)
BEGIN
DECLARE vNumPrepared INT;
DECLARE vNumTotal INT;
REPLACE INTO vn.saleTracking(saleFk,isChecked, originalQuantity, workerFk, actionFk,stateFk)
VALUES(vSaleFk,1,vOriginalQuantity,vWorkerFk,vStateFk,vStateFk);
UPDATE vn.sale SET isPicked = 1
WHERE id = vSaleFk;
SELECT COUNT(s.id) INTO vNumPrepared
FROM vn.sale s
WHERE s.ticketFk = vTicketFk AND s.isPicked = 1;
SELECT COUNT(s.id) INTO vNumTotal
FROM vn.sale s
WHERE s.ticketFk = vTicketFk;
IF vNumPrepared = vNumTotal THEN
INSERT INTO vncontrol.inter
SET state_id = vStateFk, Id_Ticket = vTicketFk, Id_Trabajador = vWorkerFk;
CALL vn.collection_update(vTicketFk);
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,13 @@
/*DROP view IF EXISTS `vn`.`coolerPathDetail`;
CREATE
ALGORITHM = UNDEFINED
DEFINER = `root`@`%`
SQL SECURITY DEFINER
VIEW `vn`.`coolerPathDetail` AS
SELECT
`c`.`cooler_path_detail_id` AS `id`,
`c`.`cooler_path_id` AS `coolerPathFk`,
`c`.`pasillo` AS `hallway`
FROM
`vn2008`.`cooler_path_detail` `c`*/

View File

@ -0,0 +1,15 @@
DROP procedure IF EXISTS `vn`.`sale_updateOriginalQuantity`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`sale_updateOriginalQuantity`(vSale INT, vQuantity INT)
proc: BEGIN
UPDATE vn.sale SET originalQuantity = vQuantity
WHERE id = vSale;
SELECT * FROM vn.sale WHERE id = vSale;
END$$
DELIMITER ;

View File

@ -0,0 +1,14 @@
DROP procedure IF EXISTS `vn`.`sector_getWarehouse`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`sector_getWarehouse`(vSectorFk INT)
BEGIN
SELECT s.warehouseFk
FROM vn.sector s
WHERE s.id = vSectorFk;
END$$
DELIMITER ;

View File

@ -21,7 +21,7 @@ INSERT INTO `vn`.`bionicConfig` (`generalInflationCoeficient`, `minimumDensityVo
(1.30, 167.00, 138000, 71);
INSERT INTO `vn`.`chatConfig` (`host`, `api`)
VALUES
VALUES
('https://chat.verdnatura.es', 'https://chat.verdnatura.es/api/v1');
INSERT IGNORE INTO `vn`.`greugeConfig`(`id`, `freightPickUpPrice`)
@ -980,6 +980,29 @@ INSERT INTO `vn`.`itemPlacement`(`id`, `itemFk`, `warehouseFk`, `code`)
(3, 1, 3, 'A3'),
(4, 2, 1, 'A4');
INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`)
VALUES
(1, 106, 5),
(2, 106, 14);
INSERT INTO `vn`.`parking` (`column`, `row`, `sectorFk`, `code`, `pickingOrder`)
VALUES
('100', '01', 1, '100-01', 1);
INSERT INTO `vn`.`shelving` (`code`, `parkingFk`, `priority`, `userFk`)
VALUES
('UXN', 1, 1, 106);
INSERT INTO `vn`.`itemShelving` (`itemFk`, `shelvingFk`, `shelve`, `deep`, `quantity`, `visible`, `available`, `grouping`, `packing`, `level`, `userFk`)
VALUES
(1, 'UXN', 'A', 2, 12, 12, 12, 12, 12, 1, 106);
INSERT INTO `vn`.`ticketCollection` (`ticketFk`, `collectionFk`, `level`)
VALUES
(1, 1, 1);
INSERT INTO `edi`.`genus`(`genus_id`, `latin_genus_name`, `entry_date`, `expiry_date`, `change_date_time`)
VALUES
(1, 'Abelia' , CURDATE(), NULL, CURDATE()),

File diff suppressed because it is too large Load Diff

BIN
loopback/.DS_Store vendored Normal file

Binary file not shown.