Merge branch 'dev' into 2995-supplierAccount-modificaciones
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Javi Gallego 2021-09-08 10:41:26 +02:00
commit 8160912fe7
111 changed files with 7565 additions and 5970 deletions

View File

@ -3,7 +3,7 @@ module.exports = Self => {
description: 'Get pending collections from a worker', description: 'Get pending collections from a worker',
accessType: 'READ', accessType: 'READ',
returns: { returns: {
type: 'Object', type: 'object',
root: true root: true
}, },
http: { http: {

View File

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

View File

@ -6,6 +6,6 @@ describe('newCollection()', () => {
let response = await app.models.Collection.newCollection(ctx, 1, 1, 1); let response = await app.models.Collection.newCollection(ctx, 1, 1, 1);
expect(response.length).toBeGreaterThan(0); expect(response.length).toBeGreaterThan(0);
expect(response[0].ticketFk).toEqual(1); expect(response[0].ticketFk).toEqual(2);
}); });
}); });

View File

@ -65,6 +65,9 @@
"Province": { "Province": {
"dataSource": "vn" "dataSource": "vn"
}, },
"Autonomy": {
"dataSource": "vn"
},
"Payment": { "Payment": {
"dataSource": "vn" "dataSource": "vn"
}, },

View File

@ -22,6 +22,9 @@
}, },
"code": { "code": {
"type": "string" "type": "string"
},
"isAutoConciliated": {
"type": "boolean"
} }
}, },
"acls": [{ "acls": [{

43
back/models/autonomy.json Normal file
View File

@ -0,0 +1,43 @@
{
"name": "Autonomy",
"description": "Autonomies of every country",
"base": "VnModel",
"options": {
"mysql": {
"table": "autonomy"
}
},
"properties": {
"id": {
"type": "Number",
"id": true,
"description": "Identifier"
},
"name": {
"type": "string",
"required": true
}
},
"relations": {
"country": {
"type": "belongsTo",
"model": "Country",
"foreignKey": "countryFk"
}
},
"scopes": {
"location": {
"include": {
"relation": "country"
}
}
},
"acls": [
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
]
}

View File

@ -9,7 +9,7 @@
}, },
"properties": { "properties": {
"id": { "id": {
"type": "Number", "type": "number",
"id": true, "id": true,
"description": "Identifier" "description": "Identifier"
}, },
@ -24,6 +24,11 @@
"model": "Country", "model": "Country",
"foreignKey": "countryFk" "foreignKey": "countryFk"
}, },
"autonomy": {
"type": "belongsTo",
"model": "Autonomy",
"foreignKey": "autonomyFk"
},
"warehouse": { "warehouse": {
"type": "belongsTo", "type": "belongsTo",
"model": "Warehouse", "model": "Warehouse",

View File

@ -0,0 +1,4 @@
DELETE FROM `salix`.`ACL` WHERE id = 48;
DELETE FROM `salix`.`ACL` WHERE id = 49;
DELETE FROM `salix`.`ACL` WHERE id = 50;
DELETE FROM `salix`.`ACL` WHERE id = 107;

View File

@ -0,0 +1,197 @@
drop procedure `vn`.`sale_getProblems`;
DELIMITER $$
$$
create
definer = root@`%` procedure `vn`.`sale_getProblems`(IN vIsTodayRelative tinyint(1))
BEGIN
/**
* Calcula los problemas de cada venta
* para un conjunto de tickets.
*
* @table tmp.sale_getProblems(ticketFk, clientFk, warehouseFk, shipped) Identificadores de los tickets a calcular
* @return tmp.sale_problems
*/
DECLARE vWarehouse INT;
DECLARE vDate DATE;
DECLARE vAvailableCache INT;
DECLARE vDone INT DEFAULT 0;
DECLARE vComponentCount INT;
DECLARE vCursor CURSOR FOR
SELECT DISTINCT tt.warehouseFk, IF(vIsTodayRelative, CURDATE(), date(tt.shipped))
FROM tmp.sale_getProblems tt
WHERE DATE(tt.shipped) BETWEEN CURDATE()
AND TIMESTAMPADD(DAY, IF(vIsTodayRelative, 9.9, 1.9), CURDATE());
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = 1;
DROP TEMPORARY TABLE IF EXISTS tmp.sale_problems;
CREATE TEMPORARY TABLE tmp.sale_problems (
ticketFk INT(11),
saleFk INT(11),
isFreezed INTEGER(1) DEFAULT 0,
risk DECIMAL(10,2) DEFAULT 0,
hasHighRisk TINYINT(1) DEFAULT 0,
hasTicketRequest INTEGER(1) DEFAULT 0,
isAvailable INTEGER(1) DEFAULT 1,
itemShortage VARCHAR(250),
isTaxDataChecked INTEGER(1) DEFAULT 1,
itemDelay VARCHAR(250),
hasComponentLack INTEGER(1),
PRIMARY KEY (ticketFk, saleFk)
) ENGINE = MEMORY;
DROP TEMPORARY TABLE IF EXISTS tmp.ticket_list;
CREATE TEMPORARY TABLE tmp.ticket_list
(PRIMARY KEY (ticketFk))
ENGINE = MEMORY
SELECT tp.ticketFk, c.id clientFk
FROM tmp.sale_getProblems tp
JOIN vn.client c ON c.id = tp.clientFk;
SELECT COUNT(*) INTO vComponentCount
FROM vn.component c
WHERE c.isRequired;
INSERT INTO tmp.sale_problems(ticketFk, hasComponentLack, saleFk)
SELECT tl.ticketFk, (COUNT(DISTINCT s.id) * vComponentCount > COUNT(c.id)), s.id
FROM tmp.ticket_list tl
JOIN vn.sale s ON s.ticketFk = tl.ticketFk
LEFT JOIN vn.saleComponent sc ON sc.saleFk = s.id
LEFT JOIN vn.component c ON c.id = sc.componentFk AND c.isRequired
JOIN vn.ticket t ON t.id = tl.ticketFk
JOIN vn.agencyMode am ON am.id = t.agencyModeFk
JOIN vn.deliveryMethod dm ON dm.id = am.deliveryMethodFk
WHERE dm.code IN('AGENCY','DELIVERY','PICKUP')
GROUP BY tl.ticketFk, s.id;
INSERT INTO tmp.sale_problems(ticketFk, isFreezed)
SELECT DISTINCT tl.ticketFk, TRUE
FROM tmp.ticket_list tl
JOIN vn.client c ON c.id = tl.clientFk
WHERE c.isFreezed
ON DUPLICATE KEY UPDATE
isFreezed = c.isFreezed;
DROP TEMPORARY TABLE IF EXISTS tmp.clientGetDebt;
CREATE TEMPORARY TABLE tmp.clientGetDebt
(PRIMARY KEY (clientFk))
ENGINE = MEMORY
SELECT DISTINCT clientFk
FROM tmp.ticket_list;
CALL clientGetDebt(CURDATE());
INSERT INTO tmp.sale_problems(ticketFk, risk, hasHighRisk)
SELECT DISTINCT tl.ticketFk, r.risk, ((r.risk - cc.riskTolerance) > c.credit + 10)
FROM tmp.ticket_list tl
JOIN vn.ticket t ON t.id = tl.ticketFk
JOIN vn.agencyMode a ON t.agencyModeFk = a.id
JOIN tmp.risk r ON r.clientFk = t.clientFk
JOIN vn.client c ON c.id = t.clientFk
JOIN vn.clientConfig cc
WHERE r.risk > c.credit + 10
AND a.isRiskFree = FALSE
ON DUPLICATE KEY UPDATE
risk = r.risk, hasHighRisk = ((r.risk - cc.riskTolerance) > c.credit + 10);
INSERT INTO tmp.sale_problems(ticketFk, hasTicketRequest)
SELECT DISTINCT tl.ticketFk, TRUE
FROM tmp.ticket_list tl
JOIN vn.ticketRequest tr ON tr.ticketFk = tl.ticketFk
WHERE tr.isOK IS NULL
ON DUPLICATE KEY UPDATE
hasTicketRequest = TRUE;
OPEN vCursor;
WHILE NOT vDone
DO
FETCH vCursor INTO vWarehouse, vDate;
CALL cache.available_refresh(vAvailableCache, FALSE, vWarehouse, vDate);
INSERT INTO tmp.sale_problems(ticketFk, isAvailable, saleFk)
SELECT tl.ticketFk, FALSE, s.id
FROM tmp.ticket_list tl
JOIN vn.ticket t ON t.id = tl.ticketFk
JOIN vn.sale s ON s.ticketFk = t.id
JOIN vn.item i ON i.id = s.itemFk
JOIN vn.itemType it on it.id = i.typeFk
LEFT JOIN cache.available av ON av.item_id = i.id
AND av.calc_id = vAvailableCache
WHERE date(t.shipped) = vDate
AND it.categoryFk != 6
AND IFNULL(av.available, 0) < 0
AND s.isPicked = FALSE
AND NOT i.generic
AND vWarehouse = t.warehouseFk
GROUP BY tl.ticketFk
ON DUPLICATE KEY UPDATE
isAvailable = FALSE, saleFk = VALUES(saleFk);
INSERT INTO tmp.sale_problems(ticketFk, itemShortage, saleFk)
SELECT ticketFk, problem, saleFk
FROM (
SELECT tl.ticketFk, CONCAT('F: ',GROUP_CONCAT(i.id, ' ', i.longName, ' ')) problem, s.id AS saleFk
FROM tmp.ticket_list tl
JOIN vn.ticket t ON t.id = tl.ticketFk
JOIN vn.sale s ON s.ticketFk = t.id
JOIN vn.item i ON i.id = s.itemFk
JOIN vn.itemType it on it.id = i.typeFk
LEFT JOIN vn.itemShelvingStock_byWarehouse issw ON issw.itemFk = i.id AND issw.warehouseFk = t.warehouseFk
LEFT JOIN cache.available av ON av.item_id = i.id AND av.calc_id = vAvailableCache
WHERE IFNULL(av.available, 0) < 0
AND s.quantity > IFNULL(issw.visible, 0)
AND s.quantity > 0
AND s.isPicked = FALSE
AND s.reserved = FALSE
AND it.categoryFk != 6
AND IF(vIsTodayRelative, TRUE, date(t.shipped) = vDate)
AND NOT i.generic
AND CURDATE() = vDate
AND t.warehouseFk = vWarehouse
GROUP BY tl.ticketFk LIMIT 1) sub
ON DUPLICATE KEY UPDATE
itemShortage = sub.problem, saleFk = sub.saleFk;
INSERT INTO tmp.sale_problems(ticketFk, itemDelay, saleFk)
SELECT ticketFk, problem, saleFk
FROM (
SELECT tl.ticketFk, GROUP_CONCAT('I: ',i.id, ' ', i.longName, ' ') problem, s.id AS saleFk
FROM tmp.ticket_list tl
JOIN vn.ticket t ON t.id = tl.ticketFk
JOIN vn.sale s ON s.ticketFk = t.id
JOIN vn.item i ON i.id = s.itemFk
JOIN vn.itemType it on it.id = i.typeFk
LEFT JOIN vn.itemShelvingStock_byWarehouse issw ON issw.itemFk = i.id AND issw.warehouseFk = t.warehouseFk
WHERE s.quantity > IFNULL(issw.visible, 0)
AND s.quantity > 0
AND s.isPicked = FALSE
AND s.reserved = FALSE
AND it.categoryFk != 6
AND IF(vIsTodayRelative, TRUE, date(t.shipped) = vDate)
AND NOT i.generic
AND CURDATE() = vDate
AND t.warehouseFk = vWarehouse
GROUP BY tl.ticketFk LIMIT 1) sub
ON DUPLICATE KEY UPDATE
itemDelay = sub.problem, saleFk = sub.saleFk;
END WHILE;
CLOSE vCursor;
INSERT INTO tmp.sale_problems(ticketFk, isTaxDataChecked)
SELECT DISTINCT tl.ticketFk, FALSE
FROM tmp.ticket_list tl
JOIN vn.client c ON c.id = tl.clientFk
WHERE c.isTaxDataChecked = FALSE
ON DUPLICATE KEY UPDATE
isTaxDataChecked = FALSE;
DROP TEMPORARY TABLE
tmp.clientGetDebt,
tmp.ticket_list;
END;;$$
DELIMITER ;

View File

@ -0,0 +1,48 @@
drop procedure `vn`.`ticket_getProblems`;
DELIMITER $$
$$
create
definer = root@`%` procedure `vn`.`ticket_getProblems`(IN vIsTodayRelative tinyint(1))
BEGIN
/**
* Calcula los problemas para un conjunto de tickets.
* Agrupados por ticket
*
* @table tmp.sale_getProblems(ticketFk, clientFk, warehouseFk, shipped) Identificadores de los tickets a calcular
* @return tmp.ticket_problems
*/
CALL sale_getProblems(vIsTodayRelative);
DROP TEMPORARY TABLE IF EXISTS tmp.ticket_problems;
CREATE TEMPORARY TABLE tmp.ticket_problems
(INDEX (ticketFk))
ENGINE = MEMORY
SELECT
ticketFk,
MAX(p.isFreezed) AS isFreezed,
MAX(p.risk) AS risk,
MAX(p.hasHighRisk) AS hasHighRisk,
MAX(p.hasTicketRequest) AS hasTicketRequest,
MIN(p.isAvailable) AS isAvailable,
MAX(p.itemShortage) AS itemShortage,
MIN(p.isTaxDataChecked) AS isTaxDataChecked,
MAX(p.hasComponentLack) AS hasComponentLack,
0 AS totalProblems
FROM tmp.sale_problems p
GROUP BY ticketFk;
UPDATE tmp.ticket_problems tp
SET tp.totalProblems = (
(tp.isFreezed) +
IF(tp.risk, TRUE, FALSE) +
(tp.hasTicketRequest) +
(tp.isAvailable = 0) +
(tp.isTaxDataChecked = 0) +
(tp.hasComponentLack)
);
DROP TEMPORARY TABLE
tmp.sale_problems;
END;;$$
DELIMITER ;

View File

@ -0,0 +1 @@
alter table `vn`.`travelThermograph` modify `temperature` enum('COOL', 'WARM') null;

File diff suppressed because one or more lines are too long

View File

@ -226,13 +226,21 @@ INSERT INTO `vn`.`payDem`(`id`, `payDem`)
(1, 10), (1, 10),
(2, 20); (2, 20);
INSERT INTO `vn`.`province`(`id`, `name`, `countryFk`, `warehouseFk`) INSERT INTO `vn`.`autonomy`(`id`, `name`, `countryFk`)
VALUES VALUES
(1, 'Province one', 1, NULL), (1, 'Autonomy one', 1),
(2, 'Province two', 1, NULL), (2, 'Autonomy two', 1),
(3, 'Province three', 1, NULL), (3, 'Autonomy three', 2),
(4, 'Province four', 2, NULL), (4, 'Autonomy four', 13);
(5, 'Province five', 13, NULL);
INSERT INTO `vn`.`province`(`id`, `name`, `countryFk`, `autonomyFk`, `warehouseFk`)
VALUES
(1, 'Province one', 1, 1, NULL),
(2, 'Province two', 1, 1, NULL),
(3, 'Province three', 1, 2, NULL),
(4, 'Province four', 2, 3, NULL),
(5, 'Province five', 13, 4, NULL);
INSERT INTO `vn`.`town`(`id`, `name`, `provinceFk`) INSERT INTO `vn`.`town`(`id`, `name`, `provinceFk`)
VALUES VALUES
@ -269,20 +277,20 @@ INSERT INTO `vn`.`contactChannel`(`id`, `name`)
(4, 'GCN Channel'), (4, 'GCN Channel'),
(5, 'The Newspaper'); (5, 'The Newspaper');
INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city`,`postcode`,`phone`,`mobile`,`fax`,`isRelevant`,`email`,`iban`,`dueDay`,`accountingAccount`,`isEqualizated`,`provinceFk`,`hasToInvoice`,`credit`,`countryFk`,`isActive`,`gestdocFk`,`quality`,`payMethodFk`,`created`,`isToBeMailed`,`contactChannelFk`,`hasSepaVnl`,`hasCoreVnl`,`hasCoreVnh`,`riskCalculated`,`clientTypeFk`,`mailAddress`,`cplusTerIdNifFk`,`hasToInvoiceByAddress`,`isTaxDataChecked`,`isFreezed`,`creditInsurance`,`isCreatedAsServed`,`hasInvoiceSimplified`,`salesPersonFk`,`isVies`,`eypbc`) INSERT INTO `vn`.`client`(`id`,`name`,`fi`,`socialName`,`contact`,`street`,`city`,`postcode`,`phone`,`mobile`,`isRelevant`,`email`,`iban`,`dueDay`,`accountingAccount`,`isEqualizated`,`provinceFk`,`hasToInvoice`,`credit`,`countryFk`,`isActive`,`gestdocFk`,`quality`,`payMethodFk`,`created`,`isToBeMailed`,`contactChannelFk`,`hasSepaVnl`,`hasCoreVnl`,`hasCoreVnh`,`riskCalculated`,`clientTypeFk`,`mailAddress`,`hasToInvoiceByAddress`,`isTaxDataChecked`,`isFreezed`,`creditInsurance`,`isCreatedAsServed`,`hasInvoiceSimplified`,`salesPersonFk`,`isVies`,`eypbc`, `businessTypeFk`)
VALUES VALUES
(1101, 'Bruce Wayne', '84612325V', 'Batman', 'Alfred', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceWayne@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1), (1101, 'Bruce Wayne', '84612325V', 'Batman', 'Alfred', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1111111111, 222222222, 1, 'BruceWayne@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'),
(1102, 'Petter Parker', '87945234L', 'Spider man', 'Aunt May', '20 Ingram Street, Queens, USA', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1), (1102, 'Petter Parker', '87945234L', 'Spider man', 'Aunt May', '20 Ingram Street, Queens, USA', 'Silla', 46460, 1111111111, 222222222, 1, 'PetterParker@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'),
(1103, 'Clark Kent', '06815934E', 'Super man', 'lois lane', '344 Clinton Street, Apartament 3-D', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 0, 19, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1), (1103, 'Clark Kent', '06815934E', 'Super man', 'lois lane', '344 Clinton Street, Apartament 3-D', 'Silla', 46460, 1111111111, 222222222, 1, 'ClarkKent@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 0, 19, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'),
(1104, 'Tony Stark', '06089160W', 'Iron man', 'Pepper Potts', '10880 Malibu Point, 90265', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1), (1104, 'Tony Stark', '06089160W', 'Iron man', 'Pepper Potts', '10880 Malibu Point, 90265', 'Silla', 46460, 1111111111, 222222222, 1, 'TonyStark@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, 0, NULL, 0, 0, 18, 0, 1, 'florist'),
(1105, 'Max Eisenhardt', '251628698', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 8, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1), (1105, 'Max Eisenhardt', '251628698', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Silla', 46460, 1111111111, 222222222, 1, 'MaxEisenhardt@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 8, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, 1, NULL, 0, 0, 18, 0, 1, 'florist'),
(1106, 'DavidCharlesHaller', '53136686Q', 'Legion', 'Charles Xavier', 'City of New York, New York, USA', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 0, NULL, 0, 0, 19, 0, 1), (1106, 'DavidCharlesHaller', '53136686Q', 'Legion', 'Charles Xavier', 'City of New York, New York, USA', 'Silla', 46460, 1111111111, 222222222, 1, 'DavidCharlesHaller@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 0, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, 0, NULL, 0, 0, 19, 0, 1, 'florist'),
(1107, 'Hank Pym', '09854837G', 'Ant man', 'Hawk', 'Anthill, San Francisco, California', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 0, 0, NULL, 0, 0, 19, 0, 1), (1107, 'Hank Pym', '09854837G', 'Ant man', 'Hawk', 'Anthill, San Francisco, California', 'Silla', 46460, 1111111111, 222222222, 1, 'HankPym@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, 0, NULL, 0, 0, 19, 0, 1, 'florist'),
(1108, 'Charles Xavier', '22641921P', 'Professor X', 'Beast', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 19, 0, 1), (1108, 'Charles Xavier', '22641921P', 'Professor X', 'Beast', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Silla', 46460, 1111111111, 222222222, 1, 'CharlesXavier@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 1, 1, NULL, 0, 0, 19, 0, 1, 'florist'),
(1109, 'Bruce Banner', '16104829E', 'Hulk', 'Black widow', 'Somewhere in New York', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 0, 0, NULL, 0, 0, 9, 0, 1), (1109, 'Bruce Banner', '16104829E', 'Hulk', 'Black widow', 'Somewhere in New York', 'Silla', 46460, 1111111111, 222222222, 1, 'BruceBanner@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, 0, NULL, 0, 0, 9, 0, 1, 'florist'),
(1110, 'Jessica Jones', '58282869H', 'Jessica Jones', 'Luke Cage', 'NYCC 2015 Poster', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, NULL, 1, 1, 0, 0, NULL, 0, 0, NULL, 0, 1), (1110, 'Jessica Jones', '58282869H', 'Jessica Jones', 'Luke Cage', 'NYCC 2015 Poster', 'Silla', 46460, 1111111111, 222222222, 1, 'JessicaJones@mydomain.com', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 1, 1, 1, 0, 0, NULL, 0, 0, NULL, 0, 1, 'florist'),
(1111, 'Missing', NULL, 'Missing man', 'Anton', 'The space, Universe far away', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, NULL, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1), (1111, 'Missing', NULL, 'Missing man', 'Anton', 'The space, Universe far away', 'Silla', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, NULL),
(1112, 'Trash', NULL, 'Garbage man', 'Unknown name', 'New York city, Underground', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, NULL, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1); (1112, 'Trash', NULL, 'Garbage man', 'Unknown name', 'New York city, Underground', 'Silla', 46460, 1111111111, 222222222, 1, NULL, NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1, NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1, '0000-00-00', 4, 1, 0, 1, 0, NULL, 1, 0, NULL, 0, 1, NULL);
INSERT INTO `vn`.`client`(`id`, `name`, `fi`, `socialName`, `contact`, `street`, `city`, `postcode`, `isRelevant`, `email`, `iban`,`dueDay`,`accountingAccount`, `isEqualizated`, `provinceFk`, `hasToInvoice`, `credit`, `countryFk`, `isActive`, `gestdocFk`, `quality`, `payMethodFk`,`created`, `isTaxDataChecked`) INSERT INTO `vn`.`client`(`id`, `name`, `fi`, `socialName`, `contact`, `street`, `city`, `postcode`, `isRelevant`, `email`, `iban`,`dueDay`,`accountingAccount`, `isEqualizated`, `provinceFk`, `hasToInvoice`, `credit`, `countryFk`, `isActive`, `gestdocFk`, `quality`, `payMethodFk`,`created`, `isTaxDataChecked`)
SELECT id, name, CONCAT(RPAD(CONCAT(id,9),8,id),'A'), CONCAT(name, 'Social'), CONCAT(name, 'Contact'), CONCAT(name, 'Street'), 'SILLA', 46460, 1, CONCAT(name,'@mydomain.com'), NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5, CURDATE(), 1 SELECT id, name, CONCAT(RPAD(CONCAT(id,9),8,id),'A'), CONCAT(name, 'Social'), CONCAT(name, 'Contact'), CONCAT(name, 'Street'), 'SILLA', 46460, 1, CONCAT(name,'@mydomain.com'), NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5, CURDATE(), 1
@ -1060,10 +1068,15 @@ INSERT INTO `vn`.`itemPlacement`(`id`, `itemFk`, `warehouseFk`, `code`)
(4, 2, 1, 'A44'); (4, 2, 1, 'A44');
INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`) INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`, `created`)
VALUES VALUES
(1, 1106, 5), (1, 1106, 5, DATE_ADD(CURDATE(),INTERVAL +1 DAY)),
(2, 1106, 14); (2, 1106, 14, CURDATE());
INSERT INTO `vn`.`ticketCollection`(`id`, `ticketFk`, `collectionFk`)
VALUES
(2, 2, 1),
(3, 3, 2);
INSERT INTO `vn`.`parking` (`column`, `row`, `sectorFk`, `code`, `pickingOrder`) INSERT INTO `vn`.`parking` (`column`, `row`, `sectorFk`, `code`, `pickingOrder`)
VALUES VALUES
@ -1927,7 +1940,7 @@ INSERT INTO `vn`.`zoneIncluded` (`zoneFk`, `geoFk`, `isIncluded`)
(8, 4, 0), (8, 4, 0),
(8, 5, 0), (8, 5, 0),
(8, 1, 1), (8, 1, 1),
(10, 10, 1); (10, 14, 1);
INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `type`, `dated`) INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `type`, `dated`)
VALUES VALUES
@ -2212,6 +2225,11 @@ INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `week
INSERT IGNORE INTO `vn`.`greugeConfig` (`id`, `freightPickUpPrice`) VALUES ('1', '11'); INSERT IGNORE INTO `vn`.`greugeConfig` (`id`, `freightPickUpPrice`) VALUES ('1', '11');
INSERT INTO `vn`.`temperature`(`code`, `name`, `description`)
VALUES
('WARM', 'Warm', 'Warm'),
('COOL', 'Cool', 'Cool');
INSERT INTO `vn`.`thermograph`(`id`, `model`) INSERT INTO `vn`.`thermograph`(`id`, `model`)
VALUES VALUES
('TMM190901395', 'TEMPMATE'), ('TMM190901395', 'TEMPMATE'),
@ -2219,7 +2237,8 @@ INSERT INTO `vn`.`thermograph`(`id`, `model`)
('TZ1905012010', 'DISPOSABLE'), ('TZ1905012010', 'DISPOSABLE'),
('138350-0', 'DISPOSABLE'); ('138350-0', 'DISPOSABLE');
INSERT INTO `vn`.`travelThermograph`(`thermographFk`, `created`, `warehouseFk`, `travelFk`, `temperature`, `result`, `dmsFk`)
INSERT INTO `vn`.`travelThermograph`(`thermographFk`, `created`, `warehouseFk`, `travelFk`, `temperatureFk`, `result`, `dmsFk`)
VALUES VALUES
('TMM190901395', CURDATE(), 1, 1, 'WARM', 'Ok', NULL), ('TMM190901395', CURDATE(), 1, 1, 'WARM', 'Ok', NULL),
('TL.BBA85422', DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 2, 2, 'COOL', 'Ok', NULL), ('TL.BBA85422', DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 2, 2, 'COOL', 'Ok', NULL),
@ -2288,7 +2307,7 @@ INSERT INTO `vn`.`awb` (id, code, package, weight, created, amount, transitoryFk
(9, '99610289193', 302, 2972, CURDATE(), 3871, 442, 1), (9, '99610289193', 302, 2972, CURDATE(), 3871, 442, 1),
(10, '07546500856', 185, 2364, CURDATE(), 5321, 442, 1); (10, '07546500856', 185, 2364, CURDATE(), 5321, 442, 1);
REPLACE INTO vn.dua (id, code, awbFk, issued, operated, booked, bookEntried, gestdocFk, customsValue, companyFk) INSERT INTO `vn`.`dua` (id, code, awbFk, issued, operated, booked, bookEntried, gestdocFk, customsValue, companyFk)
VALUES VALUES
(1, '19ES0028013A481523', 1, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 1, 11276.95, 442), (1, '19ES0028013A481523', 1, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 1, 11276.95, 442),
(2, '21ES00280136115760', 2, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 2, 1376.20, 442), (2, '21ES00280136115760', 2, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 2, 1376.20, 442),
@ -2297,9 +2316,9 @@ REPLACE INTO vn.dua (id, code, awbFk, issued, operated, booked, bookEntried, ges
(5, '19ES00280132022070', 5, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 2, 10012.49, 442), (5, '19ES00280132022070', 5, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 2, 10012.49, 442),
(6, '19ES00280132032308', 6, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 2, 19914.25, 442), (6, '19ES00280132032308', 6, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 2, 19914.25, 442),
(7, '19ES00280132025489', 7, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 1934.06, 442), (7, '19ES00280132025489', 7, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 1934.06, 442),
(8, '19ES00280132025489', 8, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 3618.52, 442), (8, '19ES00280132025490', 8, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 3618.52, 442),
(9, '19ES00280132025489', 9, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 7126.23, 442), (9, '19ES00280132025491', 9, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 7126.23, 442),
(10, '19ES00280132025489', 10, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 4631.45, 442); (10, '19ES00280132025492', 10, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 4631.45, 442);
REPLACE INTO `vn`.`invoiceIn`(`id`, `serialNumber`,`serial`, `supplierFk`, `issued`, `created`, `supplierRef`, `isBooked`, `companyFk`, `docFk`) REPLACE INTO `vn`.`invoiceIn`(`id`, `serialNumber`,`serial`, `supplierFk`, `issued`, `created`, `supplierRef`, `isBooked`, `companyFk`, `docFk`)
VALUES VALUES
@ -2336,8 +2355,8 @@ INSERT INTO `vn`.`duaInvoiceIn`(`id`, `duaFk`, `invoiceInFk`)
(4, 4, 4), (4, 4, 4),
(5, 5, 5), (5, 5, 5),
(6, 6, 6), (6, 6, 6),
(7, 7, 7), (7, 7, 7),
(8, 8, 8), (8, 8, 8),
(9, 9, 9), (9, 9, 9),
(10, 10, 10); (10, 10, 10);

File diff suppressed because it is too large Load Diff

View File

@ -123,6 +123,7 @@ export default {
addProvince: 'vn-autocomplete[ng-model="$ctrl.location.provinceFk"] vn-icon-button[icon="add_circle"]', addProvince: 'vn-autocomplete[ng-model="$ctrl.location.provinceFk"] vn-icon-button[icon="add_circle"]',
addCity: 'vn-autocomplete[ng-model="$ctrl.location.townFk"] vn-icon-button[icon="add_circle"]', addCity: 'vn-autocomplete[ng-model="$ctrl.location.townFk"] vn-icon-button[icon="add_circle"]',
newProvinceName: 'vn-textfield[ng-model="$ctrl.province.name"]', newProvinceName: 'vn-textfield[ng-model="$ctrl.province.name"]',
newProvinceAutonomy: 'vn-autocomplete[ng-model="$ctrl.province.autonomyFk"]',
newCityName: 'vn-textfield[ng-model="$ctrl.city.name"]', newCityName: 'vn-textfield[ng-model="$ctrl.city.name"]',
newCityProvince: 'vn-autocomplete[ng-model="$ctrl.city.provinceFk"]', newCityProvince: 'vn-autocomplete[ng-model="$ctrl.city.provinceFk"]',
newPostcode: 'vn-textfield[ng-model="$ctrl.location.code"]', newPostcode: 'vn-textfield[ng-model="$ctrl.location.code"]',
@ -130,7 +131,6 @@ export default {
city: 'vn-client-create vn-datalist[ng-model="$ctrl.client.city"]', city: 'vn-client-create vn-datalist[ng-model="$ctrl.client.city"]',
province: 'vn-autocomplete[ng-model="$ctrl.client.provinceFk"]', province: 'vn-autocomplete[ng-model="$ctrl.client.provinceFk"]',
country: 'vn-client-create vn-autocomplete[ng-model="$ctrl.client.countryFk"]', country: 'vn-client-create vn-autocomplete[ng-model="$ctrl.client.countryFk"]',
dialogCountry: 'vn-autocomplete[ng-model="$ctrl.province.countryFk"]',
userName: 'vn-client-create vn-textfield[ng-model="$ctrl.client.userName"]', userName: 'vn-client-create vn-textfield[ng-model="$ctrl.client.userName"]',
email: 'vn-client-create vn-textfield[ng-model="$ctrl.client.email"]', email: 'vn-client-create vn-textfield[ng-model="$ctrl.client.email"]',
salesPerson: 'vn-client-create vn-autocomplete[ng-model="$ctrl.client.salesPersonFk"]', salesPerson: 'vn-client-create vn-autocomplete[ng-model="$ctrl.client.salesPersonFk"]',
@ -323,7 +323,6 @@ export default {
idCheckbox: '.vn-popover.shown vn-horizontal:nth-child(1) > vn-check', idCheckbox: '.vn-popover.shown vn-horizontal:nth-child(1) > vn-check',
stemsCheckbox: '.vn-popover.shown vn-horizontal:nth-child(2) > vn-check', stemsCheckbox: '.vn-popover.shown vn-horizontal:nth-child(2) > vn-check',
sizeCheckbox: '.vn-popover.shown vn-horizontal:nth-child(3) > vn-check', sizeCheckbox: '.vn-popover.shown vn-horizontal:nth-child(3) > vn-check',
nicheCheckbox: '.vn-popover.shown vn-horizontal:nth-child(4) > vn-check',
typeCheckbox: '.vn-popover.shown vn-horizontal:nth-child(5) > vn-check', typeCheckbox: '.vn-popover.shown vn-horizontal:nth-child(5) > vn-check',
categoryCheckbox: '.vn-popover.shown vn-horizontal:nth-child(6) > vn-check', categoryCheckbox: '.vn-popover.shown vn-horizontal:nth-child(6) > vn-check',
intrastadCheckbox: '.vn-popover.shown vn-horizontal:nth-child(7) > vn-check', intrastadCheckbox: '.vn-popover.shown vn-horizontal:nth-child(7) > vn-check',
@ -420,17 +419,6 @@ export default {
submitBarcodesButton: 'vn-item-barcode button[type=submit]', submitBarcodesButton: 'vn-item-barcode button[type=submit]',
firstCodeRemoveButton: 'vn-item-barcode vn-horizontal:nth-child(1) vn-icon[icon="delete"]' firstCodeRemoveButton: 'vn-item-barcode vn-horizontal:nth-child(1) vn-icon[icon="delete"]'
}, },
itemNiches: {
addNicheButton: 'vn-item-niche vn-icon[icon="add_circle"]',
firstWarehouse: 'vn-item-niche vn-autocomplete[ng-model="niche.warehouseFk"]',
firstCode: 'vn-item-niche vn-horizontal:nth-child(1) vn-textfield[ng-model="niche.code"]',
secondWarehouse: 'vn-item-niche vn-horizontal:nth-child(2) > vn-autocomplete[ng-model="niche.warehouseFk"]',
secondCode: 'vn-item-niche vn-horizontal:nth-child(2) vn-textfield[ng-model="niche.code"]',
secondNicheRemoveButton: 'vn-item-niche vn-horizontal:nth-child(2) > vn-none > vn-icon-button[icon="delete"]',
thirdWarehouse: 'vn-item-niche vn-horizontal:nth-child(3) > vn-autocomplete[ng-model="niche.warehouseFk"]',
thirdCode: 'vn-item-niche vn-horizontal:nth-child(3) vn-textfield[ng-model="niche.code"]',
submitNichesButton: 'vn-item-niche button[type=submit]'
},
itemBotanical: { itemBotanical: {
genus: 'vn-item-botanical vn-autocomplete[ng-model="$ctrl.botanical.genusFk"]', genus: 'vn-item-botanical vn-autocomplete[ng-model="$ctrl.botanical.genusFk"]',
species: 'vn-item-botanical vn-autocomplete[ng-model="$ctrl.botanical.specieFk"]', species: 'vn-item-botanical vn-autocomplete[ng-model="$ctrl.botanical.specieFk"]',
@ -440,7 +428,6 @@ export default {
basicData: 'vn-item-summary [name="basicData"]', basicData: 'vn-item-summary [name="basicData"]',
vat: 'vn-item-summary [name="tax"]', vat: 'vn-item-summary [name="tax"]',
tags: 'vn-item-summary [name="tags"]', tags: 'vn-item-summary [name="tags"]',
niche: 'vn-item-summary [name="niche"]',
botanical: 'vn-item-summary [name="botanical"]', botanical: 'vn-item-summary [name="botanical"]',
barcode: 'vn-item-summary [name="barcode"]' barcode: 'vn-item-summary [name="barcode"]'
}, },
@ -1018,7 +1005,7 @@ export default {
newThermographId: 'vn-textfield[ng-model="$ctrl.newThermograph.thermographId"]', newThermographId: 'vn-textfield[ng-model="$ctrl.newThermograph.thermographId"]',
newThermographModel: 'vn-autocomplete[ng-model="$ctrl.newThermograph.model"]', newThermographModel: 'vn-autocomplete[ng-model="$ctrl.newThermograph.model"]',
newThermographWarehouse: 'vn-autocomplete[ng-model="$ctrl.newThermograph.warehouseId"]', newThermographWarehouse: 'vn-autocomplete[ng-model="$ctrl.newThermograph.warehouseId"]',
newThermographTemperature: 'vn-autocomplete[ng-model="$ctrl.newThermograph.temperature"]', newThermographTemperature: 'vn-autocomplete[ng-model="$ctrl.newThermograph.temperatureFk"]',
createThermographButton: 'form button[response="accept"]', createThermographButton: 'form button[response="accept"]',
uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="icon-attach"]', uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="icon-attach"]',
createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr', createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr',

View File

@ -42,7 +42,7 @@ describe('Client create path', () => {
await page.waitToClick(selectors.createClientView.addPostCode); await page.waitToClick(selectors.createClientView.addPostCode);
await page.waitToClick(selectors.createClientView.addProvince); await page.waitToClick(selectors.createClientView.addProvince);
await page.write(selectors.createClientView.newProvinceName, 'Massachusetts'); await page.write(selectors.createClientView.newProvinceName, 'Massachusetts');
await page.autocompleteSearch(selectors.createClientView.dialogCountry, 'España'); await page.autocompleteSearch(selectors.createClientView.newProvinceAutonomy, 'Autonomy one');
await page.waitToClick(selectors.createClientView.saveNewProvicenButton); await page.waitToClick(selectors.createClientView.saveNewProvicenButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();

View File

@ -40,13 +40,6 @@ describe('Item summary path', () => {
expect(result).toContain('Brown'); expect(result).toContain('Brown');
}); });
it(`should check the item summary preview shows fields from niche`, async() => {
await page.waitForTextInElement(selectors.itemSummary.niche, 'A1');
const result = await page.waitToGetProperty(selectors.itemSummary.niche, 'innerText');
expect(result).toContain('A1');
});
it(`should check the item summary preview shows fields from botanical`, async() => { it(`should check the item summary preview shows fields from botanical`, async() => {
await page.waitForTextInElement(selectors.itemSummary.botanical, 'Abelia'); await page.waitForTextInElement(selectors.itemSummary.botanical, 'Abelia');
const result = await page.waitToGetProperty(selectors.itemSummary.botanical, 'innerText'); const result = await page.waitToGetProperty(selectors.itemSummary.botanical, 'innerText');
@ -126,12 +119,6 @@ describe('Item summary path', () => {
expect(result).toContain('Silver'); expect(result).toContain('Silver');
}); });
it(`should check the item summary shows fields from niches section`, async() => {
const result = await page.waitToGetProperty(selectors.itemSummary.niche, 'innerText');
expect(result).toContain('One A4');
});
it(`should check the item summary shows fields from botanical section`, async() => { it(`should check the item summary shows fields from botanical section`, async() => {
const result = await page.waitToGetProperty(selectors.itemSummary.botanical, 'innerText'); const result = await page.waitToGetProperty(selectors.itemSummary.botanical, 'innerText');

View File

@ -1,66 +0,0 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Item create niche path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('buyer', 'item');
await page.accessToSearchResult('Ranged weapon longbow 2m');
await page.accessToSection('item.card.niche');
});
afterAll(async() => {
await browser.close();
});
it(`should click create a new niche and delete a former one`, async() => {
await page.waitForTextInField(selectors.itemNiches.firstWarehouse, 'Warehouse One');
await page.waitToClick(selectors.itemNiches.addNicheButton);
await page.waitToClick(selectors.itemNiches.secondNicheRemoveButton);
await page.autocompleteSearch(selectors.itemNiches.thirdWarehouse, 'Warehouse Two');
await page.write(selectors.itemNiches.thirdCode, 'A44');
await page.waitToClick(selectors.itemNiches.submitNichesButton);
const message = await page.waitForSnackbar();
expect(message.text).toContain('Data saved!');
});
it(`should confirm the first niche is the expected one`, async() => {
await page.reloadSection('item.card.niche');
await page.waitForTextInField(selectors.itemNiches.firstWarehouse, 'Warehouse One');
let result = await page
.waitToGetProperty(selectors.itemNiches.firstWarehouse, 'value');
expect(result).toEqual('Warehouse One');
result = await page
.waitToGetProperty(selectors.itemNiches.firstCode, 'value');
expect(result).toEqual('A11');
});
it(`should confirm the second niche is the expected one`, async() => {
let result = await page
.waitToGetProperty(selectors.itemNiches.secondWarehouse, 'value');
expect(result).toEqual('Warehouse Three');
result = await page
.waitToGetProperty(selectors.itemNiches.secondCode, 'value');
expect(result).toEqual('A33');
});
it(`should confirm the third niche is the expected one`, async() => {
let result = await page
.waitToGetProperty(selectors.itemNiches.thirdWarehouse, 'value');
expect(result).toEqual('Warehouse Two');
result = await page
.waitToGetProperty(selectors.itemNiches.thirdCode, 'value');
expect(result).toEqual('A44');
});
});

View File

@ -26,7 +26,6 @@ describe('Item index path', () => {
await page.waitToClick(selectors.itemsIndex.idCheckbox); await page.waitToClick(selectors.itemsIndex.idCheckbox);
await page.waitToClick(selectors.itemsIndex.stemsCheckbox); await page.waitToClick(selectors.itemsIndex.stemsCheckbox);
await page.waitToClick(selectors.itemsIndex.sizeCheckbox); await page.waitToClick(selectors.itemsIndex.sizeCheckbox);
await page.waitToClick(selectors.itemsIndex.nicheCheckbox);
await page.waitToClick(selectors.itemsIndex.typeCheckbox); await page.waitToClick(selectors.itemsIndex.typeCheckbox);
await page.waitToClick(selectors.itemsIndex.categoryCheckbox); await page.waitToClick(selectors.itemsIndex.categoryCheckbox);
await page.waitToClick(selectors.itemsIndex.intrastadCheckbox); await page.waitToClick(selectors.itemsIndex.intrastadCheckbox);
@ -59,7 +58,6 @@ describe('Item index path', () => {
await page.waitToClick(selectors.itemsIndex.idCheckbox); await page.waitToClick(selectors.itemsIndex.idCheckbox);
await page.waitToClick(selectors.itemsIndex.stemsCheckbox); await page.waitToClick(selectors.itemsIndex.stemsCheckbox);
await page.waitToClick(selectors.itemsIndex.sizeCheckbox); await page.waitToClick(selectors.itemsIndex.sizeCheckbox);
await page.waitToClick(selectors.itemsIndex.nicheCheckbox);
await page.waitToClick(selectors.itemsIndex.typeCheckbox); await page.waitToClick(selectors.itemsIndex.typeCheckbox);
await page.waitToClick(selectors.itemsIndex.categoryCheckbox); await page.waitToClick(selectors.itemsIndex.categoryCheckbox);
await page.waitToClick(selectors.itemsIndex.intrastadCheckbox); await page.waitToClick(selectors.itemsIndex.intrastadCheckbox);

View File

@ -76,7 +76,7 @@ describe('Order edit basic data path', () => {
it('should be able to modify all the properties', async() => { it('should be able to modify all the properties', async() => {
await page.autocompleteSearch(selectors.orderBasicData.client, 'Tony Stark'); await page.autocompleteSearch(selectors.orderBasicData.client, 'Tony Stark');
await page.autocompleteSearch(selectors.orderBasicData.address, 'Tony Stark'); await page.autocompleteSearch(selectors.orderBasicData.address, 'Tony Stark');
await page.autocompleteSearch(selectors.orderBasicData.agency, 'Silla247'); await page.autocompleteSearch(selectors.orderBasicData.agency, 'Other agency');
await page.write(selectors.orderBasicData.observation, 'my observation'); await page.write(selectors.orderBasicData.observation, 'my observation');
await page.waitToClick(selectors.orderBasicData.saveButton); await page.waitToClick(selectors.orderBasicData.saveButton);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
@ -96,7 +96,7 @@ describe('Order edit basic data path', () => {
const result = await page const result = await page
.waitToGetProperty(selectors.orderBasicData.agency, 'value'); .waitToGetProperty(selectors.orderBasicData.agency, 'value');
expect(result).toEqual('7: Silla247'); expect(result).toEqual('Other agency');
}); });
it('should now confirm the observations have been edited', async() => { it('should now confirm the observations have been edited', async() => {

View File

@ -119,7 +119,7 @@ describe('Travel descriptor path', () => {
await page.waitToClick(selectors.travelDescriptor.acceptClonation); await page.waitToClick(selectors.travelDescriptor.acceptClonation);
const message = await page.waitForSnackbar(); const message = await page.waitForSnackbar();
expect(message.text).toContain('A travel with this data already exists'); expect(message.text).toContain('Unable to clone this travel');
}); });
it('should update the landed date to a future date to enable cloneWithEntries', async() => { it('should update the landed date to a future date to enable cloneWithEntries', async() => {

View File

@ -32,7 +32,7 @@ describe('Travel thermograph path', () => {
await page.write(selectors.travelThermograph.newThermographId, thermographName); await page.write(selectors.travelThermograph.newThermographId, thermographName);
await page.autocompleteSearch(selectors.travelThermograph.newThermographModel, 'TEMPMATE'); await page.autocompleteSearch(selectors.travelThermograph.newThermographModel, 'TEMPMATE');
await page.autocompleteSearch(selectors.travelThermograph.newThermographWarehouse, 'Warehouse Two'); await page.autocompleteSearch(selectors.travelThermograph.newThermographWarehouse, 'Warehouse Two');
await page.autocompleteSearch(selectors.travelThermograph.newThermographTemperature, 'WARM'); await page.autocompleteSearch(selectors.travelThermograph.newThermographTemperature, 'Warm');
await page.waitToClick(selectors.travelThermograph.createThermographButton); await page.waitToClick(selectors.travelThermograph.createThermographButton);
}); });

View File

@ -239,9 +239,6 @@
.icon-mandatory:before { .icon-mandatory:before {
content: "\e921"; content: "\e921";
} }
.icon-niche:before {
content: "\e922";
}
.icon-no036:before { .icon-no036:before {
content: "\e923"; content: "\e923";
} }

View File

@ -41,7 +41,6 @@
<glyph unicode="&#xe91f;" glyph-name="logout" d="M405.333 243.2l81.067-81.067 281.6 285.867-285.867 285.867-76.8-81.067 145.067-149.333h-550.4v-115.2h550.4l-145.067-145.067zM908.8 960h-793.6c-64 0-115.2-51.2-115.2-115.2v-226.133h115.2v226.133h797.867v-797.867h-797.867v230.4h-115.2v-226.133c0-64 51.2-115.2 115.2-115.2h797.867c64 0 115.2 51.2 115.2 115.2v793.6c-4.267 64-55.467 115.2-119.467 115.2z" /> <glyph unicode="&#xe91f;" glyph-name="logout" d="M405.333 243.2l81.067-81.067 281.6 285.867-285.867 285.867-76.8-81.067 145.067-149.333h-550.4v-115.2h550.4l-145.067-145.067zM908.8 960h-793.6c-64 0-115.2-51.2-115.2-115.2v-226.133h115.2v226.133h797.867v-797.867h-797.867v230.4h-115.2v-226.133c0-64 51.2-115.2 115.2-115.2h797.867c64 0 115.2 51.2 115.2 115.2v793.6c-4.267 64-55.467 115.2-119.467 115.2z" />
<glyph unicode="&#xe920;" glyph-name="mana" d="M529.067 494.933c0 17.067 12.8 29.867 29.867 29.867s29.867-12.8 29.867-29.867c0-17.067-12.8-29.867-29.867-29.867s-29.867 12.8-29.867 29.867zM614.4 324.267c21.333 0 38.4 17.067 38.4 38.4s-17.067 38.4-38.4 38.4c-21.333 0-38.4-17.067-38.4-38.4 0-17.067 17.067-38.4 38.4-38.4zM473.6 614.4c12.8 0 25.6 12.8 25.6 25.6s-12.8 25.6-25.6 25.6-25.6-12.8-25.6-25.6c0-17.067 12.8-25.6 25.6-25.6zM802.133 302.933v-4.267c-4.267-157.867-132.267-285.867-290.133-285.867s-285.867 128-290.133 285.867v4.267h580.267zM584.533 238.933c0 17.067-12.8 29.867-29.867 29.867s-29.867-12.8-29.867-29.867 12.8-29.867 29.867-29.867c17.067 0 29.867 12.8 29.867 29.867zM401.067 264.533c-25.6 0-46.933-21.333-46.933-46.933s21.333-46.933 46.933-46.933c25.6 0 46.933 21.333 46.933 46.933s-21.333 46.933-46.933 46.933zM456.533 354.133c25.6 0 46.933 21.333 46.933 46.933s-21.333 46.933-46.933 46.933c-25.6 0-46.933-21.333-46.933-46.933s21.333-46.933 46.933-46.933zM878.933 302.933c0-200.533-162.133-366.933-366.933-366.933s-366.933 162.133-366.933 366.933c0 136.533 72.533 260.267 192 324.267v187.733c-21.333 4.267-38.4 21.333-38.4 42.667v59.733c0 25.6 21.333 42.667 42.667 42.667h332.8c25.6 0 42.667-21.333 42.667-42.667v-55.467c0-21.333-17.067-42.667-38.4-42.667v-192c123.733-68.267 200.533-192 200.533-324.267zM840.533 302.933c0 128-76.8 243.2-192 298.667h-4.267v256h34.133c4.267 0 4.267 4.267 4.267 4.267v55.467c0 4.267-4.267 4.267-4.267 4.267h-332.8c-4.267 0-8.533-4.267-8.533-4.267v-55.467c0-4.267 4.267-4.267 4.267-4.267h34.133v-256h-4.267c-115.2-51.2-192-170.667-192-298.667 0-179.2 145.067-328.533 328.533-328.533s332.8 145.067 332.8 328.533z" /> <glyph unicode="&#xe920;" glyph-name="mana" d="M529.067 494.933c0 17.067 12.8 29.867 29.867 29.867s29.867-12.8 29.867-29.867c0-17.067-12.8-29.867-29.867-29.867s-29.867 12.8-29.867 29.867zM614.4 324.267c21.333 0 38.4 17.067 38.4 38.4s-17.067 38.4-38.4 38.4c-21.333 0-38.4-17.067-38.4-38.4 0-17.067 17.067-38.4 38.4-38.4zM473.6 614.4c12.8 0 25.6 12.8 25.6 25.6s-12.8 25.6-25.6 25.6-25.6-12.8-25.6-25.6c0-17.067 12.8-25.6 25.6-25.6zM802.133 302.933v-4.267c-4.267-157.867-132.267-285.867-290.133-285.867s-285.867 128-290.133 285.867v4.267h580.267zM584.533 238.933c0 17.067-12.8 29.867-29.867 29.867s-29.867-12.8-29.867-29.867 12.8-29.867 29.867-29.867c17.067 0 29.867 12.8 29.867 29.867zM401.067 264.533c-25.6 0-46.933-21.333-46.933-46.933s21.333-46.933 46.933-46.933c25.6 0 46.933 21.333 46.933 46.933s-21.333 46.933-46.933 46.933zM456.533 354.133c25.6 0 46.933 21.333 46.933 46.933s-21.333 46.933-46.933 46.933c-25.6 0-46.933-21.333-46.933-46.933s21.333-46.933 46.933-46.933zM878.933 302.933c0-200.533-162.133-366.933-366.933-366.933s-366.933 162.133-366.933 366.933c0 136.533 72.533 260.267 192 324.267v187.733c-21.333 4.267-38.4 21.333-38.4 42.667v59.733c0 25.6 21.333 42.667 42.667 42.667h332.8c25.6 0 42.667-21.333 42.667-42.667v-55.467c0-21.333-17.067-42.667-38.4-42.667v-192c123.733-68.267 200.533-192 200.533-324.267zM840.533 302.933c0 128-76.8 243.2-192 298.667h-4.267v256h34.133c4.267 0 4.267 4.267 4.267 4.267v55.467c0 4.267-4.267 4.267-4.267 4.267h-332.8c-4.267 0-8.533-4.267-8.533-4.267v-55.467c0-4.267 4.267-4.267 4.267-4.267h34.133v-256h-4.267c-115.2-51.2-192-170.667-192-298.667 0-179.2 145.067-328.533 328.533-328.533s332.8 145.067 332.8 328.533z" />
<glyph unicode="&#xe921;" glyph-name="mandatory" d="M981.333 725.333v-618.667c0-93.867-76.8-170.667-170.667-170.667h-311.467c-46.933 0-89.6 17.067-119.467 51.2l-337.067 341.333c0 0 55.467 51.2 55.467 55.467 8.533 8.533 21.333 12.8 34.133 12.8 8.533 0 17.067-4.267 25.6-8.533 0 0 183.467-106.667 183.467-106.667v507.733c0 34.133 29.867 64 64 64s64-29.867 64-64v-298.667h42.667v405.333c0 34.133 29.867 64 64 64s64-29.867 64-64v-405.333h42.667v362.667c0 34.133 29.867 64 64 64s64-29.867 64-64v-362.667h42.667v234.667c0 34.133 29.867 64 64 64s64-29.867 64-64z" /> <glyph unicode="&#xe921;" glyph-name="mandatory" d="M981.333 725.333v-618.667c0-93.867-76.8-170.667-170.667-170.667h-311.467c-46.933 0-89.6 17.067-119.467 51.2l-337.067 341.333c0 0 55.467 51.2 55.467 55.467 8.533 8.533 21.333 12.8 34.133 12.8 8.533 0 17.067-4.267 25.6-8.533 0 0 183.467-106.667 183.467-106.667v507.733c0 34.133 29.867 64 64 64s64-29.867 64-64v-298.667h42.667v405.333c0 34.133 29.867 64 64 64s64-29.867 64-64v-405.333h42.667v362.667c0 34.133 29.867 64 64 64s64-29.867 64-64v-362.667h42.667v234.667c0 34.133 29.867 64 64 64s64-29.867 64-64z" />
<glyph unicode="&#xe922;" glyph-name="niche" d="M512 960c-196.267 0-358.4-162.133-358.4-358.4 0-268.8 358.4-665.6 358.4-665.6s358.4 396.8 358.4 665.6c0 196.267-162.133 358.4-358.4 358.4zM512 473.6c-72.533 0-128 55.467-128 128s55.467 128 128 128 128-55.467 128-128-55.467-128-128-128z" />
<glyph unicode="&#xe923;" glyph-name="no036" d="M89.6 145.067v627.2c0 46.933 29.867 85.333 72.533 98.133v-46.933c-17.067-12.8-29.867-29.867-29.867-51.2v-584.533l-42.667-42.667zM409.6 465.067h-46.933v85.333h132.267l123.733 123.733h-46.933v226.133l136.533-136.533 51.2 51.2-149.333 145.067h-332.8c-42.667 0-81.067-38.4-81.067-81.067v-627.2l213.333 213.333zM686.933 51.2h-452.267l-42.667-42.667c0 0 0 0 0 0h494.933c51.2 0 93.867 38.4 102.4 85.333h-42.667c-8.533-25.6-34.133-42.667-59.733-42.667zM691.2 507.733v-42.667h-42.667l-81.067-81.067h123.733v-81.067h-204.8l-166.4-166.4h452.267c42.667 0 81.067 38.4 81.067 81.067v452.267l-162.133-162.133zM59.733-64l-59.733 59.733 964.267 964.267 59.733-59.733-964.267-964.267z" /> <glyph unicode="&#xe923;" glyph-name="no036" d="M89.6 145.067v627.2c0 46.933 29.867 85.333 72.533 98.133v-46.933c-17.067-12.8-29.867-29.867-29.867-51.2v-584.533l-42.667-42.667zM409.6 465.067h-46.933v85.333h132.267l123.733 123.733h-46.933v226.133l136.533-136.533 51.2 51.2-149.333 145.067h-332.8c-42.667 0-81.067-38.4-81.067-81.067v-627.2l213.333 213.333zM686.933 51.2h-452.267l-42.667-42.667c0 0 0 0 0 0h494.933c51.2 0 93.867 38.4 102.4 85.333h-42.667c-8.533-25.6-34.133-42.667-59.733-42.667zM691.2 507.733v-42.667h-42.667l-81.067-81.067h123.733v-81.067h-204.8l-166.4-166.4h452.267c42.667 0 81.067 38.4 81.067 81.067v452.267l-162.133-162.133zM59.733-64l-59.733 59.733 964.267 964.267 59.733-59.733-964.267-964.267z" />
<glyph unicode="&#xe924;" glyph-name="notes" d="M614.4 960h-413.867c-59.733 0-106.667-46.933-106.667-102.4v-819.2c0-55.467 46.933-102.4 102.4-102.4h627.2c55.467 0 102.4 46.933 102.4 102.4v614.4l-311.467 307.2zM563.2 601.6v281.6l290.133-281.6h-290.133z" /> <glyph unicode="&#xe924;" glyph-name="notes" d="M614.4 960h-413.867c-59.733 0-106.667-46.933-106.667-102.4v-819.2c0-55.467 46.933-102.4 102.4-102.4h627.2c55.467 0 102.4 46.933 102.4 102.4v614.4l-311.467 307.2zM563.2 601.6v281.6l290.133-281.6h-290.133z" />
<glyph unicode="&#xe925;" glyph-name="noweb" d="M0 362.667c0 132.267 98.133 238.933 226.133 256 55.467 102.4 162.133 170.667 285.867 170.667 64 0 119.467-17.067 170.667-51.2l-580.267-580.267c-64 46.933-102.4 123.733-102.4 204.8zM823.467 533.333c-4.267 29.867-17.067 55.467-25.6 81.067l-507.733-507.733h520.533c119.467 0 213.333 93.867 213.333 213.333 0 110.933-85.333 204.8-200.533 213.333zM1024 900.267l-59.733 59.733-964.267-964.267 59.733-59.733 964.267 964.267z" /> <glyph unicode="&#xe925;" glyph-name="noweb" d="M0 362.667c0 132.267 98.133 238.933 226.133 256 55.467 102.4 162.133 170.667 285.867 170.667 64 0 119.467-17.067 170.667-51.2l-580.267-580.267c-64 46.933-102.4 123.733-102.4 204.8zM823.467 533.333c-4.267 29.867-17.067 55.467-25.6 81.067l-507.733-507.733h520.533c119.467 0 213.333 93.867 213.333 213.333 0 110.933-85.333 204.8-200.533 213.333zM1024 900.267l-59.733 59.733-964.267-964.267 59.733-59.733 964.267 964.267z" />

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View File

@ -63,7 +63,7 @@
show-field="bank" show-field="bank"
order="id" order="id"
value-field="id" value-field="id"
search-function="{or: [{id: $search}, {bank: {like: '%'+ $search +'%'}}]}"> search-function="$ctrl.bankSearchFunc($search)">
<tpl-item>{{id}}: {{bank}}</tpl-item> <tpl-item>{{id}}: {{bank}}</tpl-item>
</vn-autocomplete> </vn-autocomplete>
<vn-autocomplete <vn-autocomplete

View File

@ -78,6 +78,12 @@ class Controller {
this.$.companies.refresh(); this.$.companies.refresh();
this.$.popover.show(event.target); this.$.popover.show(event.target);
} }
bankSearchFunc($search) {
return /^\d+$/.test($search)
? {id: $search}
: {bank: {like: '%' + $search + '%'}};
}
} }
Controller.$inject = ['$scope', '$translate', 'vnConfig', 'vnAuth', 'vnToken']; Controller.$inject = ['$scope', '$translate', 'vnConfig', 'vnAuth', 'vnToken'];

View File

@ -61,12 +61,28 @@ describe('Salix', () => {
}); });
describe('getImageUrl()', () => { describe('getImageUrl()', () => {
it('should return de url image', () => { it('should return the url image', () => {
const url = $root.imagePath('user', '160x160', userId); const url = $root.imagePath('user', '160x160', userId);
expect(url).toBeDefined(); expect(url).toBeDefined();
expect(url).toEqual(`/api/Images/user/160x160/${userId}/download?access_token=null`); expect(url).toEqual(`/api/Images/user/160x160/${userId}/download?access_token=null`);
}); });
}); });
describe('bankSearchFunc()', () => {
it('should return the filter by id property for an input of a number', () => {
const bankId = 1;
const result = controller.bankSearchFunc(bankId);
expect(result).toEqual({id: bankId});
});
it('should return the filter by bank property for an input of an string', () => {
const bankName = 'Bank of America';
const result = controller.bankSearchFunc(bankName);
expect(result).toEqual({bank: {like: '%' + bankName + '%'}});
});
});
}); });
}); });

View File

@ -1,19 +1,29 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Model rewriteDbError()', () => { describe('Model rewriteDbError()', () => {
it('should extend rewriteDbError properties to any model passed', () => { it('should extend rewriteDbError properties to any model passed', () => {
let exampleModel = app.models.ItemNiche; const exampleModel = models.ItemTag;
expect(exampleModel.rewriteDbError).toBeDefined(); expect(exampleModel.rewriteDbError).toBeDefined();
}); });
it('should handle a duplicated warehouse error', async() => { it('should handle a duplicated warehouse error', async() => {
let itemNiche = {itemFk: 1, warehouseFK: 1, code: 'A11'}; const tx = await models.Ticket.beginTransaction({});
let error; let error;
await app.models.ItemNiche.create(itemNiche).catch(e => {
try {
const options = {transaction: tx};
const itemTag = {itemFk: 1, tagFk: 56, value: 'Ranged weapon', priority: 1};
await models.ItemTag.create(itemTag, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e; error = e;
}).finally(() => { }
expect(error.message).toEqual(`The warehouse can't be repeated`);
}); expect(error.message).toEqual(`The tag can't be repeated`);
}); });
}); });

View File

@ -95,7 +95,7 @@
"The nif cannot be empty": "The nif cannot be empty", "The nif cannot be empty": "The nif cannot be empty",
"Amount cannot be zero": "Amount cannot be zero", "Amount cannot be zero": "Amount cannot be zero",
"Company has to be official": "Company has to be official", "Company has to be official": "Company has to be official",
"A travel with this data already exists": "A travel with this data already exists", "Unable to clone this travel": "Unable to clone this travel",
"The observation type can't be repeated": "The observation type can't be repeated", "The observation type can't be repeated": "The observation type can't be repeated",
"New ticket request has been created with price": "New ticket request has been created *'{{description}}'* for day *{{shipped}}*, with a quantity of *{{quantity}}* and a price of *{{price}} €*", "New ticket request has been created with price": "New ticket request has been created *'{{description}}'* for day *{{shipped}}*, with a quantity of *{{quantity}}* and a price of *{{price}} €*",
"New ticket request has been created": "New ticket request has been created *'{{description}}'* for day *{{shipped}}*, with a quantity of *{{quantity}}*", "New ticket request has been created": "New ticket request has been created *'{{description}}'* for day *{{shipped}}*, with a quantity of *{{quantity}}*",
@ -114,5 +114,6 @@
"Global invoicing failed": "[Global invoicing] Wasn't able to invoice some of the clients", "Global invoicing failed": "[Global invoicing] Wasn't able to invoice some of the clients",
"A ticket with a negative base can't be invoiced": "A ticket with a negative base can't be invoiced", "A ticket with a negative base can't be invoiced": "A ticket with a negative base can't be invoiced",
"This client is not invoiceable": "This client is not invoiceable", "This client is not invoiceable": "This client is not invoiceable",
"INACTIVE_PROVIDER": "Inactive provider" "INACTIVE_PROVIDER": "Inactive provider",
"reference duplicated": "reference duplicated"
} }

View File

@ -143,7 +143,7 @@
"ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto", "ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto",
"Distance must be lesser than 1000": "La distancia debe ser inferior a 1000", "Distance must be lesser than 1000": "La distancia debe ser inferior a 1000",
"This ticket is deleted": "Este ticket está eliminado", "This ticket is deleted": "Este ticket está eliminado",
"A travel with this data already exists": "Ya existe un travel con estos datos", "Unable to clone this travel": "No ha sido posible clonar este travel",
"This thermograph id already exists": "La id del termógrafo ya existe", "This thermograph id already exists": "La id del termógrafo ya existe",
"Choose a date range or days forward": "Selecciona un rango de fechas o días en adelante", "Choose a date range or days forward": "Selecciona un rango de fechas o días en adelante",
"ORDER_ALREADY_CONFIRMED": "ORDER_ALREADY_CONFIRMED", "ORDER_ALREADY_CONFIRMED": "ORDER_ALREADY_CONFIRMED",

View File

@ -180,10 +180,10 @@ module.exports = Self => {
} }
Self.observe('before save', async function(ctx) { Self.observe('before save', async function(ctx) {
let changes = ctx.data || ctx.instance; const changes = ctx.data || ctx.instance;
let orgData = ctx.currentInstance; const orgData = ctx.currentInstance;
let finalState = getFinalState(ctx); const finalState = getFinalState(ctx);
let payMethodWithIban = 4; const payMethodWithIban = 4;
// Validate socialName format // Validate socialName format
const hasChanges = orgData && changes; const hasChanges = orgData && changes;
@ -204,14 +204,20 @@ module.exports = Self => {
changes.payMethodFk = 5; // Credit card changes.payMethodFk = 5; // Credit card
} }
let payMethodFk = changes.payMethodFk || (orgData && orgData.payMethodFk); const payMethodFk = changes.payMethodFk || (orgData && orgData.payMethodFk);
let dueDay = changes.dueDay || (orgData && orgData.dueDay); const dueDay = changes.dueDay || (orgData && orgData.dueDay);
if (payMethodFk == payMethodWithIban && dueDay == 0) if (payMethodFk == payMethodWithIban && dueDay == 0)
changes.dueDay = 5; changes.dueDay = 5;
if (isMultiple(ctx)) return; if (isMultiple(ctx)) return;
if (!ctx.isNewInstance) {
const isTaxDataCheckedChanged = !orgData.isTaxDataChecked && changes.isTaxDataChecked;
if (isTaxDataCheckedChanged && !orgData.businessTypeFk)
throw new UserError(`Can't verify data unless the client has a business type`);
}
if (changes.credit !== undefined) { if (changes.credit !== undefined) {
await validateCreditChange(ctx, finalState); await validateCreditChange(ctx, finalState);
let filter = {fields: ['id'], where: {userFk: ctx.options.accessToken.userId}}; let filter = {fields: ['id'], where: {userFk: ctx.options.accessToken.userId}};

View File

@ -33,7 +33,7 @@
fields="['accountingTypeFk']" fields="['accountingTypeFk']"
include="{relation: 'accountingType'}" include="{relation: 'accountingType'}"
ng-model="$ctrl.bankFk" ng-model="$ctrl.bankFk"
search-function="{or: [{id: $search}, {bank: {like: '%'+ $search +'%'}}]}" search-function="$ctrl.bankSearchFunc($search)"
selection="$ctrl.bankSelection" selection="$ctrl.bankSelection"
order="id" order="id"
required="true"> required="true">

View File

@ -137,6 +137,12 @@ class Controller extends Dialog {
} }
}); });
} }
bankSearchFunc($search) {
return /^\d+$/.test($search)
? {id: $search}
: {bank: {like: '%' + $search + '%'}};
}
} }
Controller.$inject = ['$element', '$scope', '$transclude', 'vnReport']; Controller.$inject = ['$element', '$scope', '$transclude', 'vnReport'];

