feat: refs #7301 add inventory-config and acl #3230

Open
pablone wants to merge 4 commits from 7301-itemLastEntries into dev
18 changed files with 296 additions and 151 deletions
Showing only changes of commit 2ba931bedb - Show all commits

View File

@ -36,3 +36,7 @@ rules:
jasmine/no-focused-tests: 0 jasmine/no-focused-tests: 0
jasmine/prefer-toHaveBeenCalledWith: 0 jasmine/prefer-toHaveBeenCalledWith: 0
arrow-spacing: ["error", { "before": true, "after": true }] arrow-spacing: ["error", { "before": true, "after": true }]
no-restricted-syntax:
- "error"
- selector: "NewExpression[callee.name='Date']"
message: "Use Date.vnNew() instead of new Date()."

View File

@ -28,9 +28,10 @@ describe('ticket assign()', () => {
await tx.rollback(); await tx.rollback();
}); });
it('should throw an error when there is not picking tickets', async() => { it('should throw an error when there are no picking tickets', async() => {
try { try {
await models.Collection.assign(ctx, options); await models.Collection.assign(ctx, options);
fail('Expected an error to be thrown, but none was thrown.');
} catch (e) { } catch (e) {
expect(e.message).toEqual('There are not picking tickets'); expect(e.message).toEqual('There are not picking tickets');
} }

View File

@ -1518,20 +1518,20 @@ INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseO
(11, util.VN_CURDATE() - INTERVAL 1 DAY , util.VN_CURDATE(), 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4, FALSE, NULL), (11, util.VN_CURDATE() - INTERVAL 1 DAY , util.VN_CURDATE(), 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4, FALSE, NULL),
(12, util.VN_CURDATE() , util.VN_CURDATE() + INTERVAL 1 DAY, 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4, FALSE, NULL); (12, util.VN_CURDATE() , util.VN_CURDATE() + INTERVAL 1 DAY, 6, 3, 0, 50.00, 500, 'eleventh travel', 1, 2, 4, FALSE, NULL);
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `evaNotes`) INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `evaNotes`, `typeFk`)
VALUES VALUES
(1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 1', 0, ''), (1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 1', 0, '', 'packaging'),
(2, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 442, 'IN2002', 'Movement 2', 0, 'observation two'), (2, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 442, 'IN2002', 'Movement 2', 0, 'observation two' , 'product'),
(3, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 0, 442, 'IN2003', 'Movement 3', 0, 'observation three'), (3, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 0, 442, 'IN2003', 'Movement 3', 0, 'observation three', 'product'),
(4, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 69, 'IN2004', 'Movement 4', 0, 'observation four'), (4, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 2, 0, 69, 'IN2004', 'Movement 4', 0, 'observation four' , 'product'),
(5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 'observation five'), (5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 'observation five' , 'product'),
(6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 'observation six'), (6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 'observation six' , 'product'),
(7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 'observation seven'), (7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 'observation seven', 'product'),
(8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1,''), (8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1, '', 'product'),
(9, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, ''), (9, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, '', 'product'),
(10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 10', 1, ''), (10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 10',1, '', 'product'),
(11, 4, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 1', 0, ''), (11, 4, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 1, 442, 'IN2001', 'Movement 11',0, '', 'product'),
(99, 69, '2000-12-01 00:00:00.000', 11, 0, 442, 'IN2009', 'Movement 99', 0, ''); (99, 69, util.VN_CURDATE() - INTERVAL 1 MONTH, 11, 0, 442, 'IN2009', 'Movement 99',0, '', 'product');
INSERT INTO `vn`.`entryConfig` (`defaultEntry`, `inventorySupplierFk`, `defaultSupplierFk`) INSERT INTO `vn`.`entryConfig` (`defaultEntry`, `inventorySupplierFk`, `defaultSupplierFk`)
VALUES (2, 4, 1); VALUES (2, 4, 1);
@ -4026,7 +4026,6 @@ INSERT INTO srt.buffer (id, x, y, `size`, `length`, stateFk, typeFk, isActive, c
(9, 1400, 1500, 500, 13000, 1, 1, 1, '04B', 4, 0, NULL, NULL, NULL, NULL, 0, 1, 1, NULL), (9, 1400, 1500, 500, 13000, 1, 1, 1, '04B', 4, 0, NULL, NULL, NULL, NULL, 0, 1, 1, NULL),
(10, 0, 2000, 500, 13000, 1, 1, 1, '05A', 5, 0, NULL, NULL, NULL, NULL, 0, 1, 1, NULL); (10, 0, 2000, 500, 13000, 1, 1, 1, '05A', 5, 0, NULL, NULL, NULL, NULL, 0, 1, 1, NULL);
INSERT IGNORE INTO vn.saySimpleCountry (countryFk, channel) INSERT IGNORE INTO vn.saySimpleCountry (countryFk, channel)
VALUES (19, '1169'), VALUES (19, '1169'),
(8, '1183'); (8, '1183');
@ -4034,9 +4033,8 @@ INSERT IGNORE INTO vn.saySimpleCountry (countryFk, channel)
INSERT IGNORE INTO vn.saySimpleConfig (url, defaultChannel) INSERT IGNORE INTO vn.saySimpleConfig (url, defaultChannel)
VALUES ('saysimle-url-mock', 1320); VALUES ('saysimle-url-mock', 1320);
INSERT INTO vn.workerIrpf (workerFk,spouseNif,geographicMobilityDate) INSERT INTO vn.workerIrpf (workerFk,spouseNif, geographicMobilityDate)
VALUES VALUES (1106,'26493101E','2019-09-20');
(1106,'26493101E','2019-09-20');
INSERT IGNORE INTO vn.inventoryConfig INSERT IGNORE INTO vn.inventoryConfig

View File

@ -9,16 +9,18 @@ BEGIN
* *
* @param vSelf Id de entrada * @param vSelf Id de entrada
*/ */
DECLARE vIsEditable BOOL; DECLARE vIsNotEditable BOOL DEFAULT FALSE;
SELECT e.isBooked INTO vIsEditable SELECT TRUE INTO vIsNotEditable
FROM `entry` e FROM `entry` e
JOIN entryType et ON et.code = e.typeFk LEFT JOIN entryType et ON et.code = e.typeFk
WHERE NOT et.isInformal WHERE e.id = vSelf
AND e.id = vSelf; AND e.isBooked
AND (e.typeFk IS NULL OR NOT et.isInformal);
IF vIsEditable AND NOT IFNULL(@isModeInventory, FALSE) THEN IF vIsNotEditable AND NOT IFNULL(@isModeInventory, FALSE) THEN
CALL util.throw(CONCAT('Entry ', vSelf, ' is not editable')); CALL util.throw(CONCAT('Entry ', vSelf, ' is not editable'));
END IF; END IF;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -22,7 +22,7 @@ BEGIN
ic.url, ic.url,
ish.available, ish.available,
ish.buyFk, ish.buyFk,
sh.shelvingFk ish.shelvingFk
FROM itemShelving ish FROM itemShelving ish
JOIN item i ON i.id = ish.itemFk JOIN item i ON i.id = ish.itemFk
JOIN shelving s ON s.id = ish.shelvingFk JOIN shelving s ON s.id = ish.shelvingFk

View File

@ -5,122 +5,122 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_splitItemPacki
) )
BEGIN BEGIN
/** /**
* Clona y reparte las ventas de un ticket en funcion del tipo de empaquetado. * Separa en diferentes tickets según el tipo de empaquetado
* Respeta el id inicial para el tipo propuesto. * El ticket original conserva las líneas del tipo de empaquetado especificado
* Las líneas sin tipo de empaquetado se asignan al ticket del tipo por defecto.
* *
* @param vSelf Id ticket * @param vSelf Id del ticket original
* @param vOriginalItemPackingTypeFk Tipo para el que se reserva el número de ticket original * @param vOriginalItemPackingTypeFk Tipo de empaquetado a mantener en el ticket original
* @return table tmp.ticketIPT(ticketFk, itemPackingTypeFk) * @return table tmp.ticketIPT(ticketFk, itemPackingTypeFk)
*/ */
DECLARE vItemPackingTypeFk VARCHAR(1) DEFAULT 'H'; DECLARE vIsDone BOOLEAN DEFAULT FALSE;
DECLARE vCurrentPackingType VARCHAR(1);
DECLARE vDefaultPackingType VARCHAR(1);
DECLARE vHasOriginalPackingType BOOLEAN;
DECLARE vNewTicketFk INT; DECLARE vNewTicketFk INT;
DECLARE vPackingTypesToSplit INT; DECLARE vTicketFk INT;
DECLARE vDone INT DEFAULT FALSE;
DECLARE vSaleGroup CURSOR FOR DECLARE vItemPackingTypes CURSOR FOR
SELECT itemPackingTypeFk SELECT DISTINCT itemPackingTypeFk FROM tSalesToMove;
FROM tSaleGroup
WHERE itemPackingTypeFk IS NOT NULL
ORDER BY (itemPackingTypeFk = vOriginalItemPackingTypeFk) DESC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; DECLARE CONTINUE HANDLER FOR NOT FOUND SET vIsDone = TRUE;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
CREATE OR REPLACE TEMPORARY TABLE tSalesToMove (
ticketFk INT,
saleFk INT,
itemPackingTypeFk VARCHAR(1)
) ENGINE=MEMORY;
SELECT COALESCE(MAX(ic.defaultPackingTypeFk), MAX(i.itemPackingTypeFk)) INTO vDefaultPackingType
FROM vn.sale s
JOIN item i ON i.id = s.itemFk
LEFT JOIN itemConfig ic ON ic.defaultPackingTypeFk = i.itemPackingTypeFk
WHERE s.ticketFk = vSelf
GROUP BY s.ticketFk;
SELECT EXISTS (
SELECT TRUE
FROM sale s
JOIN item i ON i.id = s.itemFk
WHERE s.ticketFk = vSelf
AND i.itemPackingTypeFk = vOriginalItemPackingTypeFk
) INTO vHasOriginalPackingType;
IF vOriginalItemPackingTypeFk IS NULL OR NOT vHasOriginalPackingType THEN
SET vOriginalItemPackingTypeFk = vDefaultPackingType;
END IF;
START TRANSACTION; START TRANSACTION;
SELECT id SELECT t.id INTO vTicketFk
FROM sale FROM ticket t
WHERE ticketFk = vSelf JOIN sale s ON s.id = t.id
AND NOT quantity WHERE t.id = vSelf
FOR UPDATE; FOR UPDATE;
DELETE FROM sale INSERT INTO tSalesToMove (saleFk, itemPackingTypeFk)
WHERE NOT quantity SELECT s.id, i.itemPackingTypeFk
AND ticketFk = vSelf;
CREATE OR REPLACE TEMPORARY TABLE tSale
(PRIMARY KEY (id))
ENGINE = MEMORY
SELECT s.id, i.itemPackingTypeFk, IFNULL(sv.litros, 0) litros
FROM sale s FROM sale s
JOIN item i ON i.id = s.itemFk JOIN item i ON i.id = s.itemFk
LEFT JOIN saleVolume sv ON sv.saleFk = s.id WHERE s.ticketFk = vSelf
WHERE s.ticketFk = vSelf; AND i.itemPackingTypeFk <> vOriginalItemPackingTypeFk;
CREATE OR REPLACE TEMPORARY TABLE tSaleGroup
ENGINE = MEMORY
SELECT itemPackingTypeFk, SUM(litros) totalLitros
FROM tSale
GROUP BY itemPackingTypeFk;
SELECT COUNT(*) INTO vPackingTypesToSplit
FROM tSaleGroup
WHERE itemPackingTypeFk IS NOT NULL;
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketIPT(
ticketFk INT,
itemPackingTypeFk VARCHAR(1)
) ENGINE = MEMORY;
CASE vPackingTypesToSplit
WHEN 0 THEN
INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk)
VALUES(vSelf, vItemPackingTypeFk);
WHEN 1 THEN
INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk)
SELECT vSelf, itemPackingTypeFk
FROM tSaleGroup
WHERE itemPackingTypeFk IS NOT NULL;
ELSE
OPEN vSaleGroup;
FETCH vSaleGroup INTO vItemPackingTypeFk;
INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk)
VALUES(vSelf, vItemPackingTypeFk);
OPEN vItemPackingTypes;
l: LOOP l: LOOP
SET vDone = FALSE; SET vIsDone = FALSE;
FETCH vSaleGroup INTO vItemPackingTypeFk; FETCH vItemPackingTypes INTO vCurrentPackingType;
IF vDone THEN IF vIsDone THEN
LEAVE l; LEAVE l;
END IF; END IF;
CALL ticket_Clone(vSelf, vNewTicketFk); CALL ticket_Clone(vSelf, vNewTicketFk);
INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk) SELECT id INTO vTicketFk
VALUES(vNewTicketFk, vItemPackingTypeFk); FROM ticket t
END LOOP; WHERE t.id = vNewTicketFk
CLOSE vSaleGroup;
SELECT s.id
FROM sale s
JOIN tSale ts ON ts.id = s.id
JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = ts.itemPackingTypeFk
FOR UPDATE; FOR UPDATE;
UPDATE tSalesToMove
SET ticketFk = vNewTicketFk
WHERE itemPackingTypeFk = vCurrentPackingType;
IF vCurrentPackingType = vDefaultPackingType THEN
INSERT INTO tSalesToMove (ticketFk, saleFk, itemPackingTypeFk)
SELECT vNewTicketFk, s.id, i.itemPackingTypeFk
FROM sale s
JOIN item i ON i.id = s.itemFk
WHERE s.ticketFk = vSelf
AND i.itemPackingTypeFk IS NULL;
END IF;
END LOOP;
CLOSE vItemPackingTypes;
UPDATE sale s UPDATE sale s
JOIN tSale ts ON ts.id = s.id JOIN tSalesToMove t ON t.saleFk = s.id
JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = ts.itemPackingTypeFk
SET s.ticketFk = t.ticketFk; SET s.ticketFk = t.ticketFk;
SELECT itemPackingTypeFk INTO vItemPackingTypeFk CREATE OR REPLACE TEMPORARY TABLE tmp.ticketIPT
FROM tSaleGroup sg ENGINE=MEMORY
WHERE sg.itemPackingTypeFk IS NOT NULL SELECT s.ticketFk, MAX(i.itemPackingTypeFk) itemPackingTypeFk
ORDER BY sg.itemPackingTypeFk FROM sale s
LIMIT 1; JOIN item i ON i.id = s.itemFk
WHERE s.ticketFk = vSelf
UPDATE sale s GROUP BY s.ticketFk
JOIN tSale ts ON ts.id = s.id UNION
JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = vItemPackingTypeFk SELECT ticketFk, MAX(itemPackingTypeFk)
SET s.ticketFk = t.ticketFk FROM tSalesToMove
WHERE ts.itemPackingTypeFk IS NULL; GROUP BY ticketFk;
END CASE;
COMMIT; COMMIT;
DROP TEMPORARY TABLE DROP TEMPORARY TABLE tSalesToMove;
tSale,
tSaleGroup;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -38,10 +38,10 @@ BEGIN
CALL travel_throwAwb(NEW.travelFk); CALL travel_throwAwb(NEW.travelFk);
END IF; END IF;
SELECT isRaid INTO vIsRaid SELECT t.isRaid INTO vIsRaid
FROM travel t FROM travel t
JOIN entry e ON e.travelFk = t.id JOIN entry e ON e.travelFk = t.id
WHERE entryFk = NEW.id; WHERE e.id = NEW.id;
SELECT NOT (o.warehouseInFk <=> n.warehouseInFk) SELECT NOT (o.warehouseInFk <=> n.warehouseInFk)
OR NOT (o.warehouseOutFk <=> n.warehouseOutFk) OR NOT (o.warehouseOutFk <=> n.warehouseOutFk)

