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',
accessType: 'READ',
returns: {
type: 'Object',
type: 'object',
root: true
},
http: {

View File

@ -1,9 +1,9 @@
const app = require('vn-loopback/server/server');
const models = require('vn-loopback/server/server').models;
describe('getCollection()', () => {
it('return list of collection', async() => {
describe('ticket getCollection()', () => {
it('should return a list of collections', async() => {
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[0].collectionFk).toEqual(1);

View File

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

View File

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

View File

@ -22,6 +22,9 @@
},
"code": {
"type": "string"
},
"isAutoConciliated": {
"type": "boolean"
}
},
"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": {
"id": {
"type": "Number",
"type": "number",
"id": true,
"description": "Identifier"
},
@ -24,6 +24,11 @@
"model": "Country",
"foreignKey": "countryFk"
},
"autonomy": {
"type": "belongsTo",
"model": "Autonomy",
"foreignKey": "autonomyFk"
},
"warehouse": {
"type": "belongsTo",
"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),
(2, 20);
INSERT INTO `vn`.`province`(`id`, `name`, `countryFk`, `warehouseFk`)
INSERT INTO `vn`.`autonomy`(`id`, `name`, `countryFk`)
VALUES
(1, 'Province one', 1, NULL),
(2, 'Province two', 1, NULL),
(3, 'Province three', 1, NULL),
(4, 'Province four', 2, NULL),
(5, 'Province five', 13, NULL);
(1, 'Autonomy one', 1),
(2, 'Autonomy two', 1),
(3, 'Autonomy three', 2),
(4, 'Autonomy four', 13);
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`)
VALUES
@ -269,20 +277,20 @@ INSERT INTO `vn`.`contactChannel`(`id`, `name`)
(4, 'GCN Channel'),
(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
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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),
(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);
(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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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`)
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');
INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`)
INSERT INTO `vn`.`collection`(`id`, `workerFk`, `stateFk`, `created`)
VALUES
(1, 1106, 5),
(2, 1106, 14);
(1, 1106, 5, DATE_ADD(CURDATE(),INTERVAL +1 DAY)),
(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`)
VALUES
@ -1927,7 +1940,7 @@ INSERT INTO `vn`.`zoneIncluded` (`zoneFk`, `geoFk`, `isIncluded`)
(8, 4, 0),
(8, 5, 0),
(8, 1, 1),
(10, 10, 1);
(10, 14, 1);
INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `type`, `dated`)
VALUES
@ -2212,6 +2225,11 @@ INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `week
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`)
VALUES
('TMM190901395', 'TEMPMATE'),
@ -2219,7 +2237,8 @@ INSERT INTO `vn`.`thermograph`(`id`, `model`)
('TZ1905012010', '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
('TMM190901395', CURDATE(), 1, 1, 'WARM', '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),
(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
(1, '19ES0028013A481523', 1, CURDATE(), CURDATE(), CURDATE(), CURDATE(), 1, 11276.95, 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),
(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),
(8, '19ES00280132025489', 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),
(10, '19ES00280132025489', 10, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 4631.45, 442);
(8, '19ES00280132025490', 8, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 3618.52, 442),
(9, '19ES00280132025491', 9, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), CURDATE(), CURDATE(), CURDATE(), 2, 7126.23, 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`)
VALUES
@ -2336,8 +2355,8 @@ INSERT INTO `vn`.`duaInvoiceIn`(`id`, `duaFk`, `invoiceInFk`)
(4, 4, 4),
(5, 5, 5),
(6, 6, 6),
(7, 7, 7),
(8, 8, 8),
(7, 7, 7),
(8, 8, 8),
(9, 9, 9),
(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"]',
addCity: 'vn-autocomplete[ng-model="$ctrl.location.townFk"] vn-icon-button[icon="add_circle"]',
newProvinceName: 'vn-textfield[ng-model="$ctrl.province.name"]',
newProvinceAutonomy: 'vn-autocomplete[ng-model="$ctrl.province.autonomyFk"]',
newCityName: 'vn-textfield[ng-model="$ctrl.city.name"]',
newCityProvince: 'vn-autocomplete[ng-model="$ctrl.city.provinceFk"]',
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"]',
province: 'vn-autocomplete[ng-model="$ctrl.client.provinceFk"]',
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"]',
email: 'vn-client-create vn-textfield[ng-model="$ctrl.client.email"]',
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',
stemsCheckbox: '.vn-popover.shown vn-horizontal:nth-child(2) > 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',
categoryCheckbox: '.vn-popover.shown vn-horizontal:nth-child(6) > 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]',
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: {
genus: 'vn-item-botanical vn-autocomplete[ng-model="$ctrl.botanical.genusFk"]',
species: 'vn-item-botanical vn-autocomplete[ng-model="$ctrl.botanical.specieFk"]',
@ -440,7 +428,6 @@ export default {
basicData: 'vn-item-summary [name="basicData"]',
vat: 'vn-item-summary [name="tax"]',
tags: 'vn-item-summary [name="tags"]',
niche: 'vn-item-summary [name="niche"]',
botanical: 'vn-item-summary [name="botanical"]',
barcode: 'vn-item-summary [name="barcode"]'
},
@ -1018,7 +1005,7 @@ export default {
newThermographId: 'vn-textfield[ng-model="$ctrl.newThermograph.thermographId"]',
newThermographModel: 'vn-autocomplete[ng-model="$ctrl.newThermograph.model"]',
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"]',
uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="icon-attach"]',
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.addProvince);
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);
const message = await page.waitForSnackbar();

View File

@ -40,13 +40,6 @@ describe('Item summary path', () => {
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() => {
await page.waitForTextInElement(selectors.itemSummary.botanical, 'Abelia');
const result = await page.waitToGetProperty(selectors.itemSummary.botanical, 'innerText');
@ -126,12 +119,6 @@ describe('Item summary path', () => {
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() => {
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.stemsCheckbox);
await page.waitToClick(selectors.itemsIndex.sizeCheckbox);
await page.waitToClick(selectors.itemsIndex.nicheCheckbox);
await page.waitToClick(selectors.itemsIndex.typeCheckbox);
await page.waitToClick(selectors.itemsIndex.categoryCheckbox);
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.stemsCheckbox);
await page.waitToClick(selectors.itemsIndex.sizeCheckbox);
await page.waitToClick(selectors.itemsIndex.nicheCheckbox);
await page.waitToClick(selectors.itemsIndex.typeCheckbox);
await page.waitToClick(selectors.itemsIndex.categoryCheckbox);
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() => {
await page.autocompleteSearch(selectors.orderBasicData.client, '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.waitToClick(selectors.orderBasicData.saveButton);
const message = await page.waitForSnackbar();
@ -96,7 +96,7 @@ describe('Order edit basic data path', () => {
const result = await page
.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() => {

View File

@ -119,7 +119,7 @@ describe('Travel descriptor path', () => {
await page.waitToClick(selectors.travelDescriptor.acceptClonation);
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() => {

View File

@ -32,7 +32,7 @@ describe('Travel thermograph path', () => {
await page.write(selectors.travelThermograph.newThermographId, thermographName);
await page.autocompleteSearch(selectors.travelThermograph.newThermographModel, 'TEMPMATE');
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);
});

View File

@ -239,9 +239,6 @@
.icon-mandatory:before {
content: "\e921";
}
.icon-niche:before {
content: "\e922";
}
.icon-no036:before {
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="&#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="&#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="&#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" />

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View File

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

View File

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

View File

@ -61,12 +61,28 @@ describe('Salix', () => {
});
describe('getImageUrl()', () => {
it('should return de url image', () => {
it('should return the url image', () => {
const url = $root.imagePath('user', '160x160', userId);
expect(url).toBeDefined();
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()', () => {
it('should extend rewriteDbError properties to any model passed', () => {
let exampleModel = app.models.ItemNiche;
const exampleModel = models.ItemTag;
expect(exampleModel.rewriteDbError).toBeDefined();
});
it('should handle a duplicated warehouse error', async() => {
let itemNiche = {itemFk: 1, warehouseFK: 1, code: 'A11'};
const tx = await models.Ticket.beginTransaction({});
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;
}).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",
"Amount cannot be zero": "Amount cannot be zero",
"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",
"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}}*",
@ -114,5 +114,6 @@
"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",
"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",
"Distance must be lesser than 1000": "La distancia debe ser inferior a 1000",
"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",
"Choose a date range or days forward": "Selecciona un rango de fechas o días en adelante",
"ORDER_ALREADY_CONFIRMED": "ORDER_ALREADY_CONFIRMED",

View File

@ -180,10 +180,10 @@ module.exports = Self => {
}
Self.observe('before save', async function(ctx) {
let changes = ctx.data || ctx.instance;
let orgData = ctx.currentInstance;
let finalState = getFinalState(ctx);
let payMethodWithIban = 4;
const changes = ctx.data || ctx.instance;
const orgData = ctx.currentInstance;
const finalState = getFinalState(ctx);
const payMethodWithIban = 4;
// Validate socialName format
const hasChanges = orgData && changes;
@ -204,14 +204,20 @@ module.exports = Self => {
changes.payMethodFk = 5; // Credit card
}
let payMethodFk = changes.payMethodFk || (orgData && orgData.payMethodFk);
let dueDay = changes.dueDay || (orgData && orgData.dueDay);
const payMethodFk = changes.payMethodFk || (orgData && orgData.payMethodFk);
const dueDay = changes.dueDay || (orgData && orgData.dueDay);
if (payMethodFk == payMethodWithIban && dueDay == 0)
changes.dueDay = 5;
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) {
await validateCreditChange(ctx, finalState);
let filter = {fields: ['id'], where: {userFk: ctx.options.accessToken.userId}};

View File

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

View File

@ -118,5 +118,21 @@ describe('Client', () => {
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-autocomplete
ng-model="$ctrl.client.transferorFk"
url="Clients/isActive"
url="Clients"
search-function="$ctrl.transferorSearchFunction($search)"
where="{id: {neq: $ctrl.client.id}}"
show-field="name"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,3 @@
const loggable = require('vn-loopback/util/log');
module.exports = Self => {
Self.remoteMethodCtx('clone', {
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) => {
const userId = ctx.req.accessToken.userId;
const models = Self.app.models;
let tx;
const myOptions = {};
@ -56,10 +52,11 @@ module.exports = Self => {
const issued = new Date(sourceInvoiceIn.issued);
issued.setMonth(issued.getMonth() + 1);
const clonedRef = sourceInvoiceIn.supplierRef + '(2)';
const clone = await models.InvoiceIn.create({
serial: sourceInvoiceIn.serial,
supplierRef: sourceInvoiceIn.supplierRef,
supplierRef: clonedRef,
supplierFk: sourceInvoiceIn.supplierFk,
issued: issued,
currencyFk: sourceInvoiceIn.currencyFk,

View File

@ -17,7 +17,7 @@ describe('invoiceIn clone()', () => {
try {
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);

View File

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

View File

@ -65,6 +65,7 @@ module.exports = Self => {
let clientId = args.clientFk;
let maxShipped = args.maxShipped;
let companyId;
let newInvoice;
let query;
try {
if (ticketId) {
@ -137,18 +138,18 @@ module.exports = Self => {
], 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 (newInvoice.id)
await Self.createPdf(ctx, newInvoice.id);
return newInvoice;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
if (newInvoice.id)
await Self.createPdf(ctx, newInvoice.id);
return newInvoice;
};
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 got = require('got');
const path = require('path');

View File

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

View File

@ -112,8 +112,6 @@ module.exports = Self => {
return {'it.workerFk': value};
case 'origin':
return {'ori.code': value};
case 'niche':
return {'ip.code': value};
case 'intrastat':
return {'intr.description': value};
}
@ -148,8 +146,7 @@ module.exports = Self => {
ic.name AS category,
intr.description AS intrastat,
b.grouping,
b.packing,
ip.code AS niche, @visibleCalc
b.packing
FROM item i
LEFT JOIN itemType it ON it.id = i.typeFk
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 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 vn.buy b ON b.id = lb.buy_id
LEFT JOIN itemPlacement ip ON ip.itemFk = i.id AND ip.warehouseFk = it.warehouseFk`
LEFT JOIN vn.buy b ON b.id = lb.buy_id`
);
if (ctx.args.tags) {

View File

@ -92,19 +92,11 @@ module.exports = Self => {
};
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);
summary.item = res[0];
summary.tags = res[1];
[summary.botanical] = res[2];
summary.niches = res[3];
const userConfig = await models.UserConfig.getUserConfig(ctx, myOptions);

View File

@ -1,7 +1,7 @@
const models = require('vn-loopback/server/server').models;
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 options = {transaction: tx};
@ -14,7 +14,6 @@ describe('item getSummary()', () => {
expect(keys).toContain('item');
expect(keys).toContain('tags');
expect(keys).toContain('botanical');
expect(keys).toContain('niches');
expect(keys).toContain('available');
expect(keys).toContain('visible');

View File

@ -26,9 +26,6 @@
"ItemLog": {
"dataSource": "vn"
},
"ItemNiche": {
"dataSource": "vn"
},
"ItemPlacement": {
"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",
"foreignKey": "itemFk"
},
"itemNiche": {
"type": "hasMany",
"model": "ItemNiche",
"foreignKey": "itemFk"
},
"packaging": {
"type": "hasOne",
"model": "Packaging",
"foreignKey": "itemFk"
}
},
"scope": {
"where": {
"name": {
"neq": ""
"scopes": {
"withName": {
"where": {
"name": {
"neq": ""
}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -30,8 +30,6 @@ New species: Nueva especie
New genus: Nuevo genus
Add tag: Añadir etiqueta
Remove tag: Quitar etiqueta
Add niche: Añadir nicho
Remove niche: Quitar nicho
Add barcode: Añadir código de barras
Remove barcode: Quitar código de barras
Buyer: Comprador
@ -56,7 +54,6 @@ Summary: Vista previa
Basic data: Datos básicos
Tax: IVA
History: Historial
Niches: Nichos
Botanical: Botánico
Barcodes: Códigos de barras
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.tags", "icon": "icon-tags"},
{"state": "item.card.tax", "icon": "icon-tax"},
{"state": "item.card.niche", "icon": "place"},
{"state": "item.card.botanical", "icon": "local_florist"},
{"state": "item.card.itemBarcode", "icon": "icon-barcode"},
{"state": "item.card.diary", "icon": "icon-transaction"},
@ -79,16 +78,6 @@
"description": "Tax",
"acl": ["administrative","buyer"]
},
{
"url" : "/niche",
"state": "item.card.niche",
"component": "vn-item-niche",
"description": "Niches",
"params": {
"item": "$ctrl.item"
},
"acl": ["buyer","replenisher"]
},
{
"url" : "/botanical",
"state": "item.card.botanical",

View File

@ -138,24 +138,6 @@
value="{{tax.taxClass.description}}">
</vn-label-value>
</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">
<h4 ng-show="$ctrl.isBuyer">
<a

View File

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

View File

@ -264,38 +264,33 @@ module.exports = Self => {
FROM tmp.filter f
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');
let condition;
let hasProblem;
let range;
let hasWhere;
switch (args.problems) {
case true:
condition = `or`;
hasProblem = true;
range = 0;
hasWhere = true;
break;
case false:
condition = `and`;
hasProblem = null;
range = null;
hasWhere = true;
break;
let problemsFilter;
if (hasProblems === true) {
problemsFilter = {or: [
{'tp.isFreezed': true},
{'tp.risk': {gt: 0}},
{'tp.hasTicketRequest': true},
{'tp.hasComponentLack': true},
{'tp.isTaxDataChecked': false},
{'tp.isAvailable': false}
]};
} else if (hasProblems === false) {
problemsFilter = {and: [
{'tp.isFreezed': false},
{'tp.risk': 0},
{'tp.hasTicketRequest': false},
{'tp.hasComponentLack': false},
{'tp.isTaxDataChecked': true},
{'tp.isAvailable': true}
]};
}
let problems = {[condition]: [
{'tp.isFreezed': hasProblem},
{'tp.risk': hasProblem},
{'tp.hasTicketRequest': hasProblem},
{'tp.isAvailable': range}
]};
if (hasWhere)
stmt.merge(conn.makeWhere(problems));
if (problemsFilter)
stmt.merge(conn.makeWhere(problemsFilter));
stmt.merge(conn.makeOrderBy(filter.order));
stmt.merge(conn.makeLimit(filter));

View File

@ -23,7 +23,7 @@ describe('SalesMonitor salesFilter()', () => {
const 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() => {
@ -41,7 +41,7 @@ describe('SalesMonitor salesFilter()', () => {
const 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() => {
@ -103,4 +103,40 @@ describe('SalesMonitor salesFilter()', () => {
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
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
Minimize/Maximize: Minimizar/Maximizar
Minimize/Maximize: Minimizar/Maximizar
Problems: Problemas

View File

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

View File

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

View File

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

View File

@ -3,13 +3,15 @@ import './index.js';
describe('Order', () => {
describe('Component vnOrderBasicData', () => {
let $httpBackend;
let $httpParamSerializer;
let controller;
let $scope;
beforeEach(ngModule('order'));
beforeEach(inject(($compile, _$httpBackend_, $rootScope) => {
beforeEach(inject(($compile, _$httpBackend_, $rootScope, _$httpParamSerializer_) => {
$httpBackend = _$httpBackend_;
$httpParamSerializer = _$httpParamSerializer_;
$scope = $rootScope.$new();
$httpBackend.whenRoute('GET', 'Addresses')
@ -30,10 +32,35 @@ describe('Order', () => {
describe('constructor()', () => {
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();
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));
let query = `Clients?filter=${filter}`;
this.$http.get(query).then(res=> {
this.$http.get(query).then(res => {
if (res.data) {
let client = res.data[0];
let defaultAddress = client.defaultAddress;

View File

@ -107,7 +107,12 @@ module.exports = Self => {
arg: 'alertLevel',
type: 'number',
description: `The alert level of the tickets`
}
},
{
arg: 'collectionFk',
type: 'number',
description: `The collection id filter`
},
],
returns: {
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));
stmts.push(stmt);

View File

@ -38,6 +38,8 @@ module.exports = function(Self) {
myOptions.transaction = tx;
}
let serial;
let invoiceId;
try {
const tickets = await models.Ticket.find({
where: {
@ -68,7 +70,7 @@ module.exports = function(Self) {
companyId,
'R'
], myOptions);
const serial = result.serial;
serial = result.serial;
await Self.rawSql(`
DROP TEMPORARY TABLE IF EXISTS ticketToInvoice;
@ -83,7 +85,7 @@ module.exports = function(Self) {
const [resultInvoice] = await Self.rawSql('SELECT @invoiceId id', [], myOptions);
const invoiceId = resultInvoice.id;
invoiceId = resultInvoice.id;
for (let ticket of tickets) {
const ticketInvoice = await models.Ticket.findById(ticket.id, {
@ -104,14 +106,14 @@ module.exports = function(Self) {
await Self.rawSql('CALL invoiceOutBooking(?)', [invoiceId], myOptions);
if (tx) await tx.commit();
if (serial != 'R' && invoiceId)
await models.InvoiceOut.createPdf(ctx, invoiceId);
return {invoiceFk: invoiceId, serial: serial};
} catch (e) {
if (tx) await tx.rollback();
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;
}
});
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>
<vn-autocomplete ng-if="!sale.id" class="dense"
vn-focus
url="Items"
url="Items/withName"
ng-model="sale.itemFk"
show-field="name"
value-field="id"

View File

@ -679,5 +679,21 @@ describe('Ticket', () => {
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"
url="Provinces">
</vn-autocomplete>
<vn-textfield
vn-one
label="Collection"
ng-model="filter.collectionFk">
</vn-textfield>
</vn-horizontal>
<vn-horizontal class="vn-px-lg">
<vn-check

View File

@ -18,4 +18,5 @@ DELIVERED: Servido
ON_PREPARATION: En preparacion
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
Or: O
Or: O
Collection: Colección

View File

@ -4,27 +4,30 @@ module.exports = Self => {
accessType: 'WRITE',
accepts: [{
arg: 'thermographId',
type: 'String',
type: 'string',
description: 'The thermograph id',
required: true
}, {
},
{
arg: 'model',
type: 'String',
type: 'string',
description: 'The thermograph model',
required: true
}, {
arg: 'temperature',
type: 'String',
},
{
arg: 'temperatureFk',
type: 'string',
description: 'The thermograph temperature',
required: true
}, {
},
{
arg: 'warehouseId',
type: 'Number',
type: 'number',
description: 'The warehouse id',
required: true
}],
returns: {
type: 'Object',
type: 'object',
root: true
},
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 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 {
const options = {transaction: tx};
const thermograph = await models.Thermograph.create({
id: thermographId,
model: model
}, options);
}, myOptions);
await Self.rawSql(`
INSERT INTO travelThermograph(thermographFk, warehouseFk, temperature, created)
VALUES (?, ?,?, NOW())
`, [thermograph.id, warehouseId, temperature], options);
INSERT INTO travelThermograph(thermographFk, warehouseFk, temperatureFk, created)
VALUES (?, ?, ?, NOW())
`, [thermograph.id, warehouseId, temperatureFk], myOptions);
await tx.commit();
if (tx) await tx.commit();
return thermograph;
} catch (err) {
await tx.rollback();
if (tx) await tx.rollback();
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()', () => {
const models = app.models;
const thermographId = '99999-1';
const model = 'DISPOSABLE';
const temperature = 'COOL';
const temperatureFk = 'COOL';
const warehouseId = 1;
let createdThermograph;
afterAll(async done => {
let travelThermograpToDelete = await models.TravelThermograph.findOne({where: {thermographFk: createdThermograph.id}});
let thermograpToDelete = await models.Thermograph.findById(createdThermograph.id);
it(`should create a thermograph which is saved in both thermograph and travelThermograph`, async() => {
const tx = await models.Thermograph.beginTransaction({});
await travelThermograpToDelete.destroy();
await thermograpToDelete.destroy();
try {
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() => {
let createdTravelThermograpth = await models.TravelThermograph.findOne({where: {thermographFk: thermographId}});
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);
it(`should throw an error when trying to created repeated thermograph`, async() => {
const tx = await models.Thermograph.beginTransaction({});
let error;
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) {
await tx.rollback();
error = e;
}
expect(error).toBeDefined();
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'}
}],
returns: {
type: 'Object',
type: 'object',
description: 'The new cloned travel id',
root: true,
},
@ -48,46 +48,51 @@ module.exports = Self => {
let stmts = [];
let stmt;
try {
stmt = new ParameterizedSQL(
`CALL travel_cloneWithEntries(?, ?, ?, ?, ?, ?, @vTravelFk)`, [
id, started, ended, travel.warehouseOutFk, travel.warehouseInFk, travel.ref]);
stmt = new ParameterizedSQL(
`CALL travel_cloneWithEntries(?, ?, ?, ?, ?, ?, ?, @vTravelFk)`, [
id,
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 index = stmts.push('SELECT @vTravelFk AS id') - 1;
const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql);
const [lastInsert] = result[newTravelIndex];
const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql);
const [lastInsert] = result[index];
const newTravel = await Self.findById(lastInsert.id, {
fields: [
'id',
'shipped',
'landed',
'warehouseInFk',
'warehouseOutFk',
'agencyFk',
'ref'
]
});
if (!lastInsert.id)
throw new UserError('Unable to clone this travel');
const oldProperties = await loggable.translateValues(Self, travel);
const newProperties = await loggable.translateValues(Self, newTravel);
await models.TravelLog.create({
originFk: newTravel.id,
userFk: userId,
action: 'insert',
changedModel: 'Travel',
changedModelId: newTravel.id,
oldInstance: oldProperties,
newInstance: newProperties
});
const newTravel = await Self.findById(lastInsert.id, {
fields: [
'id',
'shipped',
'landed',
'warehouseInFk',
'warehouseOutFk',
'agencyFk',
'ref'
]
});
return newTravel.id;
} catch (error) {
if (error.code === 'ER_DUP_ENTRY')
throw new UserError('A travel with this data already exists');
throw error;
}
const oldProperties = await loggable.translateValues(Self, travel);
const newProperties = await loggable.translateValues(Self, newTravel);
await models.TravelLog.create({
originFk: newTravel.id,
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',
accepts: [{
arg: 'id',
type: 'Number',
type: 'number',
description: 'The travel id',
http: {source: 'path'}
}, {
},
{
arg: 'thermographId',
type: 'String',
type: 'string',
description: 'The thermograph id',
required: true
}, {
},
{
arg: 'state',
type: 'String',
type: 'string',
required: true
}, {
},
{
arg: 'warehouseId',
type: 'Number',
type: 'number',
description: 'The warehouse id',
required: true
}, {
},
{
arg: 'companyId',
type: 'Number',
type: 'number',
description: 'The company id',
required: true
}, {
},
{
arg: 'dmsTypeId',
type: 'Number',
type: 'number',
description: 'The dms type id',
required: true
}, {
},
{
arg: 'reference',
type: 'String',
type: 'string',
required: true
}, {
},
{
arg: 'description',
type: 'String',
type: 'string',
required: true
}],
returns: {
type: 'Object',
type: 'object',
root: true
},
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 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 {
const options = {transaction: tx};
const travelThermograph = await models.TravelThermograph.findOne({
where: {
thermographFk: thermographId,
travelFk: null
}
}, options);
}, myOptions);
if (!travelThermograph)
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];
await travelThermograph.updateAttributes({
dmsFk: firstDms.id,
travelFk: id,
result: state
}, options);
}, myOptions);
await tx.commit();
if (tx) await tx.commit();
return travelThermograph;
} catch (err) {
await tx.rollback();
if (tx) await tx.rollback();
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()', () => {
const models = app.models;
const travelId = 3;
const currentUserId = 1102;
const thermographId = '138350-0';
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() => {
spyOn(app.models.Dms, 'uploadFile').and.returnValue([{id: 5}]);
const tx = await models.Travel.beginTransaction({});
travelThermographBefore = await models.TravelThermograph.findOne({
where: {
thermographFk: thermographId,
travelFk: null
}
});
try {
const options = {transaction: tx};
await models.Travel.createThermograph(ctx, travelId, thermographId);
spyOn(models.Dms, 'uploadFile').and.returnValue([{id: 5}]);
const travelThermographAfter = await models.TravelThermograph.findOne({
where: {
thermographFk: thermographId,
travelFk: travelId
}
});
travelThermographBefore = await models.TravelThermograph.findOne({
where: {
thermographFk: thermographId,
travelFk: null
}
}, options);
expect(app.models.Dms.uploadFile).toHaveBeenCalledWith(ctx, jasmine.any(Object));
await models.Travel.createThermograph(ctx, travelId, thermographId, options);
expect(travelThermographBefore).toBeDefined();
expect(travelThermographBefore.thermographFk).toEqual(thermographId);
expect(travelThermographBefore.travelFk).toBeNull();
expect(travelThermographAfter).toBeDefined();
const travelThermographAfter = await models.TravelThermograph.findOne({
where: {
thermographFk: thermographId,
travelFk: travelId
}
}, options);
expect(travelThermographAfter.thermographFk).toEqual(thermographId);
expect(travelThermographAfter.travelFk).toEqual(travelId);
expect(travelThermographAfter.dmsFk).toEqual(5);
expect(models.Dms.uploadFile).toHaveBeenCalledWith(ctx, jasmine.any(Object));
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": {
"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": {
"id": {
"type": "Number",
"type": "number",
"description": "Identifier",
"id": true
},
"created": {
"type": "Date"
"type": "date"
},
"temperature": {
"type": "String",
"type": "string"
},
"temperatureFk": {
"type": "string",
"required": true
},
"result": {
"type": "String"
"type": "string"
},
"warehouseFk": {
"type": "Number",
"type": "number",
"required": true
}
},

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