View File

@ -118,5 +118,21 @@ describe('Client', () => {
expect(controller.receipt.compensationAccount).toEqual('4000000003'); expect(controller.receipt.compensationAccount).toEqual('4000000003');
}); });
}); });
describe('bankSearchFunc()', () => {
it('should return the filter by id property for an input of a number', () => {
const bankId = 1;
const result = controller.bankSearchFunc(bankId);
expect(result).toEqual({id: bankId});
});
it('should return the filter by bank property for an input of an string', () => {
const bankName = 'Bank of America';
const result = controller.bankSearchFunc(bankName);
expect(result).toEqual({bank: {like: '%' + bankName + '%'}});
});
});
}); });
}); });

View File

@ -80,7 +80,7 @@
<vn-horizontal> <vn-horizontal>
<vn-autocomplete <vn-autocomplete
ng-model="$ctrl.client.transferorFk" ng-model="$ctrl.client.transferorFk"
url="Clients/isActive" url="Clients"
search-function="$ctrl.transferorSearchFunction($search)" search-function="$ctrl.transferorSearchFunction($search)"
where="{id: {neq: $ctrl.client.id}}" where="{id: {neq: $ctrl.client.id}}"
show-field="name" show-field="name"

View File

@ -182,7 +182,8 @@
vn-one vn-one
label="Verified data" label="Verified data"
ng-model="$ctrl.client.isTaxDataChecked" ng-model="$ctrl.client.isTaxDataChecked"
vn-acl="salesAssistant"> vn-acl="salesAssistant"
disabled="!$ctrl.client.businessTypeFk">
</vn-check> </vn-check>
</vn-horizontal> </vn-horizontal>
</vn-card> </vn-card>