View File

@ -0,0 +1,40 @@
-- Eliminar registros existentes donde property = '*'
DELETE FROM `salix`.ACL WHERE model = 'entry' AND property = '*';
-- Insertar permisos para los métodos solicitados en el modelo Entry
INSERT INTO `salix`.ACL (model, property, accessType, permission, principalType, principalId)
VALUES
-- Permisos para administrative
('Entry', 'upsert', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'isBooked', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'findById', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'find', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'filter', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'count', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'getEntry', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'getBuys', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'findOne', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'deleteBuys', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'editLatestBuys', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'importBuys', 'WRITE', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'importBuysPreview', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'lastItemBuys', 'READ', 'ALLOW', 'ROLE', 'administrative'),
('Entry', 'latestBuysFilter', 'READ', 'ALLOW', 'ROLE', 'administrative'),
-- Permisos para buyer (excluyendo isBooked)
('Entry', 'upsert', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'findById', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'find', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'filter', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'count', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'getEntry', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'getBuys', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'findOne', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'deleteBuys', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'editLatestBuys', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'importBuys', 'WRITE', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'importBuysPreview', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'lastItemBuys', 'READ', 'ALLOW', 'ROLE', 'buyer'),
('Entry', 'latestBuysFilter', 'READ', 'ALLOW', 'ROLE', 'buyer');

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.itemConfig ADD defaultPackingTypeFk VARCHAR(1) DEFAULT 'H' NULL;