View File

@ -12,11 +12,11 @@
label="Name"> label="Name">
</vn-textfield> </vn-textfield>
<vn-autocomplete vn-one <vn-autocomplete vn-one
ng-model="$ctrl.province.countryFk" ng-model="$ctrl.province.autonomyFk"
url="Countries" url="Autonomies"
show-field="country" show-field="name"
value-field="id" value-field="id"
label="Country"> label="Autonomy">
</vn-autocomplete> </vn-autocomplete>
</vn-horizontal> </vn-horizontal>
</tpl-body> </tpl-body>

View File

@ -13,8 +13,8 @@ class Controller extends Component {
try { try {
if (!this.province.name) if (!this.province.name)
throw new Error(`The province name can't be empty`); throw new Error(`The province name can't be empty`);
if (!this.province.countryFk) if (!this.province.autonomyFk)
throw new Error(`The country can't be empty`); throw new Error(`The autonomy can't be empty`);
this.$http.patch(`provinces`, this.province).then(res => { this.$http.patch(`provinces`, this.province).then(res => {
this.vnApp.showMessage(this.$t('The province has been created')); this.vnApp.showMessage(this.$t('The province has been created'));

View File

@ -18,8 +18,8 @@ describe('Client', () => {
describe('onAccept()', () => { describe('onAccept()', () => {
it('should perform a POST query and show a success snackbar', () => { it('should perform a POST query and show a success snackbar', () => {
let params = {name: 'New Jersey', countryFk: 1}; const params = {name: 'New Jersey', autonomyFk: 1};
controller.province = {name: 'New Jersey', countryFk: 1}; controller.province = {name: 'New Jersey', autonomyFk: 1};
jest.spyOn(controller.vnApp, 'showMessage'); jest.spyOn(controller.vnApp, 'showMessage');
$httpBackend.expect('PATCH', `provinces`, params).respond(200, params); $httpBackend.expect('PATCH', `provinces`, params).respond(200, params);

View File

@ -348,7 +348,7 @@
</span> </span>
</vn-td> </vn-td>
<vn-td shrink> <vn-td shrink>
<span class="chip {{$ctrl.totalPriceColor(ticket)}}"> <span class="chip {{::$ctrl.totalPriceColor(ticket)}}">
{{::(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}} {{::(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}}
</span> </span>
</vn-td> </vn-td>

View File

@ -59,7 +59,7 @@
<vn-autocomplete <vn-autocomplete
class="dense" class="dense"
vn-focus vn-focus
url="Items" url="Items/withName"
ng-model="buy.itemFk" ng-model="buy.itemFk"
show-field="name" show-field="name"
value-field="id" value-field="id"
@ -156,7 +156,7 @@
</vn-horizontal> </vn-horizontal>
<vn-crud-model <vn-crud-model
vn-id="itemsModel" vn-id="itemsModel"
url="Items" url="Items/withName"
filter="$ctrl.itemFilter" filter="$ctrl.itemFilter"
data="items" data="items"
limit="10"> limit="10">

View File

@ -64,7 +64,7 @@
</span> </span>
<vn-autocomplete ng-if="!buy.id" class="dense" <vn-autocomplete ng-if="!buy.id" class="dense"
vn-focus vn-focus
url="Items" url="Items/withName"
ng-model="buy.itemFk" ng-model="buy.itemFk"
show-field="name" show-field="name"
value-field="id" value-field="id"

View File

@ -1,6 +1,3 @@
const loggable = require('vn-loopback/util/log');
module.exports = Self => { module.exports = Self => {
Self.remoteMethodCtx('clone', { Self.remoteMethodCtx('clone', {
description: 'Clone the invoiceIn and as many invoiceInTax and invoiceInDueDay referencing it', description: 'Clone the invoiceIn and as many invoiceInTax and invoiceInDueDay referencing it',
@ -23,7 +20,6 @@ module.exports = Self => {
}); });
Self.clone = async(ctx, id, options) => { Self.clone = async(ctx, id, options) => {
const userId = ctx.req.accessToken.userId;
const models = Self.app.models; const models = Self.app.models;
let tx; let tx;
const myOptions = {}; const myOptions = {};
@ -56,10 +52,11 @@ module.exports = Self => {
const issued = new Date(sourceInvoiceIn.issued); const issued = new Date(sourceInvoiceIn.issued);
issued.setMonth(issued.getMonth() + 1); issued.setMonth(issued.getMonth() + 1);
const clonedRef = sourceInvoiceIn.supplierRef + '(2)';
const clone = await models.InvoiceIn.create({ const clone = await models.InvoiceIn.create({
serial: sourceInvoiceIn.serial, serial: sourceInvoiceIn.serial,
supplierRef: sourceInvoiceIn.supplierRef, supplierRef: clonedRef,
supplierFk: sourceInvoiceIn.supplierFk, supplierFk: sourceInvoiceIn.supplierFk,
issued: issued, issued: issued,
currencyFk: sourceInvoiceIn.currencyFk, currencyFk: sourceInvoiceIn.currencyFk,

View File

@ -17,7 +17,7 @@ describe('invoiceIn clone()', () => {
try { try {
const clone = await models.InvoiceIn.clone(ctx, 1, options); const clone = await models.InvoiceIn.clone(ctx, 1, options);
expect(clone.supplierRef).toEqual('1234'); expect(clone.supplierRef).toEqual('1234(2)');
const invoiceInTaxes = await models.InvoiceInTax.find({where: {invoiceInFk: clone.id}}, options); const invoiceInTaxes = await models.InvoiceInTax.find({where: {invoiceInFk: clone.id}}, options);

View File

@ -100,7 +100,7 @@ describe('InvoiceIn filter()', () => {
try { try {
const ctx = { const ctx = {
args: { args: {
awbCode: '07546491432', awbCode: '07546500856',
} }
}; };
@ -108,8 +108,8 @@ describe('InvoiceIn filter()', () => {
const firstRow = result[0]; const firstRow = result[0];
expect(result.length).toEqual(1); expect(result.length).toEqual(1);
expect(firstRow.id).toEqual(7); expect(firstRow.id).toEqual(10);
expect(firstRow.awbCode).toEqual('07546491432'); expect(firstRow.awbCode).toEqual('07546500856');
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -65,6 +65,7 @@ module.exports = Self => {
let clientId = args.clientFk; let clientId = args.clientFk;
let maxShipped = args.maxShipped; let maxShipped = args.maxShipped;
let companyId; let companyId;
let newInvoice;
let query; let query;
try { try {
if (ticketId) { if (ticketId) {
@ -137,18 +138,18 @@ module.exports = Self => {
], myOptions); ], myOptions);
} }
const [newInvoice] = await Self.rawSql(`SELECT @newInvoiceId id`, null, myOptions); [newInvoice] = await Self.rawSql(`SELECT @newInvoiceId id`, null, myOptions);
if (tx) await tx.commit(); if (tx) await tx.commit();
if (newInvoice.id)
await Self.createPdf(ctx, newInvoice.id);
return newInvoice;
} catch (e) { } catch (e) {
if (tx) await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;
} }
if (newInvoice.id)
await Self.createPdf(ctx, newInvoice.id);
return newInvoice;
}; };
async function isInvoiceable(clientId, options) { async function isInvoiceable(clientId, options) {

View File

@ -1,3 +1,4 @@
const UserError = require('vn-loopback/util/user-error');
const fs = require('fs-extra'); const fs = require('fs-extra');
const got = require('got'); const got = require('got');
const path = require('path'); const path = require('path');

View File

@ -43,8 +43,6 @@ module.exports = Self => {
Self.globalInvoicing = async(ctx, options) => { Self.globalInvoicing = async(ctx, options) => {
const args = ctx.args; const args = ctx.args;
const invoicesIds = [];
const failedClients = [];
let tx; let tx;
const myOptions = {}; const myOptions = {};
@ -57,6 +55,8 @@ module.exports = Self => {
myOptions.transaction = tx; myOptions.transaction = tx;
} }
const invoicesIds = [];
const failedClients = [];
let query; let query;
try { try {
query = ` query = `
@ -155,16 +155,16 @@ module.exports = Self => {
await notifyFailures(ctx, failedClients, myOptions); await notifyFailures(ctx, failedClients, myOptions);
if (tx) await tx.commit(); if (tx) await tx.commit();
// Print invoices PDF
for (let invoiceId of invoicesIds)
await Self.createPdf(ctx, invoiceId);
return invoicesIds;
} catch (e) { } catch (e) {
if (tx) await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;
} }
// Print invoices PDF
for (let invoiceId of invoicesIds)
await Self.createPdf(ctx, invoiceId);
return invoicesIds;
}; };
async function getNegativeBase(options) { async function getNegativeBase(options) {

View File

@ -112,8 +112,6 @@ module.exports = Self => {
return {'it.workerFk': value}; return {'it.workerFk': value};
case 'origin': case 'origin':
return {'ori.code': value}; return {'ori.code': value};
case 'niche':
return {'ip.code': value};
case 'intrastat': case 'intrastat':
return {'intr.description': value}; return {'intr.description': value};
} }
@ -148,8 +146,7 @@ module.exports = Self => {
ic.name AS category, ic.name AS category,
intr.description AS intrastat, intr.description AS intrastat,
b.grouping, b.grouping,
b.packing, b.packing
ip.code AS niche, @visibleCalc
FROM item i FROM item i
LEFT JOIN itemType it ON it.id = i.typeFk LEFT JOIN itemType it ON it.id = i.typeFk
LEFT JOIN itemCategory ic ON ic.id = it.categoryFk LEFT JOIN itemCategory ic ON ic.id = it.categoryFk
@ -159,8 +156,7 @@ module.exports = Self => {
LEFT JOIN producer pr ON pr.id = i.producerFk LEFT JOIN producer pr ON pr.id = i.producerFk
LEFT JOIN origin ori ON ori.id = i.originFk LEFT JOIN origin ori ON ori.id = i.originFk
LEFT JOIN cache.last_buy lb ON lb.item_id = i.id AND lb.warehouse_id = it.warehouseFk LEFT JOIN cache.last_buy lb ON lb.item_id = i.id AND lb.warehouse_id = it.warehouseFk
LEFT JOIN vn.buy b ON b.id = lb.buy_id LEFT JOIN vn.buy b ON b.id = lb.buy_id`
LEFT JOIN itemPlacement ip ON ip.itemFk = i.id AND ip.warehouseFk = it.warehouseFk`
); );
if (ctx.args.tags) { if (ctx.args.tags) {

View File

@ -92,19 +92,11 @@ module.exports = Self => {
}; };
promises.push(models.ItemBotanical.find(filter, myOptions)); promises.push(models.ItemBotanical.find(filter, myOptions));
// Niches
filter = {
where: {itemFk: id},
include: {relation: 'warehouse'}
};
promises.push(models.ItemNiche.find(filter, myOptions));
let res = await Promise.all(promises); let res = await Promise.all(promises);
summary.item = res[0]; summary.item = res[0];
summary.tags = res[1]; summary.tags = res[1];
[summary.botanical] = res[2]; [summary.botanical] = res[2];
summary.niches = res[3];
const userConfig = await models.UserConfig.getUserConfig(ctx, myOptions); const userConfig = await models.UserConfig.getUserConfig(ctx, myOptions);

View File

@ -1,7 +1,7 @@
const models = require('vn-loopback/server/server').models; const models = require('vn-loopback/server/server').models;
describe('item getSummary()', () => { describe('item getSummary()', () => {
it('should return summary with item, tags, botanical, niches, available and visible defined ', async() => { it('should return summary with item, tags, botanical, available and visible defined ', async() => {
const tx = await models.Item.beginTransaction({}); const tx = await models.Item.beginTransaction({});
const options = {transaction: tx}; const options = {transaction: tx};
@ -14,7 +14,6 @@ describe('item getSummary()', () => {
expect(keys).toContain('item'); expect(keys).toContain('item');
expect(keys).toContain('tags'); expect(keys).toContain('tags');
expect(keys).toContain('botanical'); expect(keys).toContain('botanical');
expect(keys).toContain('niches');
expect(keys).toContain('available'); expect(keys).toContain('available');
expect(keys).toContain('visible'); expect(keys).toContain('visible');

View File

@ -26,9 +26,6 @@
"ItemLog": { "ItemLog": {
"dataSource": "vn" "dataSource": "vn"
}, },
"ItemNiche": {
"dataSource": "vn"
},
"ItemPlacement": { "ItemPlacement": {
"dataSource": "vn" "dataSource": "vn"
}, },

View File

@ -1,9 +0,0 @@
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.rewriteDbError(function(err) {
if (err.code === 'ER_DUP_ENTRY')
return new UserError(`The warehouse can't be repeated`);
return err;
});
};

View File

@ -1,42 +0,0 @@
{
"name": "ItemNiche",
"base": "Loggable",
"log": {
"model": "ItemLog",
"relation": "item",
"showField": "code"
},
"options": {
"mysql": {
"table": "itemPlacement"
}
},
"properties": {
"id": {
"type": "Number",
"id": 1,
"description": "Identifier"
},
"warehouseFk": {
"type": "Number",
"description": "Identifier"
},
"code": {
"type": "String",
"required": true
}
},
"relations": {
"item": {
"type": "belongsTo",
"model": "Item",
"foreignKey": "itemFk"
},
"warehouse": {
"type": "belongsTo",
"model": "Warehouse",
"foreignKey": "warehouseFk",
"required": true
}
}
}

View File

@ -196,21 +196,18 @@
"model": "ItemTaxCountry", "model": "ItemTaxCountry",
"foreignKey": "itemFk" "foreignKey": "itemFk"
}, },
"itemNiche": {
"type": "hasMany",
"model": "ItemNiche",
"foreignKey": "itemFk"
},
"packaging": { "packaging": {
"type": "hasOne", "type": "hasOne",
"model": "Packaging", "model": "Packaging",
"foreignKey": "itemFk" "foreignKey": "itemFk"
} }
}, },
"scope": { "scopes": {
"where": { "withName": {
"name": { "where": {
"neq": "" "name": {
"neq": ""
}
} }
} }
} }

View File

@ -51,7 +51,7 @@
class="dense" class="dense"
ng-if="!price.itemFk" ng-if="!price.itemFk"
vn-focus vn-focus
url="Items" url="Items/withName"
ng-model="price.itemFk" ng-model="price.itemFk"
show-field="name" show-field="name"
value-field="id" value-field="id"

View File

@ -16,7 +16,6 @@ import './log';
import './request'; import './request';
import './request-search-panel'; import './request-search-panel';
import './last-entries'; import './last-entries';
import './niche';
import './botanical'; import './botanical';
import './barcode'; import './barcode';
import './summary'; import './summary';

View File

@ -18,7 +18,6 @@
<vn-th field="name">Description</vn-th> <vn-th field="name">Description</vn-th>
<vn-th field="stems" shrink>Stems</vn-th> <vn-th field="stems" shrink>Stems</vn-th>
<vn-th field="size" shrink>Size</vn-th> <vn-th field="size" shrink>Size</vn-th>
<vn-th field="niche" shrink>Niche</vn-th>
<vn-th field="typeFk" shrink>Type</vn-th> <vn-th field="typeFk" shrink>Type</vn-th>
<vn-th field="category" shrink>Category</vn-th> <vn-th field="category" shrink>Category</vn-th>
<vn-th field="intrastat" shrink>Intrastat</vn-th> <vn-th field="intrastat" shrink>Intrastat</vn-th>
@ -63,7 +62,6 @@
</vn-td> </vn-td>
<vn-td shrink>{{::item.stems}}</vn-td> <vn-td shrink>{{::item.stems}}</vn-td>
<vn-td shrink>{{::item.size}}</vn-td> <vn-td shrink>{{::item.size}}</vn-td>
<vn-td shrink>{{::item.niche}}</vn-td>
<vn-td shrink title="{{::item.typeName}}"> <vn-td shrink title="{{::item.typeName}}">
{{::item.typeName}} {{::item.typeName}}
</vn-td> </vn-td>

View File

@ -23,8 +23,6 @@ class Controller extends Section {
return {'b.packing': value}; return {'b.packing': value};
case 'origin': case 'origin':
return {'ori.code': value}; return {'ori.code': value};
case 'niche':
return {'ip.code': value};
case 'typeFk': case 'typeFk':
return {'i.typeFk': value}; return {'i.typeFk': value};
case 'intrastat': case 'intrastat':

View File

@ -30,8 +30,6 @@ New species: Nueva especie
New genus: Nuevo genus New genus: Nuevo genus
Add tag: Añadir etiqueta Add tag: Añadir etiqueta
Remove tag: Quitar etiqueta Remove tag: Quitar etiqueta
Add niche: Añadir nicho
Remove niche: Quitar nicho
Add barcode: Añadir código de barras Add barcode: Añadir código de barras
Remove barcode: Quitar código de barras Remove barcode: Quitar código de barras
Buyer: Comprador Buyer: Comprador
@ -56,7 +54,6 @@ Summary: Vista previa
Basic data: Datos básicos Basic data: Datos básicos
Tax: IVA Tax: IVA
History: Historial History: Historial
Niches: Nichos
Botanical: Botánico Botanical: Botánico
Barcodes: Códigos de barras Barcodes: Códigos de barras
Diary: Histórico Diary: Histórico

View File

@ -1,72 +0,0 @@
<vn-crud-model
vn-id="model"
url="ItemNiches"
fields="['id', 'itemFk', 'warehouseFk', 'code']"
link="{itemFk: $ctrl.$params.id}"
data="niches"
auto-load="true">
</vn-crud-model>
<vn-watcher
vn-id="watcher"
data="niches"
form="form">
</vn-watcher>
<vn-crud-model
auto-load="true"
url="Warehouses"
data="warehouses"
order="name"
vn-id="warehouse-model">
</vn-crud-model>
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
<vn-card class="vn-pa-lg">
<vn-horizontal ng-repeat="niche in niches track by $index">
<vn-autocomplete vn-one vn-focus
data="warehouses"
label="Warehouse"
show-field="name"
value-field="id"
ng-model="niche.warehouseFk"
vn-acl="buyer,replenisher">
</vn-autocomplete>
<vn-textfield
vn-three
label="Code"
ng-model="niche.code"
rule="ItemNiche"
vn-acl="buyer,replenisher">
</vn-textfield>
<vn-none>
<vn-icon-button
vn-acl="buyer,replenisher"
pointer
vn-tooltip="Remove niche"
icon="delete"
ng-click="model.remove($index)">
</vn-icon-button>
</vn-none>
</vn-horizontal>
<vn-one>
<vn-icon-button
vn-acl="buyer, replenisher"
vn-tooltip="Add niche"
vn-bind="+"
icon="add_circle"
ng-click="model.insert()">
</vn-icon-button>
</vn-one>
</vn-card>
<vn-button-bar>
<vn-submit
disabled="!watcher.dataChanged()"
label="Save">
</vn-submit>
<!-- # #2680 Undo changes button bugs -->
<!-- <vn-button
class="cancel"
label="Undo changes"
disabled="!watcher.dataChanged()"
ng-click="watcher.loadOriginalData()">
</vn-button> -->
</vn-button-bar>
</form>

View File

@ -1,17 +0,0 @@
import ngModule from '../module';
import Section from 'salix/components/section';
export default class Controller extends Section {
onSubmit() {
this.$.watcher.check();
this.$.model.save().then(() => {
this.$.watcher.notifySaved();
this.$.watcher.updateOriginalData();
});
}
}
ngModule.vnComponent('vnItemNiche', {
template: require('./index.html'),
controller: Controller
});

View File

@ -15,7 +15,6 @@
{"state": "item.card.basicData", "icon": "settings"}, {"state": "item.card.basicData", "icon": "settings"},
{"state": "item.card.tags", "icon": "icon-tags"}, {"state": "item.card.tags", "icon": "icon-tags"},
{"state": "item.card.tax", "icon": "icon-tax"}, {"state": "item.card.tax", "icon": "icon-tax"},
{"state": "item.card.niche", "icon": "place"},
{"state": "item.card.botanical", "icon": "local_florist"}, {"state": "item.card.botanical", "icon": "local_florist"},
{"state": "item.card.itemBarcode", "icon": "icon-barcode"}, {"state": "item.card.itemBarcode", "icon": "icon-barcode"},
{"state": "item.card.diary", "icon": "icon-transaction"}, {"state": "item.card.diary", "icon": "icon-transaction"},
@ -79,16 +78,6 @@
"description": "Tax", "description": "Tax",
"acl": ["administrative","buyer"] "acl": ["administrative","buyer"]
}, },
{
"url" : "/niche",
"state": "item.card.niche",
"component": "vn-item-niche",
"description": "Niches",
"params": {
"item": "$ctrl.item"
},
"acl": ["buyer","replenisher"]
},
{ {
"url" : "/botanical", "url" : "/botanical",
"state": "item.card.botanical", "state": "item.card.botanical",

View File

@ -138,24 +138,6 @@
value="{{tax.taxClass.description}}"> value="{{tax.taxClass.description}}">
</vn-label-value> </vn-label-value>
</vn-one> </vn-one>
<vn-one name="niche">
<h4 ng-show="$ctrl.isBuyer || $ctrl.isReplenisher">
<a
ui-sref="item.card.niche({id:$ctrl.item.id})"
target="_self">
<span translate vn-tooltip="Go to">Niche</span>
</a>
</h4>
<h4
translate
ng-show="!$ctrl.isBuyer && !$ctrl.isReplenisher">
Niche
</h4>
<vn-label-value label="{{niche.warehouse.name}}"
ng-repeat="niche in $ctrl.summary.niches"
value="{{niche.code}}">
</vn-label-value>
</vn-one>
<vn-one name="botanical"> <vn-one name="botanical">
<h4 ng-show="$ctrl.isBuyer"> <h4 ng-show="$ctrl.isBuyer">
<a <a

View File

@ -1,4 +1,3 @@
Niche: Nichos
Barcode: Códigos de barras Barcode: Códigos de barras
Other data: Otros datos Other data: Otros datos
Go to the item: Ir al artículo Go to the item: Ir al artículo

View File

@ -264,38 +264,33 @@ module.exports = Self => {
FROM tmp.filter f FROM tmp.filter f
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id`); LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id`);
if (args.problems != undefined && (!args.from && !args.to)) const hasProblems = args.problems;
if (hasProblems != undefined && (!args.from && !args.to))
throw new UserError('Choose a date range or days forward'); throw new UserError('Choose a date range or days forward');
let condition; let problemsFilter;
let hasProblem; if (hasProblems === true) {
let range; problemsFilter = {or: [
let hasWhere; {'tp.isFreezed': true},
switch (args.problems) { {'tp.risk': {gt: 0}},
case true: {'tp.hasTicketRequest': true},
condition = `or`; {'tp.hasComponentLack': true},
hasProblem = true; {'tp.isTaxDataChecked': false},
range = 0; {'tp.isAvailable': false}
hasWhere = true; ]};
break; } else if (hasProblems === false) {
problemsFilter = {and: [
case false: {'tp.isFreezed': false},
condition = `and`; {'tp.risk': 0},
hasProblem = null; {'tp.hasTicketRequest': false},
range = null; {'tp.hasComponentLack': false},
hasWhere = true; {'tp.isTaxDataChecked': true},
break; {'tp.isAvailable': true}
]};
} }
let problems = {[condition]: [ if (problemsFilter)
{'tp.isFreezed': hasProblem}, stmt.merge(conn.makeWhere(problemsFilter));
{'tp.risk': hasProblem},
{'tp.hasTicketRequest': hasProblem},
{'tp.isAvailable': range}
]};
if (hasWhere)
stmt.merge(conn.makeWhere(problems));
stmt.merge(conn.makeOrderBy(filter.order)); stmt.merge(conn.makeOrderBy(filter.order));
stmt.merge(conn.makeLimit(filter)); stmt.merge(conn.makeLimit(filter));

View File

@ -23,7 +23,7 @@ describe('SalesMonitor salesFilter()', () => {
const filter = {}; const filter = {};
const result = await app.models.SalesMonitor.salesFilter(ctx, filter); const result = await app.models.SalesMonitor.salesFilter(ctx, filter);
expect(result.length).toEqual(4); expect(result.length).toEqual(9);
}); });
it('should return the tickets matching the problems on false', async() => { it('should return the tickets matching the problems on false', async() => {
@ -41,7 +41,7 @@ describe('SalesMonitor salesFilter()', () => {
const filter = {}; const filter = {};
const result = await app.models.SalesMonitor.salesFilter(ctx, filter); const result = await app.models.SalesMonitor.salesFilter(ctx, filter);
expect(result.length).toEqual(6); expect(result.length).toEqual(0);
}); });
it('should return the tickets matching the problems on null', async() => { it('should return the tickets matching the problems on null', async() => {
@ -103,4 +103,40 @@ describe('SalesMonitor salesFilter()', () => {
expect(result.length).toEqual(4); expect(result.length).toEqual(4);
}); });
it('should return the tickets sorted by problems descendant', async() => {
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
yesterday.setHours(0, 0, 0, 0);
const today = new Date();
today.setHours(23, 59, 59, 59);
const ctx = {req: {accessToken: {userId: 18}}, args: {}};
const filter = {order: 'totalProblems DESC'};
const result = await app.models.SalesMonitor.salesFilter(ctx, filter);
const firstTicket = result.shift();
const secondTicket = result.shift();
expect(firstTicket.totalProblems).toEqual(3);
expect(secondTicket.totalProblems).toEqual(2);
});
it('should return the tickets sorted by problems ascendant', async() => {
const yesterday = new Date();
yesterday.setDate(yesterday.getDate() - 1);
yesterday.setHours(0, 0, 0, 0);
const today = new Date();
today.setHours(23, 59, 59, 59);
const ctx = {req: {accessToken: {userId: 18}}, args: {}};
const filter = {order: 'totalProblems ASC'};
const result = await app.models.SalesMonitor.salesFilter(ctx, filter);
const firstTicket = result.shift();
const secondTicket = result.shift();
expect(firstTicket.totalProblems).toEqual(null);
expect(secondTicket.totalProblems).toEqual(null);
});
}); });

View File

@ -5,4 +5,5 @@ Search tickets: Buscar tickets
Delete selected elements: Eliminar los elementos seleccionados Delete selected elements: Eliminar los elementos seleccionados
All the selected elements will be deleted. Are you sure you want to continue?: Todos los elementos seleccionados serán eliminados. ¿Seguro que quieres continuar? All the selected elements will be deleted. Are you sure you want to continue?: Todos los elementos seleccionados serán eliminados. ¿Seguro que quieres continuar?
Component lack: Faltan componentes Component lack: Faltan componentes
Minimize/Maximize: Minimizar/Maximizar Minimize/Maximize: Minimizar/Maximizar
Problems: Problemas

View File

@ -33,7 +33,7 @@
<vn-table model="model"> <vn-table model="model">
<vn-thead> <vn-thead>
<vn-tr> <vn-tr>
<vn-th class="icon-field"></vn-th> <vn-th field="totalProblems" menu-enabled="false">Problems</vn-th>
<vn-th field="nickname">Client</vn-th> <vn-th field="nickname">Client</vn-th>
<vn-th field="salesPersonFk" class="expendable" shrink>Salesperson</vn-th> <vn-th field="salesPersonFk" class="expendable" shrink>Salesperson</vn-th>
<vn-th field="shipped" shrink-date>Date</vn-th> <vn-th field="shipped" shrink-date>Date</vn-th>
@ -77,6 +77,7 @@
</vn-icon> </vn-icon>
<vn-icon <vn-icon
ng-show="::ticket.risk" ng-show="::ticket.risk"
ng-class="::{'highRisk': ticket.hasHighRisk}"
title="{{::$ctrl.$t('Risk')}}: {{ticket.risk}}" title="{{::$ctrl.$t('Risk')}}: {{ticket.risk}}"
class="bright" class="bright"
icon="icon-risk"> icon="icon-risk">
@ -135,7 +136,7 @@
</span> </span>
</vn-td> </vn-td>
<vn-td shrink> <vn-td shrink>
<span class="chip {{$ctrl.totalPriceColor(ticket)}}"> <span class="chip {{::$ctrl.totalPriceColor(ticket)}}">
{{::(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}} {{::(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}}
</span> </span>
</vn-td> </vn-td>

View File

@ -32,4 +32,8 @@ vn-monitor-sales-tickets {
vn-tbody a[ng-repeat].vn-tr:focus { vn-tbody a[ng-repeat].vn-tr:focus {
background-color: $color-primary-light background-color: $color-primary-light
} }
.highRisk i {
color: $color-alert
}
} }

View File

@ -35,7 +35,8 @@
search-function="$search" search-function="$search"
show-field="nickname" show-field="nickname"
value-field="id" value-field="id"
ng-model="$ctrl.order.addressFk"> ng-model="$ctrl.order.addressFk"
on-change="$ctrl.getAvailableAgencies()">
<tpl-item>{{::nickname}}</tpl-item> <tpl-item>{{::nickname}}</tpl-item>
</vn-autocomplete> </vn-autocomplete>
</vn-horizontal> </vn-horizontal>
@ -43,17 +44,16 @@
<vn-date-picker <vn-date-picker
vn-one vn-one
label="Landed" label="Landed"
ng-model="$ctrl.order.landed"> ng-model="$ctrl.order.landed"
on-change="$ctrl.getAvailableAgencies()">
</vn-date-picker> </vn-date-picker>
<vn-autocomplete <vn-autocomplete
vn-one disabled="!$ctrl.order.addressFk || !$ctrl.order.landed"
url="AgencyModes" data="$ctrl._availableAgencies"
label="Agency" label="Agency"
search-function="{or: [{id: $search}, {name: {like: '%'+$search+'%'}}]}" show-field="agencyMode"
show-field="name" value-field="agencyModeFk"
value-field="id"
ng-model="$ctrl.order.agencyModeFk"> ng-model="$ctrl.order.agencyModeFk">
<tpl-item>{{::id}}: {{::name}}</tpl-item>
</vn-autocomplete> </vn-autocomplete>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>

View File

@ -20,6 +20,32 @@ class Controller extends Section {
} }
}); });
} }
set order(value = {}) {
this._order = value;
const agencyModeFk = value.agencyModeFk;
this.getAvailableAgencies();
this._order.agencyModeFk = agencyModeFk;
}
get order() {
return this._order;
}
getAvailableAgencies() {
const order = this.order;
order.agencyModeFk = null;
const params = {
addressFk: order.addressFk,
landed: order.landed
};
if (params.landed && params.addressFk) {
this.$http.get(`Agencies/landsThatDay`, {params})
.then(res => this._availableAgencies = res.data);
}
}
} }
ngModule.vnComponent('vnOrderBasicData', { ngModule.vnComponent('vnOrderBasicData', {

View File

@ -3,13 +3,15 @@ import './index.js';
describe('Order', () => { describe('Order', () => {
describe('Component vnOrderBasicData', () => { describe('Component vnOrderBasicData', () => {
let $httpBackend; let $httpBackend;
let $httpParamSerializer;
let controller; let controller;
let $scope; let $scope;
beforeEach(ngModule('order')); beforeEach(ngModule('order'));
beforeEach(inject(($compile, _$httpBackend_, $rootScope) => { beforeEach(inject(($compile, _$httpBackend_, $rootScope, _$httpParamSerializer_) => {
$httpBackend = _$httpBackend_; $httpBackend = _$httpBackend_;
$httpParamSerializer = _$httpParamSerializer_;
$scope = $rootScope.$new(); $scope = $rootScope.$new();
$httpBackend.whenRoute('GET', 'Addresses') $httpBackend.whenRoute('GET', 'Addresses')
@ -30,10 +32,35 @@ describe('Order', () => {
describe('constructor()', () => { describe('constructor()', () => {
it('should update the address after the client changes', async() => { it('should update the address after the client changes', async() => {
controller.selection = {id: 2, defaultAddressFk: 2}; const addressId = 999;
const id = 444;
controller.selection = {id: id, defaultAddressFk: addressId};
$scope.$digest(); $scope.$digest();
expect(controller.order.addressFk).toEqual(2); expect(controller.order.addressFk).toEqual(addressId);
});
});
describe('getAvailableAgencies()', () => {
it('should set agencyModeFk to null and get the available agencies if the order has landed and client', async() => {
controller.order.agencyModeFk = 999;
controller.order.addressFk = 999;
controller.order.landed = new Date();
const expectedAgencies = [{id: 1}, {id: 2}];
const paramsObj = {
addressFk: controller.order.addressFk,
landed: controller.order.landed
};
const serializedParams = $httpParamSerializer(paramsObj);
$httpBackend.expect('GET', `Agencies/landsThatDay?${serializedParams}`).respond(expectedAgencies);
controller.getAvailableAgencies();
$httpBackend.flush();
expect(controller.order.agencyModeFk).toBeDefined();
expect(controller._availableAgencies).toEqual(expectedAgencies);
}); });
}); });
}); });

View File

@ -37,7 +37,7 @@ class Controller extends Component {
}; };
filter = encodeURIComponent(JSON.stringify(filter)); filter = encodeURIComponent(JSON.stringify(filter));
let query = `Clients?filter=${filter}`; let query = `Clients?filter=${filter}`;
this.$http.get(query).then(res=> { this.$http.get(query).then(res => {
if (res.data) { if (res.data) {
let client = res.data[0]; let client = res.data[0];
let defaultAddress = client.defaultAddress; let defaultAddress = client.defaultAddress;

View File

@ -107,7 +107,12 @@ module.exports = Self => {
arg: 'alertLevel', arg: 'alertLevel',
type: 'number', type: 'number',
description: `The alert level of the tickets` description: `The alert level of the tickets`
} },
{
arg: 'collectionFk',
type: 'number',
description: `The collection id filter`
},
], ],
returns: { returns: {
type: ['object'], type: ['object'],
@ -269,6 +274,15 @@ module.exports = Self => {
}); });
} }
if (args.collectionFk) {
stmt.merge({
sql: `
JOIN collection cll ON cll.id = ?
JOIN ticketCollection tc ON tc.collectionFk = cll.id AND tc.ticketFk = t.id`,
params: [args.collectionFk]
});
}
stmt.merge(conn.makeWhere(filter.where)); stmt.merge(conn.makeWhere(filter.where));
stmts.push(stmt); stmts.push(stmt);

View File

@ -38,6 +38,8 @@ module.exports = function(Self) {
myOptions.transaction = tx; myOptions.transaction = tx;
} }
let serial;
let invoiceId;
try { try {
const tickets = await models.Ticket.find({ const tickets = await models.Ticket.find({
where: { where: {
@ -68,7 +70,7 @@ module.exports = function(Self) {
companyId, companyId,
'R' 'R'
], myOptions); ], myOptions);
const serial = result.serial; serial = result.serial;
await Self.rawSql(` await Self.rawSql(`
DROP TEMPORARY TABLE IF EXISTS ticketToInvoice; DROP TEMPORARY TABLE IF EXISTS ticketToInvoice;
@ -83,7 +85,7 @@ module.exports = function(Self) {
const [resultInvoice] = await Self.rawSql('SELECT @invoiceId id', [], myOptions); const [resultInvoice] = await Self.rawSql('SELECT @invoiceId id', [], myOptions);
const invoiceId = resultInvoice.id; invoiceId = resultInvoice.id;
for (let ticket of tickets) { for (let ticket of tickets) {
const ticketInvoice = await models.Ticket.findById(ticket.id, { const ticketInvoice = await models.Ticket.findById(ticket.id, {
@ -104,14 +106,14 @@ module.exports = function(Self) {
await Self.rawSql('CALL invoiceOutBooking(?)', [invoiceId], myOptions); await Self.rawSql('CALL invoiceOutBooking(?)', [invoiceId], myOptions);
if (tx) await tx.commit(); if (tx) await tx.commit();
if (serial != 'R' && invoiceId)
await models.InvoiceOut.createPdf(ctx, invoiceId);
return {invoiceFk: invoiceId, serial: serial};
} catch (e) { } catch (e) {
if (tx) await tx.rollback(); if (tx) await tx.rollback();
throw e; throw e;
} }
if (serial != 'R' && invoiceId)
await models.InvoiceOut.createPdf(ctx, invoiceId);
return {invoiceFk: invoiceId, serial: serial};
}; };
}; };

View File

@ -202,4 +202,23 @@ describe('ticket filter()', () => {
throw e; throw e;
} }
}); });
it('should return the tickets belonging to the collection id 1', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
const options = {transaction: tx};
const ctx = {req: {accessToken: {userId: 18}}, args: {collectionFk: 1}};
const filter = {};
const result = await models.Ticket.filter(ctx, filter, options);
expect(result.length).toEqual(2);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
}); });

View File

@ -134,7 +134,7 @@
</span> </span>
<vn-autocomplete ng-if="!sale.id" class="dense" <vn-autocomplete ng-if="!sale.id" class="dense"
vn-focus vn-focus
url="Items" url="Items/withName"
ng-model="sale.itemFk" ng-model="sale.itemFk"
show-field="name" show-field="name"
value-field="id" value-field="id"

View File

@ -679,5 +679,21 @@ describe('Ticket', () => {
expect(controller.$.model.refresh).toHaveBeenCalledWith(); expect(controller.$.model.refresh).toHaveBeenCalledWith();
}); });
}); });
describe('itemSearchFunc()', () => {
it('should return the filter by id property for an input of a number', () => {
const itemId = 1;
const result = controller.itemSearchFunc(itemId);
expect(result).toEqual({id: itemId});
});
it('should return the filter by bank property for an input of an string', () => {
const itemName = 'Bow';
const result = controller.itemSearchFunc(itemName);
expect(result).toEqual({name: {like: '%' + itemName + '%'}});
});
});
}); });
}); });

View File

@ -110,6 +110,11 @@
ng-model="filter.provinceFk" ng-model="filter.provinceFk"
url="Provinces"> url="Provinces">
</vn-autocomplete> </vn-autocomplete>
<vn-textfield
vn-one
label="Collection"
ng-model="filter.collectionFk">
</vn-textfield>
</vn-horizontal> </vn-horizontal>
<vn-horizontal class="vn-px-lg"> <vn-horizontal class="vn-px-lg">
<vn-check <vn-check

View File

@ -18,4 +18,5 @@ DELIVERED: Servido
ON_PREPARATION: En preparacion ON_PREPARATION: En preparacion
PACKED: Encajado PACKED: Encajado
Cannot choose a range of dates and days onward at the same time: No se puede selecionar un rango de fechas y días en adelante a la vez Cannot choose a range of dates and days onward at the same time: No se puede selecionar un rango de fechas y días en adelante a la vez
Or: O Or: O
Collection: Colección

View File

@ -4,27 +4,30 @@ module.exports = Self => {
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [{
arg: 'thermographId', arg: 'thermographId',
type: 'String', type: 'string',
description: 'The thermograph id', description: 'The thermograph id',
required: true required: true
}, { },
{
arg: 'model', arg: 'model',
type: 'String', type: 'string',
description: 'The thermograph model', description: 'The thermograph model',
required: true required: true
}, { },
arg: 'temperature', {
type: 'String', arg: 'temperatureFk',
type: 'string',
description: 'The thermograph temperature', description: 'The thermograph temperature',
required: true required: true
}, { },
{
arg: 'warehouseId', arg: 'warehouseId',
type: 'Number', type: 'number',
description: 'The warehouse id', description: 'The warehouse id',
required: true required: true
}], }],
returns: { returns: {
type: 'Object', type: 'object',
root: true root: true
}, },
http: { http: {
@ -33,27 +36,35 @@ module.exports = Self => {
} }
}); });
Self.createThermograph = async(thermographId, model, temperature, warehouseId) => { Self.createThermograph = async(thermographId, model, temperatureFk, warehouseId, options) => {
const models = Self.app.models; const models = Self.app.models;
const tx = await Self.beginTransaction({}); let tx;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try { try {
const options = {transaction: tx};
const thermograph = await models.Thermograph.create({ const thermograph = await models.Thermograph.create({
id: thermographId, id: thermographId,
model: model model: model
}, options); }, myOptions);
await Self.rawSql(` await Self.rawSql(`
INSERT INTO travelThermograph(thermographFk, warehouseFk, temperature, created) INSERT INTO travelThermograph(thermographFk, warehouseFk, temperatureFk, created)
VALUES (?, ?,?, NOW()) VALUES (?, ?, ?, NOW())
`, [thermograph.id, warehouseId, temperature], options); `, [thermograph.id, warehouseId, temperatureFk], myOptions);
await tx.commit(); if (tx) await tx.commit();
return thermograph; return thermograph;
} catch (err) { } catch (err) {
await tx.rollback(); if (tx) await tx.rollback();
throw err; throw err;
} }
}; };

View File

@ -1,47 +1,51 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Termograph createThermograph()', () => { describe('Termograph createThermograph()', () => {
const models = app.models;
const thermographId = '99999-1'; const thermographId = '99999-1';
const model = 'DISPOSABLE'; const model = 'DISPOSABLE';
const temperature = 'COOL'; const temperatureFk = 'COOL';
const warehouseId = 1; const warehouseId = 1;
let createdThermograph;
afterAll(async done => { it(`should create a thermograph which is saved in both thermograph and travelThermograph`, async() => {
let travelThermograpToDelete = await models.TravelThermograph.findOne({where: {thermographFk: createdThermograph.id}}); const tx = await models.Thermograph.beginTransaction({});
let thermograpToDelete = await models.Thermograph.findById(createdThermograph.id);
await travelThermograpToDelete.destroy(); try {
await thermograpToDelete.destroy(); const options = {transaction: tx};
done(); const createdThermograph = await models.Thermograph.createThermograph(thermographId, model, temperatureFk, warehouseId, options);
expect(createdThermograph.id).toEqual(thermographId);
expect(createdThermograph.model).toEqual(model);
const createdTravelThermograpth = await models.TravelThermograph.findOne({where: {thermographFk: thermographId}}, options);
expect(createdTravelThermograpth.warehouseFk).toEqual(warehouseId);
expect(createdTravelThermograpth.temperatureFk).toEqual(temperatureFk);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
it(`should be able to create just once a thermograph which is saved in both thermograph and travelThermograph`, async() => { it(`should throw an error when trying to created repeated thermograph`, async() => {
let createdTravelThermograpth = await models.TravelThermograph.findOne({where: {thermographFk: thermographId}}); const tx = await models.Thermograph.beginTransaction({});
expect(createdTravelThermograpth).toBeNull();
createdThermograph = await models.Thermograph.createThermograph(thermographId, model, temperature, warehouseId);
expect(createdThermograph.id).toEqual(thermographId);
expect(createdThermograph.model).toEqual(model);
createdTravelThermograpth = await models.TravelThermograph.findOne({where: {thermographFk: thermographId}});
expect(createdTravelThermograpth.warehouseFk).toEqual(warehouseId);
expect(createdTravelThermograpth.temperature).toEqual(temperature);
let error; let error;
try { try {
await models.Thermograph.createThermograph(thermographId, model, temperature, warehouseId); const options = {transaction: tx};
await models.Thermograph.createThermograph(thermographId, model, temperatureFk, warehouseId, options);
await models.Thermograph.createThermograph(thermographId, model, temperatureFk, warehouseId, options);
await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback();
error = e; error = e;
} }
expect(error).toBeDefined();
expect(error.message).toBe('This thermograph id already exists'); expect(error.message).toBe('This thermograph id already exists');
}); });
}); });

View File

@ -1,18 +0,0 @@
module.exports = Self => {
Self.remoteMethod('getThermographTemperatures', {
description: 'Gets the thermograph temperatures',
accessType: 'READ',
returns: {
type: ['String'],
root: true
},
http: {
path: `/getThermographTemperatures`,
verb: 'GET'
}
});
Self.getThermographTemperatures = async() => {
return Self.getEnumValues('temperature');
};
};

View File

@ -14,7 +14,7 @@ module.exports = Self => {
http: {source: 'path'} http: {source: 'path'}
}], }],
returns: { returns: {
type: 'Object', type: 'object',
description: 'The new cloned travel id', description: 'The new cloned travel id',
root: true, root: true,
}, },
@ -48,46 +48,51 @@ module.exports = Self => {
let stmts = []; let stmts = [];
let stmt; let stmt;
try { stmt = new ParameterizedSQL(
stmt = new ParameterizedSQL( `CALL travel_cloneWithEntries(?, ?, ?, ?, ?, ?, ?, @vTravelFk)`, [
`CALL travel_cloneWithEntries(?, ?, ?, ?, ?, ?, @vTravelFk)`, [ id,
id, started, ended, travel.warehouseOutFk, travel.warehouseInFk, travel.ref]); started,
ended,
travel.warehouseOutFk,
travel.warehouseInFk,
travel.ref,
travel.agencyFk
]
);
stmts.push(stmt);
const newTravelIndex = stmts.push('SELECT @vTravelFk AS id') - 1;
stmts.push(stmt); const sql = ParameterizedSQL.join(stmts, ';');
const index = stmts.push('SELECT @vTravelFk AS id') - 1; const result = await conn.executeStmt(sql);
const [lastInsert] = result[newTravelIndex];
const sql = ParameterizedSQL.join(stmts, ';'); if (!lastInsert.id)
const result = await conn.executeStmt(sql); throw new UserError('Unable to clone this travel');
const [lastInsert] = result[index];
const newTravel = await Self.findById(lastInsert.id, {
fields: [
'id',
'shipped',
'landed',
'warehouseInFk',
'warehouseOutFk',
'agencyFk',
'ref'
]
});
const oldProperties = await loggable.translateValues(Self, travel); const newTravel = await Self.findById(lastInsert.id, {
const newProperties = await loggable.translateValues(Self, newTravel); fields: [
await models.TravelLog.create({ 'id',
originFk: newTravel.id, 'shipped',
userFk: userId, 'landed',
action: 'insert', 'warehouseInFk',
changedModel: 'Travel', 'warehouseOutFk',
changedModelId: newTravel.id, 'agencyFk',
oldInstance: oldProperties, 'ref'
newInstance: newProperties ]
}); });
return newTravel.id; const oldProperties = await loggable.translateValues(Self, travel);
} catch (error) { const newProperties = await loggable.translateValues(Self, newTravel);
if (error.code === 'ER_DUP_ENTRY') await models.TravelLog.create({
throw new UserError('A travel with this data already exists'); originFk: newTravel.id,
throw error; userFk: userId,
} action: 'insert',
changedModel: 'Travel',
changedModelId: newTravel.id,
oldInstance: oldProperties,
newInstance: newProperties
});
return newTravel.id;
}; };
}; };

View File

@ -6,44 +6,51 @@ module.exports = Self => {
accessType: 'WRITE', accessType: 'WRITE',
accepts: [{ accepts: [{
arg: 'id', arg: 'id',
type: 'Number', type: 'number',
description: 'The travel id', description: 'The travel id',
http: {source: 'path'} http: {source: 'path'}
}, { },
{
arg: 'thermographId', arg: 'thermographId',
type: 'String', type: 'string',
description: 'The thermograph id', description: 'The thermograph id',
required: true required: true
}, { },
{
arg: 'state', arg: 'state',
type: 'String', type: 'string',
required: true required: true
}, { },
{
arg: 'warehouseId', arg: 'warehouseId',
type: 'Number', type: 'number',
description: 'The warehouse id', description: 'The warehouse id',
required: true required: true
}, { },
{
arg: 'companyId', arg: 'companyId',
type: 'Number', type: 'number',
description: 'The company id', description: 'The company id',
required: true required: true
}, { },
{
arg: 'dmsTypeId', arg: 'dmsTypeId',
type: 'Number', type: 'number',
description: 'The dms type id', description: 'The dms type id',
required: true required: true
}, { },
{
arg: 'reference', arg: 'reference',
type: 'String', type: 'string',
required: true required: true
}, { },
{
arg: 'description', arg: 'description',
type: 'String', type: 'string',
required: true required: true
}], }],
returns: { returns: {
type: 'Object', type: 'object',
root: true root: true
}, },
http: { http: {
@ -52,36 +59,44 @@ module.exports = Self => {
} }
}); });
Self.createThermograph = async(ctx, id, thermographId, state) => { Self.createThermograph = async(ctx, id, thermographId, state, options) => {
const models = Self.app.models; const models = Self.app.models;
const tx = await Self.beginTransaction({}); let tx;
const myOptions = {};
if (typeof options == 'object')
Object.assign(myOptions, options);
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try { try {
const options = {transaction: tx};
const travelThermograph = await models.TravelThermograph.findOne({ const travelThermograph = await models.TravelThermograph.findOne({
where: { where: {
thermographFk: thermographId, thermographFk: thermographId,
travelFk: null travelFk: null
} }
}, options); }, myOptions);
if (!travelThermograph) if (!travelThermograph)
throw new UserError('No valid travel thermograph found'); throw new UserError('No valid travel thermograph found');
const uploadedFiles = await models.Dms.uploadFile(ctx, options); const uploadedFiles = await models.Dms.uploadFile(ctx, myOptions);
const firstDms = uploadedFiles[0]; const firstDms = uploadedFiles[0];
await travelThermograph.updateAttributes({ await travelThermograph.updateAttributes({
dmsFk: firstDms.id, dmsFk: firstDms.id,
travelFk: id, travelFk: id,
result: state result: state
}, options); }, myOptions);
await tx.commit(); if (tx) await tx.commit();
return travelThermograph; return travelThermograph;
} catch (err) { } catch (err) {
await tx.rollback(); if (tx) await tx.rollback();
throw err; throw err;
} }
}; };

View File

@ -1,50 +1,50 @@
const app = require('vn-loopback/server/server'); const models = require('vn-loopback/server/server').models;
describe('Travel createThermograph()', () => { describe('Travel createThermograph()', () => {
const models = app.models;
const travelId = 3; const travelId = 3;
const currentUserId = 1102; const currentUserId = 1102;
const thermographId = '138350-0'; const thermographId = '138350-0';
const ctx = {req: {accessToken: {userId: currentUserId}}, args: {dmsTypeId: 1}}; const ctx = {req: {accessToken: {userId: currentUserId}}, args: {dmsTypeId: 1}};
let travelThermographBefore;
afterAll(async done => {
await app.models.TravelThermograph.rawSql(`
UPDATE travelThermograph
SET travelFk = NULL, dmsFk = NULL
WHERE id = ?`, [travelThermographBefore.id]);
done();
});
it(`should set the travelFk and dmsFk properties to the travel thermograph`, async() => { it(`should set the travelFk and dmsFk properties to the travel thermograph`, async() => {
spyOn(app.models.Dms, 'uploadFile').and.returnValue([{id: 5}]); const tx = await models.Travel.beginTransaction({});
travelThermographBefore = await models.TravelThermograph.findOne({ try {
where: { const options = {transaction: tx};
thermographFk: thermographId,
travelFk: null
}
});
await models.Travel.createThermograph(ctx, travelId, thermographId); spyOn(models.Dms, 'uploadFile').and.returnValue([{id: 5}]);
const travelThermographAfter = await models.TravelThermograph.findOne({ travelThermographBefore = await models.TravelThermograph.findOne({
where: { where: {
thermographFk: thermographId, thermographFk: thermographId,
travelFk: travelId travelFk: null
} }
}); }, options);
expect(app.models.Dms.uploadFile).toHaveBeenCalledWith(ctx, jasmine.any(Object)); await models.Travel.createThermograph(ctx, travelId, thermographId, options);
expect(travelThermographBefore).toBeDefined(); const travelThermographAfter = await models.TravelThermograph.findOne({
expect(travelThermographBefore.thermographFk).toEqual(thermographId); where: {
expect(travelThermographBefore.travelFk).toBeNull(); thermographFk: thermographId,
expect(travelThermographAfter).toBeDefined(); travelFk: travelId
}
}, options);
expect(travelThermographAfter.thermographFk).toEqual(thermographId); expect(models.Dms.uploadFile).toHaveBeenCalledWith(ctx, jasmine.any(Object));
expect(travelThermographAfter.travelFk).toEqual(travelId);
expect(travelThermographAfter.dmsFk).toEqual(5); expect(travelThermographBefore).toBeDefined();
expect(travelThermographBefore.thermographFk).toEqual(thermographId);
expect(travelThermographBefore.travelFk).toBeNull();
expect(travelThermographAfter).toBeDefined();
expect(travelThermographAfter.thermographFk).toEqual(thermographId);
expect(travelThermographAfter.travelFk).toEqual(travelId);
expect(travelThermographAfter.dmsFk).toEqual(5);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
}); });
}); });

View File

@ -13,5 +13,8 @@
}, },
"TravelThermograph": { "TravelThermograph": {
"dataSource": "vn" "dataSource": "vn"
},
"Temperature": {
"dataSource": "vn"
} }
} }

View File

@ -0,0 +1,30 @@
{
"name": "Temperature",
"base": "VnModel",
"options": {
"mysql": {
"table": "temperature"
}
},
"properties": {
"code": {
"type": "string",
"id": true,
"description": "Identifier",
"required": true
},
"name": {
"type": "string",
"required": true
},
"description": {
"type": "string"
}
},
"acls": [{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}]
}

View File

@ -1,4 +0,0 @@
module.exports = Self => {
require('../methods/travel-thermograph/getThermographTemperatures')(Self);
};

View File

@ -13,22 +13,25 @@
}, },
"properties": { "properties": {
"id": { "id": {
"type": "Number", "type": "number",
"description": "Identifier", "description": "Identifier",
"id": true "id": true
}, },
"created": { "created": {
"type": "Date" "type": "date"
}, },
"temperature": { "temperature": {
"type": "String", "type": "string"
},
"temperatureFk": {
"type": "string",
"required": true "required": true
}, },
"result": { "result": {
"type": "String" "type": "string"
}, },
"warehouseFk": { "warehouseFk": {
"type": "Number", "type": "number",
"required": true "required": true
} }
}, },

Some files were not shown because too many files have changed in this diff Show More