View File

@ -0,0 +1,4 @@
ALTER TABLE vn.travel ADD IF NOT EXISTS isRaid tinyint(1) DEFAULT 0 NOT NULL COMMENT 'Redada';
ALTER TABLE vn.travel MODIFY COLUMN daysInForward int(10) unsigned DEFAULT NULL
COMMENT 'Cuando es una redada, indica el número de días que se añadirán a la fecha de hoy para establecer el landed. NULL si no es una redada';

View File

@ -240,11 +240,11 @@
"The height must be greater than 50cm": "The height must be greater than 50cm", "The height must be greater than 50cm": "The height must be greater than 50cm",
"The maximum height of the wagon is 200cm": "The maximum height of the wagon is 200cm", "The maximum height of the wagon is 200cm": "The maximum height of the wagon is 200cm",
"The quantity claimed cannot be greater than the quantity of the line": "The quantity claimed cannot be greater than the quantity of the line", "The quantity claimed cannot be greater than the quantity of the line": "The quantity claimed cannot be greater than the quantity of the line",
"Invalid or expired verification code": "Invalid or expired verification code",
"There are tickets for this area, delete them first": "There are tickets for this area, delete them first", "There are tickets for this area, delete them first": "There are tickets for this area, delete them first",
"ticketLostExpedition": "The ticket [{{ticketId}}]({{{ticketUrl}}}) has the following lost expedition:{{ expeditionId }}",
"Payment method is required": "Payment method is required", "Payment method is required": "Payment method is required",
"You do not have permission to modify the booked field": "You do not have permission to modify the booked field",
"Invalid or expired verification code": "Invalid or expired verification code",
"ticketLostExpedition": "The ticket [{{ticketId}}]({{{ticketUrl}}}) has the following lost expedition:{{ expeditionId }}",
"The raid information is not correct": "The raid information is not correct", "The raid information is not correct": "The raid information is not correct",
"Sales already moved": "Sales already moved" "Sales already moved": "Sales already moved"
} }

View File

@ -385,6 +385,7 @@
"type cannot be blank": "Se debe rellenar el tipo", "type cannot be blank": "Se debe rellenar el tipo",
"There are tickets for this area, delete them first": "Hay tickets para esta sección, borralos primero", "There are tickets for this area, delete them first": "Hay tickets para esta sección, borralos primero",
"There is no company associated with that warehouse": "No hay ninguna empresa asociada a ese almacén", "There is no company associated with that warehouse": "No hay ninguna empresa asociada a ese almacén",
"You do not have permission to modify the booked field": "No tienes permisos para modificar el campo contabilizada",
"ticketLostExpedition": "El ticket [{{ticketId}}]({{{ticketUrl}}}) tiene la siguiente expedición perdida:{{ expeditionId }}", "ticketLostExpedition": "El ticket [{{ticketId}}]({{{ticketUrl}}}) tiene la siguiente expedición perdida:{{ expeditionId }}",
"The web user's email already exists": "El correo del usuario web ya existe", "The web user's email already exists": "El correo del usuario web ya existe",
"Sales already moved": "Ya han sido transferidas", "Sales already moved": "Ya han sido transferidas",

View File

@ -364,6 +364,7 @@
"Cannot send mail": "Impossible d'envoyer le mail", "Cannot send mail": "Impossible d'envoyer le mail",
"Original invoice not found": "Facture originale introuvable", "Original invoice not found": "Facture originale introuvable",
"The quantity claimed cannot be greater than the quantity of the line": "Le montant réclamé ne peut pas être supérieur au montant de la ligne", "The quantity claimed cannot be greater than the quantity of the line": "Le montant réclamé ne peut pas être supérieur au montant de la ligne",
"You do not have permission to modify the booked field": "Vous n'avez pas la permission de modifier le champ comptabilisé",
"ticketLostExpedition": "Le ticket [{{ticketId}}]({{{ticketUrl}}}) a l'expédition perdue suivante : {{expeditionId}}", "ticketLostExpedition": "Le ticket [{{ticketId}}]({{{ticketUrl}}}) a l'expédition perdue suivante : {{expeditionId}}",
"The web user's email already exists": "L'email de l'internaute existe déjà" "The web user's email already exists": "L'email de l'internaute existe déjà"
} }

View File

@ -1,3 +1,4 @@
const UserError = require('vn-loopback/util/user-error');
const LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
module.exports = Self => { module.exports = Self => {
require('../methods/entry/filter')(Self); require('../methods/entry/filter')(Self);
@ -18,11 +19,20 @@ module.exports = Self => {
const changes = ctx.data || ctx.instance; const changes = ctx.data || ctx.instance;
const orgData = ctx.currentInstance; const orgData = ctx.currentInstance;
const loopBackContext = LoopBackContext.getCurrentContext();
const accessToken = {req: loopBackContext.active};
const hasChanges = orgData && changes;
const isBookedChanged = changes.isBooked !== undefined && orgData.isBooked !== changes.isBooked;
if (isBookedChanged) {
const canEditIsBooked = await Self.app.models.ACL.checkAccessAcl(accessToken, 'Entry', 'isBooked', 'READ');
if (!canEditIsBooked)
throw new UserError('You do not have permission to modify the booked field');
}
const observation = changes.observation || orgData.observation; const observation = changes.observation || orgData.observation;
const hasChanges = orgData && changes; const observationChanged = hasChanges && orgData.observation != observation;
const observationChanged = hasChanges
&& orgData.observation != observation;
if (observationChanged) { if (observationChanged) {
let tx; let tx;
@ -37,8 +47,7 @@ module.exports = Self => {
} }
try { try {
const loopbackContext = LoopBackContext.getCurrentContext(); const userId = loopBackContext.active.accessToken.userId;
const userId = loopbackContext.active.accessToken.userId;
const id = changes.id || orgData.id; const id = changes.id || orgData.id;
const entry = await Self.app.models.Entry.findById(id, null, myOptions); const entry = await Self.app.models.Entry.findById(id, null, myOptions);
await entry.updateAttribute('observationEditorFk', userId, myOptions); await entry.updateAttribute('observationEditorFk', userId, myOptions);

View File

@ -0,0 +1,97 @@
const {models} = require('vn-loopback/server/server');
const LoopBackContext = require('loopback-context');
describe('entry_isEditable trigger', () => {
const activeCtx = {
accessToken: {userId: 5},
http: {
req: {
headers: {origin: 'http://localhost'}
}
}
};
const ctx = {req: activeCtx};
const entryId = 1;
let tx;
let options;
let entry;
beforeEach(async() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({active: ctx.req});
tx = await models.Entry.beginTransaction({});
options = {transaction: tx};
entry = await models.Entry.findById(entryId, null, options);
});
afterEach(async() => {
await tx.rollback();
});
async function prepareEntry(isBooked, typeFk) {
let newCreated = Date.vnNew();
await entry.updateAttributes({isBooked, typeFk}, options);
await entry.updateAttributes({dated: newCreated}, options);
}
it('should throw an error when entry is booked and typeFk is null', async() => {
let error;
try {
await prepareEntry(true, null);
} catch (e) {
error = e;
}
expect(error.message).toContain(`Entry ${entryId} is not editable`);
});
it('should throw an error when entry is booked and typeFk is not informal', async() => {
let error;
try {
const type = await models.EntryType.findOne({where: {isInformal: false}}, options);
await prepareEntry(true, type.code);
} catch (e) {
error = e;
}
expect(error.message).toContain(`Entry ${entryId} is not editable`);
});
it('should not throw an error when entry is booked and typeFk is informal', async() => {
let error;
try {
const type = await models.EntryType.findOne({where: {isInformal: true}}, options);
await prepareEntry(true, type.code);
} catch (e) {
error = e;
}
expect(error).toBeUndefined();
});
it('should not throw an error when entry is not booked', async() => {
let error;
try {
const type = await models.EntryType.findOne({}, options);
await prepareEntry(false, type.code);
} catch (e) {
error = e;
}
expect(error).toBeUndefined();
});
it('should not throw an error when @isModeInventory is true', async() => {
let error;
try {
await models.Application.rawSql('SET @isModeInventory = TRUE;', null, options);
await prepareEntry(true, null);
} catch (e) {
error = e;
} finally {
await models.Application.rawSql('SET @isModeInventory = FALSE;', null, options);
}
expect(error).toBeUndefined();
});
});

View File

@ -15,7 +15,7 @@ module.exports = Self => {
Self.getWithPackaging = async options => { Self.getWithPackaging = async options => {
const models = Self.app.models; const models = Self.app.models;
const myOptions = {}; const myOptions = {};
const oneYearAgo = new Date(); const oneYearAgo = Date.vnNew();
oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1); oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
if (typeof options == 'object') if (typeof options == 'object')

View File

@ -1,26 +1,12 @@
const {models} = require('vn-loopback/server/server'); const {models} = require('vn-loopback/server/server');
describe('Supplier getWithPackaging()', () => { describe('Supplier getWithPackaging()', () => {
beforeAll.mockLoopBackContext();
it('should return a list of suppliers with an entry of type packaging', async() => { it('should return a list of suppliers with an entry of type packaging', async() => {
const typeFk = 'packaging';
const tx = await models.Supplier.beginTransaction({}); const tx = await models.Supplier.beginTransaction({});
const myOptions = {transaction: tx}; const myOptions = {transaction: tx};
try { try {
const entry = await models.Entry.findOne(
{
where: {
id: 1
},
myOptions
});
await entry.updateAttributes({
typeFk: typeFk,
created: new Date()
});
const result = await models.Supplier.getWithPackaging(myOptions); const result = await models.Supplier.getWithPackaging(myOptions);
expect(result.length).toEqual(1); expect(result.length).toEqual(1);